astrogin/laravel-mysql-spatial

MySQL spatial data types extension for Laravel.

1.0.0 2017-06-04 21:49 UTC

This package is not auto-updated.

Last update: 2024-04-19 18:07:18 UTC


README

Build Status Code Climate Code Climate Packagist Packagist license

Laravel package to easily work with MySQL Spatial Data Types and MySQL 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.

Installation

Add the package using composer:

composer require astrogin/laravel-mysql-spatial

Register the service provider in config/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:

use Illuminate\Database\Migrations\Migration;
use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

class CreatePlacesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        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();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        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 the SpatialTrait and define an array called $spatialFields with the name of the MySQL Spatial Data field(s) created in the migration:

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

Saving a model

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

Retrieving a model

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

Migration

Available MySQL Spatial Types migration blueprints:

  • geometry
  • point
  • lineString
  • polygon
  • multiPoint
  • multiLineString
  • multiPolygon
  • geometryCollection

Spatial index

You can add or drop spatial indexes in your migrations with the spatialIndex and dropSpatialIndex blueprints.

Note about spatial indexes from the MySQL documentation:

For MyISAM 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 the SPATIAL keyword. Columns in spatial indexes must be declared NOT NULL.

From the command line:

php artisan make:migration update_places_table

Then edit the migration you just created:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class UpdatePlacesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // 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
     */
    public function down()
    {
        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();
        });
    }
}

Models

Available geometry classes:

  • Point
  • LineString
  • Polygon
  • MultiPoint
  • MultiLineString
  • MultiPolygon
  • GeometryCollection

Credits

Originally inspired from njbarrett's Laravel postgis package.