matanyadaev/laravel-eloquent-spatial

4.3.2 2024-08-07 20:53 UTC

README

Latest Version on Packagist Tests Static code analysis Lint Total Downloads

此 Laravel 包允许您轻松处理空间数据类型和函数。

支持的数据库

  • MySQL 5.7/8
  • MariaDB 10
  • Postgres 12/13/14/15/16 与 PostGIS 3.4

入门

安装包

您可以通过 composer 安装此包

composer require matanyadaev/laravel-eloquent-spatial

设置第一个模型

  1. 首先,运行以下命令生成一个新模型和迁移文件:

    php artisan make:model {modelName} --migration
  2. 接下来,在迁移文件中添加一些空间列。例如,要创建一个 "places" 表

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    
    class CreatePlacesTable extends Migration
    {
        public function up(): void
        {
            Schema::create('places', static function (Blueprint $table) {
                $table->id();
                $table->string('name')->unique();
                $table->geometry('location', subtype: 'point')->nullable();
                $table->geometry('area', subtype: 'polygon')->nullable();
                $table->timestamps();
            });
        }
    
        public function down(): void
        {
            Schema::dropIfExists('places');
        }
    }
  3. 运行迁移

    php artisan migrate
  4. 在您的新模型中,填充 $fillable$casts 数组,并使用 HasSpatial 特性

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    use MatanYadaev\EloquentSpatial\Objects\Point;
    use MatanYadaev\EloquentSpatial\Objects\Polygon;
    use MatanYadaev\EloquentSpatial\Traits\HasSpatial;
    
    /**
     * @property Point $location
     * @property Polygon $area
     */
    class Place extends Model
    {
        use HasSpatial;
    
        protected $fillable = [
            'name',
            'location',
            'area',
        ];
    
        protected $casts = [
            'location' => Point::class,
            'area' => Polygon::class,
        ];
    }

与空间数据交互

设置好模型后,您现在可以创建和访问空间数据。以下是一个示例

use App\Models\Place;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Enums\Srid;

// Create new records

$londonEye = Place::create([
    'name' => 'London Eye',
    'location' => new Point(51.5032973, -0.1217424),
]);

$whiteHouse = Place::create([
    'name' => 'White House',
    'location' => new Point(38.8976763, -77.0365298, Srid::WGS84->value), // with SRID
]);

$vaticanCity = Place::create([
    'name' => 'Vatican City',
    'area' => new Polygon([
        new LineString([
              new Point(12.455363273620605, 41.90746728266806),
              new Point(12.450309991836548, 41.906636872349075),
              new Point(12.445632219314575, 41.90197359839437),
              new Point(12.447413206100464, 41.90027269624499),
              new Point(12.457906007766724, 41.90000118654431),
              new Point(12.458517551422117, 41.90281205461268),
              new Point(12.457584142684937, 41.903107507989986),
              new Point(12.457734346389769, 41.905918239316286),
              new Point(12.45572805404663, 41.90637337450963),
              new Point(12.455363273620605, 41.90746728266806),
        ]),
    ]),
])

// Access the data

echo $londonEye->location->latitude; // 51.5032973
echo $londonEye->location->longitude; // -0.1217424

echo $whiteHouse->location->srid; // 4326

echo $vacationCity->area->toJson(); // {"type":"Polygon","coordinates":[[[41.90746728266806,12.455363273620605],[41.906636872349075,12.450309991836548],[41.90197359839437,12.445632219314575],[41.90027269624499,12.447413206100464],[41.90000118654431,12.457906007766724],[41.90281205461268,12.458517551422117],[41.903107507989986,12.457584142684937],[41.905918239316286,12.457734346389769],[41.90637337450963,12.45572805404663],[41.90746728266806,12.455363273620605]]]}

进一步阅读

有关 API 的更全面文档,请参阅API 页面。

扩展

通过宏扩展 Geometry 类

您可以通过宏向 Geometry 类添加新方法。

以下是如何在服务提供者的 boot 方法中注册宏的示例

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Geometry::macro('getName', function (): string {
            /** @var Geometry $this */
            return class_basename($this);
        });
    }
}

在您的代码中使用此方法

$londonEyePoint = new Point(51.5032973, -0.1217424);

echo $londonEyePoint->getName(); // Point

通过自定义几何类扩展

您可以通过创建自定义几何类并添加功能来扩展几何类。您还可以重写现有方法,尽管这不建议,因为这可能导致意外行为。

  1. 创建一个扩展基本几何类的自定义几何类。
use MatanYadaev\EloquentSpatial\Objects\Point;

class ExtendedPoint extends Point
{
    public function toCustomArray(): array
    {
        return 'coordinates' => [
            'latitude' => $this->latitude,
            'longitude' => $this->longitude
        ]
    }
}
  1. 在服务提供者文件中更新几何类映射。
use App\ValueObjects\ExtendedPoint;
use Illuminate\Support\ServiceProvider;
use MatanYadaev\EloquentSpatial\EloquentSpatial;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        EloquentSpatial::usePoint(ExtendedPoint::class);
    }
}
  1. 更新您的模型以在 $casts 属性或 casts() 方法中使用自定义几何类。
use App\ValueObjects\ExtendedPoint;
use Illuminate\Database\Eloquent\Model;
use MatanYadaev\EloquentSpatial\Traits\HasSpatial;

class Place extends Model
{
    use HasSpatial;
    
    protected $casts = [
        'coordinates' => ExtendedPoint::class,
    ];
    
    // Or:

    protected function casts(): array
    {
        return [
            'coordinates' => ExtendedPoint::class,
        ];
    }
}
  1. 在您的代码中使用自定义几何类。
use App\Models\Location;
use App\ValueObjects\ExtendedPoint;

$place = Place::create([
    'name' => 'London Eye',
    'coordinates' => new ExtendedPoint(51.5032973, -0.1217424),
]);

echo $place->coordinates->toCustomArray(); // ['longitude' => -0.1217424, 'latitude' => 51.5032973]

开发

以下是一些有用的开发命令

  • 运行测试:composer pest:mysqlcomposer pest:mariadbcomposer pest:postgres
  • 带覆盖率运行测试:composer pest-coverage:mysql
  • 执行类型检查:composer phpstan
  • 执行代码格式化:composer pint

在运行测试之前,请确保运行 docker-compose up 以启动数据库容器。

更新和变更

有关更新和变更的详细信息,请参阅我们的 CHANGELOG

许可证

Laravel Eloquent Spatial 在 The MIT License (MIT) 许可下发布。有关更多信息,请参阅我们的 许可证文件