Handling Mysql Spatial datatypes in Laravel Eloquent ORM

后端 未结 2 1573
醉酒成梦
醉酒成梦 2021-02-12 12:49

How to handle mysql spatial datatypes in eloquent ORM?, This include how to create migration, insert spatial data and performing spatial query\'s. If there is not actual solutio

相关标签:
2条回答
  • 2021-02-12 13:26

    It is available to use https://github.com/grimzy/laravel-mysql-spatial

    you may use:

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

    then you are able to run queries on the 'location' field.

    to store model you may use:

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

    to retrieving a model you should use:

    $place2 = Place::first();
    $lat = $place2->location->getLat(); // 40.7484404
    $lng = $place2->location->getLng(); // -73.9878441
    
    0 讨论(0)
  • 2021-02-12 13:46

    A workaround I have implemented a while ago is to have a latitude and longitude fields on the model with the following validations (see Validator class):

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

    The magic comes on the boot method of the model, which sets the correct value of the spatial point field:

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

    About migrations, like @jhmilan says you can always use the Schema::create and DB::statement methods to customize the migration.

    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 讨论(0)
提交回复
热议问题