2015-06-06 123 views
16

如何在雄辯的ORM中處理mysql空間數據類型?這包括如何創建遷移,插入空間數據和執行空間查詢。如果沒有實際的解決方案存在,是否有任何解決方法?處理Laravel中的Mysql空間數據類型Eloquent ORM

+8

也許這可以幫助你:http://www.codetutorial.io/geo -spatial-mysql-laravel-5/ – haakym

+0

@haakym提供的鏈接非常有用。 Laravel本身不支持這些類型(請看這裏https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Schema/Blueprint.php),但你總是可以運行一個DB:statement()in您的遷移或甚至擴展Blueprint類並添加您自己的方法來支持這些數據類型。我個人使用DB語句方法。 – jhmilan

回答

9

我已經在不久前實施的解決方法是對具有下列驗證模型中的緯度和經度字段(見Validator class):

$rules = array('latitude' => 'required|numeric|between:-90,90', 
          'longitude'=>'required|numeric|between:-180,180',) 

魔術自帶的模型,對boot method這設置空間點字段的正確值:

/** 
* Boot method 
* @return void 
*/ 
public static function boot(){ 
    parent::boot(); 
    static::creating(function($eloquentModel){ 

     if(isset($eloquentModel->latitude, $eloquentModel->longitude)){ 
      $point = $eloquentModel->geoToPoint($eloquentModel->latitude, $eloquentModel->longitude); 
      $eloquentModel->setAttribute('location', DB::raw("GeomFromText('POINT(" . $point . ")')")); 
     } 

    }); 

    static::updated(function($eloquentModel){ 

     if(isset($eloquentModel->latitude, $eloquentModel->longitude)){ 
      $point = $eloquentModel->geoToPoint($eloquentModel->latitude, $eloquentModel->longitude); 
      DB::statement("UPDATE " . $eloquentModel->getTable() . " SET location = GeomFromText('POINT(" . $point . ")') WHERE id = ". $eloquentModel->id); 
     } 

    }); 
} 

關於遷移,就像@jhmilan說,你可以隨時使用模式:創建和DB ::聲明方法來定製遷移。

Schema::create('locations', function($table){ 
     $table->engine = "MYISAM"; 
     $table->increments('id')->unsigned(); 
     $table->decimal('latitude', 10, 8); 
     $table->decimal('longitude', 11, 8); 
     $table->timestamps(); 
    }); 

    /*Espatial Column*/ 
    DB::statement('ALTER TABLE locations ADD location POINT NOT NULL'); 
    /*Espatial index (MYISAM only)*/ 
    DB::statement('ALTER TABLE locations ADD SPATIAL INDEX index_point(location)'); 
+0

您現在可以在Innodb引擎上的Spatial數據類型上創建索引。 (來自Mysql 5.7) – Mehrdad

+0

'geoToPoint()'從哪裏來? – dbr

+0

geoToPoint只是連接經度和緯度的幫助函數,返回以下內容: $緯度。 「」。 $經度; –

0

它可以使用https://github.com/grimzy/laravel-mysql-spatial

你可以使用:

namespace App; 

use Illuminate\Database\Eloquent\Model; 
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait; 

/** 
* @property \Grimzy\LaravelMysqlSpatial\Types\Point $location 
*/ 
class Place extends Model 
{ 
    use SpatialTrait; 

    protected $fillable = [ 
     'name', 
    ]; 

    protected $spatialFields = [ 
     'location', 
    ]; 
} 

那麼你就能夠在 '位置' 字段運行查詢。

存儲模型,你可以使用:

$place1 = new Place(); 
$place1->name = 'Empire State Building'; 
$place1->location = new Point(40.7484404, -73.9878441); 
$place1->save(); 

到檢索模型,你應該使用:

$place2 = Place::first(); 
$lat = $place2->location->getLat(); // 40.7484404 
$lng = $place2->location->getLng(); // -73.9878441