Coder Social home page Coder Social logo

grimzy / laravel-mysql-spatial Goto Github PK

View Code? Open in Web Editor NEW
786.0 26.0 295.0 283 KB

MySQL Spatial Data Extension integration with Laravel.

License: Other

PHP 99.42% Makefile 0.58%
laravel laravel-5-package mysql spatial geometry laravel-6-package laravel-7-package mysql-extension spatial-functions laravel-8-package

laravel-mysql-spatial's Introduction

Laravel MySQL Spatial extension

Build Status Code Climate Code Climate Packagist Packagist StyleCI 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.

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 the MySQL/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 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. For Laravel versions prior to 5.5, you can use the Blueprint provided by this package (Grimzy\LaravelMysqlSpatial\Schema\Blueprint):

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

// For Laravel < 5.5
// 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();
            // 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
     */
    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
 * @property \Grimzy\LaravelMysqlSpatial\Types\Polygon $area
 */
class Place extends Model
{
    use SpatialTrait;

    protected $fillable = [
        'name'
    ];

    protected $spatialFields = [
        'location',
        'area'
    ];
}

Saving a model

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point
$place1->location = new Point(40.7484404, -73.9878441);	// (lat, lng)
$place1->save();

// saving a polygon
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])]);
$place1->save();

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

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point with SRID 4326 (WGS84 spheroid)
$place1->location = new Point(40.7484404, -73.9878441, 4326);	// (lat, lng, srid)
$place1->save();

// saving a polygon with SRID 4326 (WGS84 spheroid)
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])], 4326);
$place1->save();

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

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.

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\Types OpenGIS 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 the Class diagram.

Using Geometry classes

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

IteratorAggregate and ArrayAccess

The collection Geometries (LineString, Polygon, MultiPoint, MultiLineString, and GeometryCollection) implement IteratorAggregate and ArrayAccess; making it easy to perform Iterator and Array operations. For example:

$polygon = $multipolygon[10];	// ArrayAccess

// IteratorAggregate
for($polygon as $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 = new Point(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 implement JsonSerializable and Illuminate\Contracts\Support\Jsonable to help serialize into GeoJSON:

$point = new Point(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 use Geometry::fromJson($json_string) :

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

Scopes: Spatial analysis functions

Spatial analysis functions are implemented using Eloquent 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.

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

class CreatePlacesTable extends Migration {
    // ...
}

Columns

Available MySQL 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 the spatialIndex and dropSpatialIndex blueprints.

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

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.

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

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

php artisan make:migration update_places_table

Then edit the migration file that 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();
        });
    }
}

Tests

$ composer test
# 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 from njbarrett's Laravel postgis package.

laravel-mysql-spatial's People

Contributors

antonkomarev avatar astrogin avatar bricehartmann avatar d3radicated avatar davidpiesse avatar dylan-dutchandbold avatar georgeboot avatar grimzy avatar jl9404 avatar kocoten1992 avatar matanyadaev avatar sikhlana avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-mysql-spatial's Issues

orderByDistance()

I thought i'd put this here for anyone else that wanted it.

I wanted to orderByDistance and it was as simple as:

public function scopeOrderByDistance($query, $geometryColumn, $geometry)
    {
        $this->isColumnAllowed($geometryColumn);

        $query->orderByRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?))", [
            $geometry->toWkt()
        ]);

        return $query;
    }

Presumably you can add these scopes for the other columns as well.

Unable to run within when different SRID generated

I've table like this:

CREATE TABLE `jovan_test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `properties__name` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.name'))) VIRTUAL,
  `properties__age` int(11) GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.age'))) VIRTUAL,
  `properties__height` int(11) GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.height'))) VIRTUAL,
  `properties__address__city` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.city'))) VIRTUAL,
  `properties__address__zip_code` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.zip_code'))) VIRTUAL,
  `properties__address__state` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.state'))) VIRTUAL,
  `properties__address__country` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.country'))) VIRTUAL,
  `properties__address__home_coordinate` point GENERATED ALWAYS AS (st_geomfromgeojson(json_unquote(json_extract(`__docs`,'$.properties.address.home_coordinate')))) VIRTUAL,
  `properties__address__routes` geometry GENERATED ALWAYS AS (st_geomfromgeojson(json_unquote(json_extract(`__docs`,'$.properties.address.routes')))) VIRTUAL,
  `__docs` json NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `jovan_test_properties__name_index` (`properties__name`),
  KEY `jovan_test_properties__age_index` (`properties__age`),
  KEY `jovan_test_properties__height_index` (`properties__height`),
  KEY `jovan_test_properties__address__city_index` (`properties__address__city`),
  KEY `jovan_test_properties__address__zip_code_index` (`properties__address__zip_code`),
  KEY `jovan_test_properties__address__state_index` (`properties__address__state`),
  KEY `jovan_test_properties__address__country_index` (`properties__address__country`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Insert new value like this:

insert into jovan_test set __docs = '{"properties": {"age": 29, "name": "Rahmat Awaludin", "height": 160, "address": {"city": "Bandung", "state": "Jawa Barat", "routes": {"type": "LineString", "coordinates": [[102, 0], [103, 1], [104, 0], [105, 1]]}, "country": "Indonesia", "zip_code": "43193", "home_coordinate": {"type": "Point", "coordinates": [30, 10]}}}}'

With resulting like this:

mysql root@localhost:intelligence> select id, st_astext(properties__address__home_coordinate) from jovan_test;
+----+-------------------------------------------------+
| id | st_astext(properties__address__home_coordinate) |
+----+-------------------------------------------------+
| 2  | POINT(30 10)                                    |
+----+-------------------------------------------------+

The within query generated query like this:

select * from `jovan_test` where st_within(`properties__address__home_coordinate`, ST_GeomFromText("POLYGON((40 -10,-10 -10,-10 40,40 40,40 -10))"))

It silently error on mysql (I don't get error message in laravel), the message like this:

Binary geometry function st_within given two geometries of different srids: 4326 and 0, which should have been identical.

This because ST_GeomFromGeoJson generate SRID 4326 by default see here if none provided.

The srid argument, if given, must be a 32-bit unsigned integer. If not given, the geometry return value has an SRID of 4326.

While ST_GeomFromText generate SRID 0 by default if not provided see here.

This can be solved by using SRID to 0 on first ST_GeomFromGeoJson call. That is possible with this library.

But, I believe allowing set SRID on scopeWithin will work best. So the resulting query would be

select * from `jovan_test` where st_within(`properties__address__home_coordinate`, ST_GeomFromText("POLYGON((40 -10,-10 -10,-10 40,40 40,40 -10))",4326))

This sinergy with allowing SRID on creating column as you alredy done.

What do you think? I can prepare a PR if you want.

I am getting this error what might be the reason?

exception
:
"Symfony\Component\Debug\Exception\FatalThrowableError"
file
:
"/var/www/pedro/vendor/grimzy/laravel-mysql-spatial/src/Connectors/ConnectionFactory.php"
line
:
27
message
:
"Undefined class constant 'PDO::FETCH_OBJ'"

Problems running in-memory sqlite migrations containing spatial features

While writing PHPUnit tests, I ran into a couple of issues after running migrations.

First of all, something's wrong with the dependency injection. An instance of Illuminate\Database\Schema\Blueprint is always passed, even if Grimzy\LaravelMysqlSpatial\Schema\Blueprint is used instead. May not be related to this package, but I haven't yet found a solution.

Secondly, after bypassing the above issue by using $table->addColumn('point', 'column-name'); instead of $table->point('column-name'), the following exception is thrown using an in-memory sqlite database for testing:

Error: Call to undefined method Illuminate\Database\Schema\Grammars\SQLiteGrammar::typePoint()

Any suggestions on how this could be fixed? If I'm doing something wrong, please let me know. It would be nice to document how to properly configure this package for testing.

SQL Injection

Clicking through the source code has me worried. It looks like this package facilitates SQL Injections.

For example the scopeDistance function

public function scopeDistance($query, $geometryColumn, $geometry, $distance)
    {
        $query->whereRaw("st_distance(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) <= {$distance}");

        return $query;
    }

The user data is just executed raw, no bindings, no escaping. Doing a simple test below shows it allows for SQL Injection.

>>> Address::distance('location', new \Grimzy\LaravelMysqlSpatial\Types\Point(51.905737, 4.430866), "'' OR 1=1")->toSql()
=> "select * from `addresses` where st_distance(`location`, ST_GeomFromText('POINT(4.430866 51.905737)')) <= '' OR 1=1"

Cannot use "Polygon" type correctly

I have an array of coordinates, which I am passing to the controller and then parse it into an "array of Points" as follows:

            Log::info($request->polygon);
            $arrayOfPoints = [];
            foreach( $request->polygon as $point ){
                $arrayOfPoints[] = new Point($point[0], $point[1]);
            }
            Log::info(new Polygon($arrayOfPoints)); // Line 28

And immediately I get the following error:

[2017-08-22 20:44:51] local.INFO: array (
0 =>
array (
0 => '-99.16897058486938',
1 => '19.424870411471588',
),
1 =>
array (
0 => '-99.16744709014893',
1 => '19.424769230105948',
),
2 =>
array (
0 => '-99.16781187057495',
1 => '19.423433630174305',
),
3 =>
array (
0 => '-99.16882038116455',
1 => '19.4236764673421',
),
)
[2017-08-22 20:44:51] local.ERROR: exception 'InvalidArgumentException' with message '$linestrings must be an array of Points' in /Library/WebServer/Documents/private/private/vendor/grimzy/laravel-mysql-spatial/src/Types/MultiLineString.php:29
Stack trace:
#0 /Library/WebServer/Documents/private/private/app/Http/Controllers/LocationController.php(28): Grimzy\LaravelMysqlSpatial\Types\MultiLineString->__construct(Array)
#1 [internal function]: App\Http\Controllers\LocationController->create(Object(Illuminate\Http\Request))

Question: using geometry fields in Model::firstOrCreate()

I can insert geometry records using the following code:

        $location = new Point($datum->lat, $datum->lon);
        MyModel::firstOrCreate([
            'location' => DB::raw("ST_GeomFromText('" . $location->toWKT() . "')"),
        ]);

This seems a little verbose. Is there a shorter/cleaner way to do this?

MultiLineString::__construct() must be of the type array, object given

I am trying to use this package to store polygons in my database. When I set up new points for each point of my polygon and use them to create a LineString to save as a Polygon on my model, I am getting an error (title of issue)

The output of Collection is shown below along with the code to generate the collection.

I have added use SpatialTrait; and protected $spatialFields = ['polygon']; to my model.

I use the generated $polygons variable in a relational model save() method.

I have also set up the migration to use your Blueprint methods, even though Laravel now supports these fields.

Code:

$coords = explode(' ', $polygon);
                $tempCoords = [];
                foreach($coords as $coord) {
                    list($lat, $lon) = explode(',', $coord);
                    $tempCoords[] = new Point($lat, $lon);
                }

                $collection = new LineString($tempCoords);

                $polygons[] = new MyModel([
                    'polygon' => new Polygon($collection)
                ]);

Dump of $collection;

Grimzy\LaravelMysqlSpatial\Types\LineString {#764
  #points: array:7 [
    0 => Grimzy\LaravelMysqlSpatial\Types\Point {#757
      #lat: 34.39
      #lng: -98.36
    }
    1 => Grimzy\LaravelMysqlSpatial\Types\Point {#758
      #lat: 34.51
      #lng: -98.46
    }
    2 => Grimzy\LaravelMysqlSpatial\Types\Point {#759
      #lat: 34.51
      #lng: -98.31
    }
    3 => Grimzy\LaravelMysqlSpatial\Types\Point {#760
      #lat: 34.4
      #lng: -98.23
    }
    4 => Grimzy\LaravelMysqlSpatial\Types\Point {#761
      #lat: 34.21
      #lng: -98.23
    }
    5 => Grimzy\LaravelMysqlSpatial\Types\Point {#762
      #lat: 34.22
      #lng: -98.37
    }
    6 => Grimzy\LaravelMysqlSpatial\Types\Point {#763
      #lat: 34.39
      #lng: -98.36
    }
  ]
}

point validation

Hello,
Is there any way to validate that a POINT is included in a POLYGON ? or is within bounds (min/max * lat/lng) ?
Thank you !!

Empty geometryCollection field returning error on access

Hi, I am having an issue with a geometry collection field . At some point, I have to update the field removing all points inside it. The problem is when I try to obtain an object from the DB and then get the field as an array.

It seems that the cast for an empty geometry collection is erroneous:

FatalThrowableError (E_ERROR) Call to a member function toArray() on string

The error occurs when calling:
$obj->waypoints->toArray()

A dump for the object returns the field as:
"waypoints" => "\x00\x00\x00\x00\x01\x07\x00\x00\x00\x00\x00\x00\x00"

The SQL query for the field, using ST_AsText(waypoints) returns:
GEOMETRYCOLLECTION()

I declare the field in the migration as:
$table->geometryCollection('waypoints');

and declare as a spatial field on the model class:
protected $spatialFields = [ 'waypoints' ];

What is the unit of distance in Scope

In what unit the value of parameter $distance is given in the available scopes in Spatial analysis functions?

distance($geometryColumn, $geometry, $distance)

polygon

do you have example use this to draw and save polygon in database? laravel, sorrt im realy new to this kind

Wrong Blueprint given

I followed the quickstart in the readme, but encountered an exception when running php artisan migrate:

 [Symfony\Component\Debug\Exception\FatalThrowableError]
  Type error: Argument 1 passed to CreatePlacesTable::{closure}() must be an instance of Grimzy\LaravelMysqlSpatial\Schema\Blueprint, instance of Illuminate\Database
  \Schema\Blueprint given, called in /home/vagrant/gaspis/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php on line 163

I am using a Homestead instance with

  • Laravel Framework 5.4.35
  • Mysql Server version: 5.7.19-0ubuntu0.16.04.1 (Ubuntu)

I have installed the library with composer require grimzy/laravel-mysql-spatial

North Pole coordinates

Since MySQL doesn't allow spatial indexes on nullable POINT type columns (and it also doesn't allow setting default value for POINT type columns), it would be handy if there is a constant defined in Point class that represents null value. I'm currently using North Pole coordinates (lat: 90, lng: 0) as my null value. Can you define this as a CONST in Point class so that we could assign it statically? How would you implement it?

(PHP doesn't support static constructor; neither does it support assigning function calls to const members. I'm not sure what other way do we have to define it statically.

Trait method newEloquentBuilder has not been applied, because there are collisions with other trait methods

I'm using 1.0.0 version of your package together with sofa/eloquence:^5.4.
I thought the error in the title was fixed using:
use SpatialTrait { Eloquence::newEloquentBuilder insteadof SpatialTrait; SpatialTrait::newEloquentBuilder as newEloquentSpatialBuilder; }
because the Eloquence methods I'm using works well.

But now, I'm trying to update the location field of my model using the Point class without success. The exeception is: SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field.

Any idea to fix this collision without impact on the functionalities? I really need both packages.
I'm going to open an issue to Eloquence package too.

Mysql Geo Field Format

So, right now the field parsed using code:

 public static function fromWKB($wkb)
    {
        // mysql adds 4 NUL bytes at the start of the binary
        $prefix = "\0\0\0\0";
        if (substr($wkb, 0, strlen($prefix)) == $prefix) {
            $wkb = substr($wkb, strlen($prefix));
        }

        $parser = new Parser(new Factory());

        return $parser->parse($wkb);
    }

but mysql field actually stored like
$srid . $wkb
where length of $srid is 4 bytes

if $srid != 0, there will be error like this
Parsing failed: Bad endian byte value 230

Well, for mysql <8.0 there no differences between any value of $srid,
but for Earth coordinates correct one is 4326 (EPSG:4326 - wgs-84)
and difference appears in mysql >=8

At the end, it's, probably, should looks like this:

 public static function fromMysqlGeoField($value)
    {
       // $srid = substr($value,0,4); //  
       $wkb = substr($value, 4);
       $parser = new Parser(new Factory());
       return $parser->parse($wkb);
    }

Inserting LineString

I am having a terribly difficult time inserting a LineString. Points insert fine, but LineStrings are not being formatted corrected during the insert.

$route = new Route();
$route->path = new LineString([new Point(1, 1), new Point(2, 2), new Point(3, 3));
$route->save();

This is basically what I am doing. It actually appears that the LineString() object is being created successfully, but I just can't get it to insert properly.

If i dump out the $route->path property before the insert, this is what the LineString() object looks like. (Am I maybe constructing the object wrong?), to me it looks like the object is constructed correct (there are Lat and Lng properties for each point in the list, I just didn't expand them all for brevity).

image

Using this code, the save() method throws a SQL error "Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field."

Basically MySQL is saying it can't figure out how to build the geometry object with the information it is being passed.

Here is the SQL statement being produced:

SQL: insert into `routes` (`name`, `type`, `departure_name`, `departure_id`, `arrival_name`, `arrival_id`, `distance`, `duration`, `route`, `polyline`, `updated_at`, `created_at`) values (Route Runner, 1, Leas, 3, Heldj, 2, 36, 44, 40.786159 -111.981999,40.782483 -111.991326,40.777533 -111.99107,40.763445 -111.978736,40.763865 -111.914582,40.782344 -111.908802,40.782438 -111.896401,40.771566 -111.892318,40.771572 -111.899574,40.782391 -111.899599,40.782109 -111.911055,40.760796 -111.914607,40.744019 -111.904332,40.698132 -111.901919,40.611625 -111.906225,40.529731 -111.891577,40.493677 -111.891283,40.458924 -111.914726,40.449055 -111.912245,40.432307 -111.893405, 1, 2017-09-26 21:14:36, 2017-09-26 21:14:36)

So the problem is clear to me that the format that the LineString is being inserted is incorrect. It should be lineString(lat lng, lat lng, lat lng) instead of just lat lng, lat lng, lat lng.

How am I using this package wrong?

Point Class not found

Hi there,

I ran into an issue when I try to push my data to the database, here is the error I'm receiving:

Symfony\Component\Debug\Exception\FatalThrowableError: Class &#039;App\Http\Controllers\Point&#039; not found

Currently using:
Laravel Framework 5.5.28
MySQL Version : 5.6.36

Migration

use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

public function up()
{
    Schema::create('pins', function (Blueprint $table) {
      $table->point('_geoloc')->nullable();
}

Model.php
use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;

protected $spatialFields = [ '_geoloc', ];

Controller.php

namespace App\Http\Controllers;

use App\Pin;
use Illuminate\Http\Request;

class PinController extends Controller {
    public function store(Request $request) {
      $pin = new Pin();
      $pin->_geoloc = new Point(-40.1134343, -43.76543);
      $pin->save();
    }
}

Please let me know any ideas you may have, thanks!

Can´t use Within - Special analysis functions

I´m trying to test the within function to check if a point is inside a defined polygon.

Here´s the code i´m using:

$place = Place::first();
        $polygon = new Polygon([new LineString([
            new Point(40.74894149554006, -73.98615270853043),
            new Point(40.74848633046773, -73.98648262023926),
            new Point(40.747925497790725, -73.9851602911949),
            new Point(40.74837050671544, -73.98482501506805),
            new Point(40.74894149554006, -73.98615270853043)
        ])]);

        return Place::within('location', $polygon) ;

'location' is the column on my table -> ($table->point('location');)

When i run the within function, it keeps giving me this error:

Object of class Grimzy\LaravelMysqlSpatial\Eloquent\Builder could not be converted to string

Am i doing something wrong?

lat/lng vs lng/lat, should flip stored coordinates in database?

Hi
We stored coordinates in Point(lat lng) format. Now when I want to use this package the result of getLat() and getLng() is incorrect.
I think we have two solution :

  • Flip all coordinate in MySQL database using Update SQL query and use this package.
  • Customize this package to use flip ordered of lat/lng by editing Point.php file methods.

I know there are different standards/approaches (ISO 6709, MySQL Forum). But I don't know which solution is better.
Do you have any suggestion ?

Search by multiple polygons inside a polygon

Hi,

I´m building a application where the user can insert a point, line or polygon. Since i have to search by drawing a polygon on the map, i decided to save all of the above as polygons (because this way i only need one index, and the point or line can be null), as shown in the example below:

POINT(-8.534297 37.115448) -> POLYGON((-8.534297 37.115448,-8.534297 37.115448,-8.534297 37.115448,-8.534297 37.115448))
LINESTRING(-8.542011 37.117322,-8.540262 37.11674) -> POLYGON((-8.542011 37.117322,-8.540262 37.11674,-8.542011 37.117322,-8.542011 37.117322))

So, my question is: Is there a search method where i give the search (drawed) polygon to the function, and it returns all the polygons found inside (points and lines, converted to polygons be me).

I think i tried all of the functions you specify in the documentation and none of them seems to do what i need. Am i missing something?

Thanks in advance

Add an option to allow specifying the order of coordinates as stored in the database (Ie. lat/lng, lng/lat)

Hi, I'd like to request this feature as I'd love to use this library but, due to restrictions with a legacy system, I can't change the order the coordinates are stored in the database. I need to find a way to allow this library to work with POINT()s stored as (lat lng).

I came across #38 and don't quite understand your suggestion of extending the Point class to customise the order. I assume you mean Grimzy\LaravelMysqlSpatial\Types\Point, but I can't work out how to get the library to then use my extended class.

If an option (either by config or something to set in the model) could be provided to do this without needing to extend anything from the project, that would be great. I'd be happy to attempt this myself if I had some guidance.

$table change what does this do i cant see where is this function decleared

hi first thanks for amazing package i wish i reached here long time ago

as in readme

        $table->point('location')->change();

where is this function change() decleared ?

what you do to make point column not null so i can use index on it?

is there is a way to set default value for point ? point(0,0) is ok for me

Format for submitted values

I've created a point type field in my DB on a location model, I can set its value explicitly by creating a Point instance as per the examples, but what I've been unable to figure out is what format it wants on the input side, with values coming from a client. If I submit something like location=Point(51.509865,-0.118092) in my HTTP params, I end up with an error when I pass it to $location = Location::create($request->all());:

SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field (SQL: insert into `locations` (`name`, `location`) values (Coffee Shop 1, Point(51.509865, -0.118092)))

It looks like this needs something like Point::toWKT() applied to it, but I can't see how/where I'm meant to apply that automatically.

Do I need to handle some separate lat/long string values and convert them to a point on input? Perhaps with a mutator? Is there some input format that "just works"?

For the record (and which I've not seen documented anywhere), the JSON output format is:

"location":{"type":"Point","coordinates":[-0.118092,51.509865]}

Refactor SpatialTraits

Streamline API (parameter order):
Rearrange parameters of spatial analysis Eloquent scopes to be in the same order as the in the generated SQL.

How is this supposed to work?

Further to #39, I've been trying to use a point field via latitude and longitude virtual properties, but I can't make it behave usefully at all.

In my model, I've declared some fillable & location properties, much as in the provided example code:

protected $fillable = [
    'name',
    'address',
    'type',
    'longitude',
    'latitude',
];

protected $spatialFields = [
    'location',
];

location is defined in the database as a Laravel point type. longitude and latitude do not exist in the database, so I implemented them with accessors and mutators in the model like this:

public function getLongitudeAttribute()
{
    return $this->location->getLng();
}

public function getLatitudeAttribute()
{
    return $this->location->getLat();
}

public function setLongitudeAttribute($longitude)
{
    $this->location->setLng($longitude);
}

public function setLatitudeAttribute($latitude)
{
    $this->location->setLat($latitude);
}

Then I send a PUT request to update a record containing a param string:

name=Smurf+city&latitude=21.21&longitude=150.15&type=account&address=123+main+st

However, this fails in the first mutator it runs:

"message": "Undefined index: location",
"exception": "ErrorException",
"file": "/Users/marcus/Sites/app/Location.php",
"line": 65,

If I try to access location as a property in the mutator with $this->location->setLat($latitude);, I get an error because location is null (even though it's not allowed to be declared as nullable in the DB):

"message": "Call to a member function setLat() on null",
"exception": "Symfony\\Component\\Debug\\Exception\\FatalThrowableError",
"file": "/Users/marcus/Sites/app/Location.php",
"line": 65,

What's even more confusing is that I get results back in a format that doesn't reflect my settings - I don't understand why this includes a location property that doesn't appear in the fillable array, but not the latitude and longitude values that do:

{
    "id": 1,
    "created_at": "2018-03-16 16:39:47",
    "updated_at": "2018-03-16 16:39:49",
    "type": "account",
    "name": "Bernier Group",
    "address": "68914 Streich Springs Apt. 419\nVenabury, WI 39979-3229",
    "location": {
        "type": "Point",
        "coordinates": [
            -0.118092,
            51.509865
        ]
    }
},

This may be a broader Laravel question than something specific to this extension, but I don't know enough about either to tell. How should I be doing this?

Location and Area should also be listed in $fillable in model

I had a problem accessing latitude/longitude using $place->location->getLng().
I noticed that including location and area in $fillable solved the problem.

So, while location and area are both listed in $spatialFields, they should both also be listed in $fillable.

Geometry::fromWKB fails

Hello,

When decoding geometry data field from MySQL it fails for some reason with following exception:

"exception": "GeoIO\\WKB\\Parser\\Exception\\ParserException",
"message": "Parsing failed: Bad endian byte value 230.",
"trace": "#0 /home/vagrant/Code/xxx/public_html/vendor/grimzy/laravel-mysql-spatial/src/Types/Geometry.php(63): GeoIO\\WKB\\Parser\\Parser->parse('\\xE6\\x10\\x00\\x00\\x01\\x06\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x03...')\n#1 /home/vagrant/Code/xxx/public_html/vendor/grimzy/laravel-mysql-spatial/src/Eloquent/SpatialTrait.php(76): Grimzy\\LaravelMysqlSpatial\\Types\\Geometry::fromWKB('\\xE6\\x10\\x00\\x00\\x01\\x06\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x03...')\n#2 

This geometry contains multipolygon, have tested with geometry that contains point and worked fine.

Please see gist with all data required to reproduce issue: https://gist.github.com/deividaspetraitis/1d685fa1cdab0ad5719a07c4162edb57

Rearrange branches respective to MySQL versions

Have to do it because different MySQL versions have different spatial analysis function and their behavior is sometimes different.

Branches:

  • master: MySQL 5.7 and 8.0
  • mysql-5.6: MySQL 5.6

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

Object of class \Point could not be converted to string when saving

I could not make it work, I think I'm following the steps correctly.
I wanna put a simple point but it fails when saving

App\SportPlace.php

<?php

namespace App;

use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
use Illuminate\Database\Eloquent\Model;

class SportPlace extends Model
{

    use SpatialTrait;

    protected $fillable = [
        "status",
        "name",
        "latlng",
    ];

    protected $spatialFields = [
        'latlng',
    ];
$sp = new App\SportPlace();
>>> $point = new GeoJson\Geometry\Point([40.7484404, -73.9878441]);
=> GeoJson\Geometry\Point {#992}
>>> $sp->latlng = $point;
=> GeoJson\Geometry\Point {#992}
>>> $sp->save();
PHP Recoverable fatal error:  Object of class GeoJson\Geometry\Point could not be converted to string in /vendor/laravel/framework/src/Illuminate/Support/Str.php on line 33

Mysql 5.7.17
laravel-mysql-spatial 2.0.2
laravel 5.5.4

Updating point values

Setup: Laravel 5.5.x

Let's consider following table:

<?php 

$schema->create('classifieds_locations', function (Blueprint $table) {
    /...

    $table->geometry('location');

    /...
    
    $table->engine = 'InnoDB';
});

Model:

<?php 

use App\Entities\MariaDB\Model;
use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

class Location extends Model implements LocationModelInterface
{
    use SoftDeletes, SpatialTrait;

    /**
     * {@inheritdoc}
     */
    protected $table = 'locations';

    /**
     * {@inheritdoc}
     */
    public $timestamps = true;

    /**
     * {@inheritdoc}
     */
    protected $fillable = [
        0   =>  'location'
    ];

    /**
     * {@inheritdoc}
     */
    protected $spatialFields = [
        'location',
    ];

    /**
     * @inheritdoc
     */
    public function getLocation() : Point
    {
        return $this->getAttribute('location');
    }
    
    /**
     * @inheritdoc
     */
    public function setLocation(Point $point) : LocationModelInterface
    {
        $this->setAttribute('location', $point);
        return $this;
    }
}

When trying to update point values using following apporach is doesn't work because models both orinigal and attributes arrays are updated: $location->getLocation()->setLat(63.687515);

Any ideas why? It looks much nicer than workaround I've used to update values: $location->setLocation(63.687515, $location->getLocation()->getLng()));

Error when running migration

Hi, thanks by this awesome library. I'm trying it, but when I attempt to run a migration, this returns:

[Symfony\Component\Debug\Exception\FatalThrowableError]
Type error: Argument 1 passed to CreateStoresTable::{closure}() must be an instance of Grimzy\LaravelMysqlSpatial\Schema\Blueprint, instance of Ill
uminate\Database\Schema\Blueprint given, called in ...

I've imported the Grimzy\LaravelMysqlSpatial\Schema\Blueprint inside the migration, but this not runs.

Thanks by Help

point is in polygon

I create places table with name and location column
but location is not point
its polygon and i store polygon of a places in table

now how can i check the point is on which column

I try :

$s9 = new Point(38.021996, 46.3799);
$spaa = Place::find(3);
$spac = $spaa->location;
$result=$spac->contains('location',$s9);

but not work

BBox

Hello!
I'm trying to get points by bounding box. My code below.

$sw = new Point($bbox['min_y'], $bbox['min_x']);
$nw = new Point($bbox['max_y'], $bbox['min_x']);
$ne = new Point($bbox['max_y'], $bbox['max_x']);
$se = new Point($bbox['min_y'], $bbox['max_x']);

$geometry = new Polygon([
            new LineString([$sw, $nw]),
            new LineString([$nw, $ne]),
            new LineString([$ne, $se]),
            new LineString([$se, $sw]),
        ]);
$userPoints = UserPoint::intersects('geom', $geometry)->toSql();

$userPoints returns incorrect Polygon consisting of 4 LineStrings:

select * from `user_points` where st_intersects(`geom`, ST_GeomFromText('POLYGON((37.39128112793 55.523189221554,37.39128112793 55.936510173094),(37.39128112793 55.936510173094,37.976989746094 55.936510173094),(37.976989746094 55.936510173094,37.976989746094 55.523189221554),(37.976989746094 55.523189221554,37.39128112793 55.523189221554))'))

Of course, this sql can't find my POINT(37.72185 55.76129).

The right way to find my point is:

select * from `user_points` where st_intersects(`geom`, ST_GeomFromText('POLYGON((37.39128112793 55.523189221554, 37.39128112793 55.936510173094, 37.976989746094 55.936510173094, 37.976989746094 55.523189221554, 37.39128112793 55.523189221554))'))

I created this polygon from my code

$bbox = "POLYGON(($sw->toPair(), $nw->toPair(), $ne->toPair(), $se->toPair(), $sw->toPair()))";

But as I can see from your code, I can't insert WKT to scopes

$query->whereRaw("st_{$relationship}(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}'))");

What I want? I think, your Polygon is wrong, because it create 4 points, but not a polygon. You can test in with wicket.

Additional, I want to see bbox creation method and way to put in scopes my own WKT.
Thanks!

Select polygon from DB

I have an issue to pass the polygon data from DB to Client.
I save the polygon like this:

// Save item
$item = new Item($data);
...
$item->polygon = $this->buildPolygonFromArray($data['polygon']);
$item->save();

// Build polygon from array
use Grimzy\LaravelMysqlSpatial\Types\LineString;
use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;

private function buildPolygonFromArray($polygon) {
        $points = $polygon['coordinates'][0];
        $arrayOfPoints = [];
        foreach ($points as $point) {
            $arrayOfPoints[] = new Point($point[0], $point[1]);
        }
        $lineString = new LineString($arrayOfPoints);
        return new Polygon([$lineString]);
    }

Now the polygon is been selected automatically by laravel and passed to the client BUT the problem is that the latitude and longitude are been switched in positions.
I send this array with lat&long points:

'polygon' =>
                [
                    'coordinates' =>
                        [
                            0 => [
                                [34.783342, 32.075312],
                                [34.782876, 32.075323],
                                [34.782862, 32.074953],
                                [34.783407, 32.07494],
                                [34.783342, 32.075312],
                            ],
                        ]
                ]

On DB it's been saved on the opposite way (long&lat) because of the Point()->toPair() function but it is totally OK. The problem is with the select and passing to client.

The response I get in the network is like this:
{"type":"Polygon","coordinates":[[[32.075312,34.783342],[32.075323,34.782876],[32.074953,34.782862],[32.07494,34.783407],[32.075312,34.783342]]]}

When I'm going over the array the points are in Long&Lat format which is not good, I need it in the same format I create the polygon: [Lat&Long]

I thought about working with public function getPolygonAttribute($value) on the laravel side but still I need help here.

Thank you in advance,
Lior.

compatibility issue

Hi,

refere to laravel\framework commit of Add support for defining a Spatial reference system for a Point column. (code: ddc4e05fc03a8f55a56be2afdce48ba891879d65), they add srid to declearation of point method.

Due to what I mentioned above, it needs to make point method your Blueprint compatible.

check following error:

Declaration of Grimzy\LaravelMysqlSpatial\Schema\Blueprint::point($column) should be compatible with Illuminate\Database\Schema\Blueprint::point($column, $srid = NULL)

Use Point class in Model

Hi,

I have implemented this extension, and have managed to get most of it working. I would like to now use the Point object inside the Model. Essentially I would like to set an attribute value, so something like:
$this->attributes[ "location" ] = new Point( $lat, $lng );

However, the Point class is not available inside of the model. Is there a way to do this?

scopes are not working. I use laravel homestead.

Route::get('test', function () {
    $postData = collect(json_decode("[[-336.445313,82.118384],[580.429688,79.935918],[539.648438,-72.816074],[-281.601563,-76.840816],[-336.445313,82.118384]]"));

    $multiplePoints = $postData->transform(function ($data) {
        return new Point($data[1], $data[0]);
    });

    $polygon = new Polygon([new LineString($multiplePoints->toArray())]);
    
    dd(Metadata::doesTouch('map_data', $polygon)->get());
});

MetadataFactory

$factory->define(Metadata::class, function (Faker $faker) {
    $startPoint = new Point($faker->randomFloat(10, 14, 15), $faker->randomFloat(10, 121, 122));
    $linestring = new LineString([
            $startPoint,
            new Point($faker->randomFloat(10, 14, 15), $faker->randomFloat(10, 121, 122)),
            new Point($faker->randomFloat(10, 14, 15), $faker->randomFloat(10, 121, 122)),
            $startPoint,
        ]);


    return [
        'level' => mt_rand(1, 4),
        'map_data' => new Polygon([$linestring]),
    ];
});

mysql Ver 14.14 Distrib 5.7.19, for Linux (x86_64) using EditLine wrapper

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.