2015-06-06 6 views
16

Come gestire i tipi di dati spaziali mysql in ELM eloquente ?, Ciò include come creare la migrazione, inserire i dati spaziali ed eseguire query spaziali. Se non esistono soluzioni effettive, esistono soluzioni alternative?Gestione dei tipi di dati spaziali Mysql in Laravel Eloquent ORM

+8

forse questo potrebbe aiutarti: http://www.codetutorial.io/geo -spatial-mysql-laravel-5/ – haakym

+0

Il link fornito da @haakym è molto utile. Laravel non supporta questi tipi in modo nativo (guarda qui https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Schema/Blueprint.php) ma puoi sempre eseguire un DB: statement() in le tue migrazioni o addirittura, ha esteso la classe Blueprint e aggiungi i tuoi metodi per supportare questi tipi di dati. Personalmente utilizzo l'approccio dell'istruzione DB. – jhmilan

risposta

9

Una soluzione Ho implementato qualche tempo fa è quello di avere una latitudine e longitudine campi del modello con le seguenti convalide (vedi Validator class):

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

La magia arriva sul boot method del modello, che imposta il valore corretto del campo di punto spaziale:

/** 
* 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); 
     } 

    }); 
} 

a proposito di migrazioni, come @jhmilan dice che si può sempre utilizzare lo schema :: creare e DB :: dichiarazione metodi per personalizzare la migrazione.

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

ora è possibile creare l'indice sul tipo di dati Spatial sul motore Innodb. (da Mysql 5.7) – Mehrdad

+0

Da dove proviene 'geoToPoint()'? – dbr

+0

geoToPoint è solo una funzione di supporto per concatenare la latitudine e la longitudine, che restituisce quanto segue: latitudine $. "". $ Longitudine; –

0

E 'disponibile da usare https://github.com/grimzy/laravel-mysql-spatial

è possibile utilizzare:

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', 
    ]; 
} 

allora si sono in grado di eseguire le query sul campo 'location'.

al modello di negozio è possibile utilizzare:

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

per il recupero di un modello che dovrebbe utilizzare:

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