在Laravel Eloquent ORM中处理Mysql空间数据类型

21
如何在Eloquent ORM中处理MySQL的空间数据类型?这包括如何创建迁移,插入空间数据和执行空间查询。如果没有实际解决方案,是否有任何变通方法?

8
也许这个链接可以帮助你:http://www.codetutorial.io/geo-spatial-mysql-laravel-5/ 该链接介绍了如何在Laravel 5中使用MySQL进行地理空间数据处理。请注意,本文仅提供参考,具体实现取决于你的具体需求。 - haakym
@haakym提供的链接非常有帮助。Laravel本身不支持这些类型(请参见https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Schema/Blueprint.php),但您始终可以在迁移中运行DB:statement()甚至扩展Blueprint类并添加自己的方法以支持这些数据类型。个人而言,我使用DB语句方法。 - jhmilan
2个回答

13

我之前实施的一种解决方法是在模型上有一个纬度和经度字段,具有以下验证(参见Validator类):

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

魔法出现在模型的启动方法中,该方法设置了空间点字段的正确值:

/**
 * 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所说,您可以始终使用Schema :: create和DB :: statement方法来自定义迁移。

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)' );

现在你可以在Innodb引擎上的Spatial数据类型上创建索引了。(从Mysql 5.7开始) - Mehrdad Shokri
geoToPoint() 函数从哪里来的? - dbr
1
geoToPoint仅是一个辅助函数,用于连接纬度和经度,返回以下内容: $latitude . " " . $longitude; - Emilio Borraz

6

可以使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接