2015-06-06 1 views
16

Как обрабатывать пространственные типы данных mysql в красноречивой ORM ?, Это включает в себя создание миграции, вставку пространственных данных и выполнение пространственных запросов. Если фактических решений не существует, есть ли какие-либо обходные пути?Обработка Mysql Пространственные типы данных в Laravel 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() в ваши миграции или даже расширили класс Blueprint и добавили собственные методы поддержки этих типов данных. Лично я использую подход БД. – 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. (от 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 
Смежные вопросы