{"id":20887005,"url":"https://github.com/fleetbase/laravel-mysql-spatial","last_synced_at":"2025-04-11T02:23:19.191Z","repository":{"id":219861626,"uuid":"750115213","full_name":"fleetbase/laravel-mysql-spatial","owner":"fleetbase","description":"MySQL spatial data types extension for Laravel x Fleetbase.","archived":false,"fork":false,"pushed_at":"2024-02-15T18:31:00.000Z","size":106,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-03T12:54:34.348Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fleetbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-01-30T02:22:47.000Z","updated_at":"2025-02-14T11:14:55.000Z","dependencies_parsed_at":"2024-01-30T03:40:11.192Z","dependency_job_id":null,"html_url":"https://github.com/fleetbase/laravel-mysql-spatial","commit_stats":null,"previous_names":["fleetbase/laravel-mysql-spatial"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fleetbase%2Flaravel-mysql-spatial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fleetbase%2Flaravel-mysql-spatial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fleetbase%2Flaravel-mysql-spatial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fleetbase%2Flaravel-mysql-spatial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fleetbase","download_url":"https://codeload.github.com/fleetbase/laravel-mysql-spatial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248328496,"owners_count":21085325,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T08:18:45.314Z","updated_at":"2025-04-11T02:23:19.167Z","avatar_url":"https://github.com/fleetbase.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fleetbase MySQL Spatial extension\n\n[![Packagist](https://img.shields.io/packagist/v/fleetbase/laravel-mysql-spatial.svg?style=flat-square)](https://packagist.org/packages/fleetbase/laravel-mysql-spatial)\n[![Packagist](https://img.shields.io/packagist/dt/fleetbase/laravel-mysql-spatial.svg?style=flat-square)](https://packagist.org/packages/fleetbase/laravel-mysql-spatial) \n[![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](LICENSE)\n\nLaravel package to easily work with [MySQL Spatial Data Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) and [MySQL Spatial Functions](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html). This is a maintained fork from the infamous [grimzy\\/laravel-mysql-spatial](https://github.com/grimzy/laravel-mysql-spatial) for Laravel 9x and 10x.\n\nPlease 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.\n\nThis package also works with MariaDB. Please refer to the [MySQL/MariaDB Spatial Support Matrix](https://mariadb.com/kb/en/library/mysqlmariadb-spatial-support-matrix/) for compatibility.\n\n## Installation\n\nAdd the package using composer:\n\n```sh\n$ composer require fleetbase/laravel-mysql-spatial\n```\n\n## Quickstart\n\n### Create a migration\n\nFrom the command line:\n\n```shell\nphp artisan make:migration create_places_table\n```\n\nThen 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 (Fleetbase\\LaravelMysqlSpatial\\Schema\\Blueprint):\n\n```php\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\n\n// For Laravel \u003c 5.5\n// use Fleetbase\\LaravelMysqlSpatial\\Schema\\Blueprint;\n\nclass CreatePlacesTable extends Migration {\n\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('places', function(Blueprint $table)\n        {\n            $table-\u003eincrements('id');\n            $table-\u003estring('name')-\u003eunique();\n            // Add a Point spatial data field named location\n            $table-\u003epoint('location')-\u003enullable();\n            // Add a Polygon spatial data field named area\n            $table-\u003epolygon('area')-\u003enullable();\n            $table-\u003etimestamps();\n        });\n  \n        // Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid)\n  \n        // Schema::create('places', function(Blueprint $table)\n        // {\n        //     $table-\u003eincrements('id');\n        //     $table-\u003estring('name')-\u003eunique();\n        //     // Add a Point spatial data field named location with SRID 4326\n        //     $table-\u003epoint('location', 4326)-\u003enullable();\n        //     // Add a Polygon spatial data field named area with SRID 4326\n        //     $table-\u003epolygon('area', 4326)-\u003enullable();\n        //     $table-\u003etimestamps();\n        // });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('places');\n    }\n}\n```\n\nRun the migration:\n\n```shell\nphp artisan migrate\n```\n\n### Create a model\n\nFrom the command line:\n\n```shell\nphp artisan make:model Place\n```\n\nThen 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:\n\n```php\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Fleetbase\\LaravelMysqlSpatial\\Eloquent\\SpatialTrait;\n\n/**\n * @property \\Fleetbase\\LaravelMysqlSpatial\\Types\\Point   $location\n * @property \\Fleetbase\\LaravelMysqlSpatial\\Types\\Polygon $area\n */\nclass Place extends Model\n{\n    use SpatialTrait;\n\n    protected $fillable = [\n        'name'\n    ];\n\n    protected $spatialFields = [\n        'location',\n        'area'\n    ];\n}\n```\n\n### Saving a model\n\n```php\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\Point;\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\Polygon;\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\LineString;\n\n$place1 = new Place();\n$place1-\u003ename = 'Empire State Building';\n\n// saving a point\n$place1-\u003elocation = new Point(40.7484404, -73.9878441);\t// (lat, lng)\n$place1-\u003esave();\n\n// saving a polygon\n$place1-\u003earea = new Polygon([new LineString([\n    new Point(40.74894149554006, -73.98615270853043),\n    new Point(40.74848633046773, -73.98648262023926),\n    new Point(40.747925497790725, -73.9851602911949),\n    new Point(40.74837050671544, -73.98482501506805),\n    new Point(40.74894149554006, -73.98615270853043)\n])]);\n$place1-\u003esave();\n```\n\nOr if your database fields were created with a specific SRID:\n\n```php\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\Point;\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\Polygon;\nuse Fleetbase\\LaravelMysqlSpatial\\Types\\LineString;\n\n$place1 = new Place();\n$place1-\u003ename = 'Empire State Building';\n\n// saving a point with SRID 4326 (WGS84 spheroid)\n$place1-\u003elocation = new Point(40.7484404, -73.9878441, 4326);\t// (lat, lng, srid)\n$place1-\u003esave();\n\n// saving a polygon with SRID 4326 (WGS84 spheroid)\n$place1-\u003earea = new Polygon([new LineString([\n    new Point(40.74894149554006, -73.98615270853043),\n    new Point(40.74848633046773, -73.98648262023926),\n    new Point(40.747925497790725, -73.9851602911949),\n    new Point(40.74837050671544, -73.98482501506805),\n    new Point(40.74894149554006, -73.98615270853043)\n])], 4326);\n$place1-\u003esave();\n```\n\n\u003e **Note**: When saving collection Geometries (`LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, and `GeometryCollection`), only the top-most geometry should have an SRID set in the constructor.\n\u003e\n\u003e In the example above, when creating a `new Polygon()`, we only set the SRID on the `Polygon` and use the default for the `LineString` and the `Point` objects.\n\n### Retrieving a model\n\n```php\n$place2 = Place::first();\n$lat = $place2-\u003elocation-\u003egetLat();\t// 40.7484404\n$lng = $place2-\u003elocation-\u003egetLng();\t// -73.9878441\n```\n\n## Geometry classes\n\n### Available Geometry classes\n\n| Fleetbase\\LaravelMysqlSpatial\\Types                             | OpenGIS Class                                                |\n| ------------------------------------------------------------ | ------------------------------------------------------------ |\n| `Point($lat, $lng, $srid = 0)`                               | [Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) |\n| `MultiPoint(Point[], $srid = 0)`                             | [MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) |\n| `LineString(Point[], $srid = 0)`                             | [LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) |\n| `MultiLineString(LineString[], $srid = 0)`                   | [MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) |\n| `Polygon(LineString[], $srid = 0)` *([exterior and interior boundaries](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html))* | [Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html) |\n| `MultiPolygon(Polygon[], $srid = 0)`                         | [MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) |\n| `GeometryCollection(Geometry[], $srid = 0)`                  | [GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) |\n\nCheck out the [Class diagram](https://user-images.githubusercontent.com/1837678/30788608-a5afd894-a16c-11e7-9a51-0a08b331d4c4.png).\n\n### Using Geometry classes\n\nIn order for your Eloquent Model to handle the Geometry classes, it must use the `Fleetbase\\LaravelMysqlSpatial\\Eloquent\\SpatialTrait` trait and define a `protected` property `$spatialFields`  as an array of MySQL Spatial Data Type column names (example in [Quickstart](#user-content-create-a-model)).\n\n#### IteratorAggregate and ArrayAccess\n\nThe collection Geometries (`LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, and `GeometryCollection`) implement [`IteratorAggregate`](http://php.net/manual/en/class.iteratoraggregate.php) and [`ArrayAccess`](http://php.net/manual/en/class.arrayaccess.php); making it easy to perform Iterator and Array operations. For example:\n\n```php\n$polygon = $multipolygon[10];\t// ArrayAccess\n\n// IteratorAggregate\nfor($polygon as $i =\u003e $linestring) {\n  echo (string) $linestring;\n}\n\n```\n\n#### Helpers\n\n##### From/To Well Known Text ([WKT](https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-wkt-format))\n\n```php\n// fromWKT($wkt, $srid = 0)\n$point = Point::fromWKT('POINT(2 1)');\n$point-\u003etoWKT();\t// POINT(2 1)\n\n$polygon = Polygon::fromWKT('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))');\n$polygon-\u003etoWKT();\t// POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))\n```\n\n##### From/To String\n\n```php\n// fromString($wkt, $srid = 0)\n$point = new Point(1, 2);\t// lat, lng\n(string)$point\t\t\t// lng, lat: 2 1\n\n$polygon = Polygon::fromString('(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)');\n(string)$polygon;\t// (0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)\n```\n\n##### From/To JSON ([GeoJSON](http://geojson.org/))\n\nThe Geometry classes implement [`JsonSerializable`](http://php.net/manual/en/class.jsonserializable.php) and `Illuminate\\Contracts\\Support\\Jsonable` to help serialize into GeoJSON:\n\n```php\n$point = new Point(40.7484404, -73.9878441);\n\njson_encode($point); // or $point-\u003etoJson();\n\n// {\n//   \"type\": \"Feature\",\n//   \"properties\": {},\n//   \"geometry\": {\n//     \"type\": \"Point\",\n//     \"coordinates\": [\n//       -73.9878441,\n//       40.7484404\n//     ]\n//   }\n// }\n```\n\nTo deserialize a GeoJSON string into a Geometry class, you can use `Geometry::fromJson($json_string)` :\n\n```php\n$location = Geometry::fromJson('{\"type\":\"Point\",\"coordinates\":[3.4,1.2]}');\n$location instanceof Point::class;  // true\n$location-\u003egetLat();  // 1.2\n$location-\u003egetLng()); // 3.4\n```\n\n## Scopes: Spatial analysis functions\n\nSpatial analysis functions are implemented using [Eloquent Local Scopes](https://laravel.com/docs/5.4/eloquent#local-scopes).\n\nAvailable scopes:\n\n- `distance($geometryColumn, $geometry, $distance)`\n- `distanceExcludingSelf($geometryColumn, $geometry, $distance)`\n- `distanceSphere($geometryColumn, $geometry, $distance)`\n- `distanceSphereExcludingSelf($geometryColumn, $geometry, $distance)`\n- `comparison($geometryColumn, $geometry, $relationship)`\n- `within($geometryColumn, $polygon)`\n- `crosses($geometryColumn, $geometry)`\n- `contains($geometryColumn, $geometry)`\n- `disjoint($geometryColumn, $geometry)`\n- `equals($geometryColumn, $geometry)`\n- `intersects($geometryColumn, $geometry)`\n- `overlaps($geometryColumn, $geometry)`\n- `doesTouch($geometryColumn, $geometry)`\n- `orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')`\n- `orderByDistance($geometryColumn, $geometry, $direction = 'asc')`\n- `orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')`\n\n*Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf. [documentation](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html)).*\n\n## Migrations\n\nFor Laravel versions prior to 5.5, you can use the Blueprint provided with this package: `Fleetbase\\LaravelMysqlSpatial\\Schema\\Blueprint`.\n\n```php\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Fleetbase\\LaravelMysqlSpatial\\Schema\\Blueprint;\n\nclass CreatePlacesTable extends Migration {\n    // ...\n}\n```\n\n### Columns\n\nAvailable [MySQL Spatial Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) migration blueprints:\n\n- `$table-\u003egeometry(string $column_name, int $srid = 0)`\n- `$table-\u003epoint(string $column_name, int $srid = 0)`\n- `$table-\u003elineString(string $column_name, int $srid = 0)`\n- `$table-\u003epolygon(string $column_name, int $srid = 0)`\n- `$table-\u003emultiPoint(string $column_name, int $srid = 0)`\n- `$table-\u003emultiLineString(string $column_name, int $srid = 0)`\n- `$table-\u003emultiPolygon(string $column_name, int $srid = 0)`\n- `$table-\u003egeometryCollection(string $column_name, int $srid = 0)`\n\n### Spatial indexes\n\nYou can add or drop spatial indexes in your migrations with the `spatialIndex` and `dropSpatialIndex` blueprints.\n\n- `$table-\u003espatialIndex('column_name')`\n- `$table-\u003edropSpatialIndex(['column_name'])` or `$table-\u003edropSpatialIndex('index_name')`\n\nNote about spatial indexes from the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/creating-spatial-indexes.html):\n\n\u003e For [`MyISAM`](https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html) 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`.\n\nAlso please read this [**important note**](https://laravel.com/docs/5.5/migrations#indexes) regarding Index Lengths in the Laravel 5.6 documentation.\n\nFor example, as a follow up to the [Quickstart](#user-content-create-a-migration); from the command line, generate a new migration:\n\n```shell\nphp artisan make:migration update_places_table\n```\n\nThen edit the migration file that you just created:\n\n```php\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass UpdatePlacesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        // MySQL \u003c 5.7.5: table has to be MyISAM\n        // \\DB::statement('ALTER TABLE places ENGINE = MyISAM');\n\n        Schema::table('places', function (Blueprint $table) {\n            // Make sure point is not nullable\n            $table-\u003epoint('location')-\u003echange();\n          \n            // Add a spatial index on the location field\n            $table-\u003espatialIndex('location');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::table('places', function (Blueprint $table) {\n            $table-\u003edropSpatialIndex(['location']); // either an array of column names or the index name\n        });\n\n        // \\DB::statement('ALTER TABLE places ENGINE = InnoDB');\n\n        Schema::table('places', function (Blueprint $table) {\n            $table-\u003epoint('location')-\u003enullable()-\u003echange();\n        });\n    }\n}\n```\n\n## Tests\n\n```shell\n$ composer test\n# or \n$ composer test:unit\n$ composer test:integration\n```\n\nIntegration tests require a running MySQL database. If you have Docker installed, you can start easily start one:\n\n```shell\n$ make start_db\t\t# starts MySQL 8.0\n# or\n$ make start_db V=5.7\t# starts MySQL 5.7\n```\n\n## Contributing\n\nRecommendations 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. \n\n## Credits\n\nOriginally inspired from [njbarrett's Laravel postgis package](https://github.com/njbarrett/laravel-postgis).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffleetbase%2Flaravel-mysql-spatial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffleetbase%2Flaravel-mysql-spatial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffleetbase%2Flaravel-mysql-spatial/lists"}