Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

MySQL Spatial Data Extension integration with Laravel.

License

NotificationsYou must be signed in to change notification settings

grimzy/laravel-mysql-spatial

Repository files navigation

Build StatusCode ClimateCode ClimatePackagistPackagistStyleCIlicense

Laravel package to easily work withMySQL Spatial Data Types andMySQL Spatial Functions.

Please check the documentation for your MySQL version. MySQL's Extension for Spatial Data was added in MySQL 5.5 but many Spatial Functions were changed in 5.6 and 5.7.

Versions

  • 1.x.x: MySQL 5.6 (also supports MySQL 5.5 but not all spatial analysis functions)
  • 2.x.x: MySQL 5.7 and 8.0 (Laravel version < 8.0)
  • 3.x.x: MySQL 8.0 with SRID support (Laravel version < 8.0)
  • 4.x.x: MySQL 8.0 with SRID support (Laravel 8+) [Current branch]
  • 5.x.x: MySQL 5.7 and 8.0 (Laravel 8+)

This package also works with MariaDB. Please refer to theMySQL/MariaDB Spatial Support Matrix for compatibility.

Installation

Add the package using composer:

$ composer require grimzy/laravel-mysql-spatial:^4.0# or for Laravel version < 8.0$ composer require grimzy/laravel-mysql-spatial:^3.0

For MySQL 5.7:

$ composer require grimzy/laravel-mysql-spatial:^2.0

For MySQL 5.6 and 5.5:

$ composer require grimzy/laravel-mysql-spatial:^1.0

For Laravel versions before 5.5 or if not using auto-discovery, register the service provider inconfig/app.php:

'providers' => [/*   * Package Service Providers...   */Grimzy\LaravelMysqlSpatial\SpatialServiceProvider::class,],

Quickstart

Create a migration

From the command line:

php artisan make:migration create_places_table

Then edit the migration you just created by adding at least one spatial data field. For Laravel versions prior to 5.5, you can use the Blueprint provided by this package (Grimzy\LaravelMysqlSpatial\Schema\Blueprint):

useIlluminate\Database\Migrations\Migration;useIlluminate\Database\Schema\Blueprint;// For Laravel < 5.5// use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;class CreatePlacesTableextends Migration {/**     * Run the migrations.     *     * @return void     */publicfunctionup()    {        Schema::create('places',function(Blueprint$table)        {$table->increments('id');$table->string('name')->unique();// Add a Point spatial data field named location$table->point('location')->nullable();// Add a Polygon spatial data field named area$table->polygon('area')->nullable();$table->timestamps();        });// Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid)// Schema::create('places', function(Blueprint $table)// {//     $table->increments('id');//     $table->string('name')->unique();//     // Add a Point spatial data field named location with SRID 4326//     $table->point('location', 4326)->nullable();//     // Add a Polygon spatial data field named area with SRID 4326//     $table->polygon('area', 4326)->nullable();//     $table->timestamps();// });    }/**     * Reverse the migrations.     *     * @return void     */publicfunctiondown()    {        Schema::drop('places');    }}

Run the migration:

php artisan migrate

Create a model

From the command line:

php artisan make:model Place

Then edit the model you just created. It must use theSpatialTrait and define an array called$spatialFields with the name of the MySQL Spatial Data field(s) created in the migration:

namespaceApp;useIlluminate\Database\Eloquent\Model;useGrimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;/** * @property \Grimzy\LaravelMysqlSpatial\Types\Point   $location * @property \Grimzy\LaravelMysqlSpatial\Types\Polygon $area */class Placeextends Model{use SpatialTrait;protected$fillable = ['name'    ];protected$spatialFields = ['location','area'    ];}

Saving a model

useGrimzy\LaravelMysqlSpatial\Types\Point;useGrimzy\LaravelMysqlSpatial\Types\Polygon;useGrimzy\LaravelMysqlSpatial\Types\LineString;$place1 =newPlace();$place1->name ='Empire State Building';// saving a point$place1->location =newPoint(40.7484404, -73.9878441);// (lat, lng)$place1->save();// saving a polygon$place1->area =newPolygon([newLineString([newPoint(40.74894149554006, -73.98615270853043),newPoint(40.74848633046773, -73.98648262023926),newPoint(40.747925497790725, -73.9851602911949),newPoint(40.74837050671544, -73.98482501506805),newPoint(40.74894149554006, -73.98615270853043)])]);$place1->save();

Or if your database fields were created with a specific SRID:

useGrimzy\LaravelMysqlSpatial\Types\Point;useGrimzy\LaravelMysqlSpatial\Types\Polygon;useGrimzy\LaravelMysqlSpatial\Types\LineString;$place1 =newPlace();$place1->name ='Empire State Building';// saving a point with SRID 4326 (WGS84 spheroid)$place1->location =newPoint(40.7484404, -73.9878441,4326);// (lat, lng, srid)$place1->save();// saving a polygon with SRID 4326 (WGS84 spheroid)$place1->area =newPolygon([newLineString([newPoint(40.74894149554006, -73.98615270853043),newPoint(40.74848633046773, -73.98648262023926),newPoint(40.747925497790725, -73.9851602911949),newPoint(40.74837050671544, -73.98482501506805),newPoint(40.74894149554006, -73.98615270853043)])],4326);$place1->save();

Note: When saving collection Geometries (LineString,Polygon,MultiPoint,MultiLineString, andGeometryCollection), only the top-most geometry should have an SRID set in the constructor.

In the example above, when creating anew Polygon(), we only set the SRID on thePolygon and use the default for theLineString and thePoint objects.

Retrieving a model

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

Geometry classes

Available Geometry classes

Grimzy\LaravelMysqlSpatial\TypesOpenGIS Class
Point($lat, $lng, $srid = 0)Point
MultiPoint(Point[], $srid = 0)MultiPoint
LineString(Point[], $srid = 0)LineString
MultiLineString(LineString[], $srid = 0)MultiLineString
Polygon(LineString[], $srid = 0)(exterior and interior boundaries)Polygon
MultiPolygon(Polygon[], $srid = 0)MultiPolygon
GeometryCollection(Geometry[], $srid = 0)GeometryCollection

Check out theClass diagram.

Using Geometry classes

In order for your Eloquent Model to handle the Geometry classes, it must use theGrimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait trait and define aprotected property$spatialFields as an array of MySQL Spatial Data Type column names (example inQuickstart).

IteratorAggregate and ArrayAccess

The collection Geometries (LineString,Polygon,MultiPoint,MultiLineString, andGeometryCollection) implementIteratorAggregate andArrayAccess; making it easy to perform Iterator and Array operations. For example:

$polygon =$multipolygon[10];// ArrayAccess// IteratorAggregatefor($polygonas$i =>$linestring) {echo (string)$linestring;}

Helpers

From/To Well Known Text (WKT)
// fromWKT($wkt, $srid = 0)$point = Point::fromWKT('POINT(2 1)');$point->toWKT();// POINT(2 1)$polygon = Polygon::fromWKT('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))');$polygon->toWKT();// POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
From/To String
// fromString($wkt, $srid = 0)$point =newPoint(1,2);// lat, lng(string)$point// lng, lat: 2 1$polygon = Polygon::fromString('(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)');(string)$polygon;// (0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)
From/To JSON (GeoJSON)

The Geometry classes implementJsonSerializable andIlluminate\Contracts\Support\Jsonable to help serialize into GeoJSON:

$point =newPoint(40.7484404, -73.9878441);json_encode($point);// or $point->toJson();// {//   "type": "Feature",//   "properties": {},//   "geometry": {//     "type": "Point",//     "coordinates": [//       -73.9878441,//       40.7484404//     ]//   }// }

To deserialize a GeoJSON string into a Geometry class, you can useGeometry::fromJson($json_string) :

$location = Geometry::fromJson('{"type":"Point","coordinates":[3.4,1.2]}');$locationinstanceof Point::class;// true$location->getLat();// 1.2$location->getLng());// 3.4

Scopes: Spatial analysis functions

Spatial analysis functions are implemented usingEloquent Local Scopes.

Available scopes:

  • distance($geometryColumn, $geometry, $distance)
  • distanceExcludingSelf($geometryColumn, $geometry, $distance)
  • distanceSphere($geometryColumn, $geometry, $distance)
  • distanceSphereExcludingSelf($geometryColumn, $geometry, $distance)
  • comparison($geometryColumn, $geometry, $relationship)
  • within($geometryColumn, $polygon)
  • crosses($geometryColumn, $geometry)
  • contains($geometryColumn, $geometry)
  • disjoint($geometryColumn, $geometry)
  • equals($geometryColumn, $geometry)
  • intersects($geometryColumn, $geometry)
  • overlaps($geometryColumn, $geometry)
  • doesTouch($geometryColumn, $geometry)
  • orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')
  • orderByDistance($geometryColumn, $geometry, $direction = 'asc')
  • orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')

Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf.documentation).

Migrations

For Laravel versions prior to 5.5, you can use the Blueprint provided with this package:Grimzy\LaravelMysqlSpatial\Schema\Blueprint.

useIlluminate\Database\Migrations\Migration;useGrimzy\LaravelMysqlSpatial\Schema\Blueprint;class CreatePlacesTableextends Migration {// ...}

Columns

AvailableMySQL Spatial Types migration blueprints:

  • $table->geometry(string $column_name, int $srid = 0)
  • $table->point(string $column_name, int $srid = 0)
  • $table->lineString(string $column_name, int $srid = 0)
  • $table->polygon(string $column_name, int $srid = 0)
  • $table->multiPoint(string $column_name, int $srid = 0)
  • $table->multiLineString(string $column_name, int $srid = 0)
  • $table->multiPolygon(string $column_name, int $srid = 0)
  • $table->geometryCollection(string $column_name, int $srid = 0)

Spatial indexes

You can add or drop spatial indexes in your migrations with thespatialIndex anddropSpatialIndex blueprints.

  • $table->spatialIndex('column_name')
  • $table->dropSpatialIndex(['column_name']) or$table->dropSpatialIndex('index_name')

Note about spatial indexes from theMySQL documentation:

ForMyISAM and (as of MySQL 5.7.5)InnoDB tables, MySQL can create spatial indexes using syntax similar to that for creating regular indexes, but using theSPATIAL keyword. Columns in spatial indexes must be declaredNOT NULL.

Also please read thisimportant note regarding Index Lengths in the Laravel 5.6 documentation.

For example, as a follow up to theQuickstart; from the command line, generate a new migration:

php artisan make:migration update_places_table

Then edit the migration file that you just created:

useIlluminate\Database\Migrations\Migration;useIlluminate\Database\Schema\Blueprint;useIlluminate\Support\Facades\Schema;class UpdatePlacesTableextends Migration{/**     * Run the migrations.     *     * @return void     */publicfunctionup()    {// MySQL < 5.7.5: table has to be MyISAM// \DB::statement('ALTER TABLE places ENGINE = MyISAM');        Schema::table('places',function (Blueprint$table) {// Make sure point is not nullable$table->point('location')->change();// Add a spatial index on the location field$table->spatialIndex('location');        });    }/**     * Reverse the migrations.     *     * @return void     */publicfunctiondown()    {        Schema::table('places',function (Blueprint$table) {$table->dropSpatialIndex(['location']);// either an array of column names or the index name        });// \DB::statement('ALTER TABLE places ENGINE = InnoDB');        Schema::table('places',function (Blueprint$table) {$table->point('location')->nullable()->change();        });    }}

Tests

$ composertest# or$ composer test:unit$ composer test:integration

Integration tests require a running MySQL database. If you have Docker installed, you can start easily start one:

$ make start_db# starts MySQL 8.0# or$ make start_db V=5.7# starts MySQL 5.7

Contributing

Recommendations and pull request are most welcome! Pull requests with tests are the best! There are still a lot of MySQL spatial functions to implement or creative ways to use spatial functions.

Credits

Originally inspired fromnjbarrett's Laravel postgis package.

Packages

No packages published

Contributors12


[8]ページ先頭

©2009-2025 Movatter.jp