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

Commit 49b0daf

Browse files
authored
Merge pull request #119 from grimzy/srid
MySQL 8 SRID support
2 parents 7f62564 + e3bcd37 commit 49b0daf

34 files changed

+895
-504
lines changed

‎.travis.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ php:
66
- '7.0'
77
- '7.1'
88
- '7.2'
9+
- '7.3'
910

1011
env:
11-
- MYSQL_VERSION=5.7
1212
- MYSQL_VERSION=8.0
1313

1414
dist: trusty

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
V=5.7
1+
V=8.0
22
DB_DIR=$(shell pwd)/_db-$(V)
33
mV=10.3
44
mDB_DIR=$(shell pwd)/_db-$(mV)

‎README.md‎

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,29 @@ Please check the documentation for your MySQL version. MySQL's Extension for Spa
1313
**Versions**
1414

1515
- `1.x.x`: MySQL 5.6 (also supports MySQL 5.5 but not all spatial analysis functions)
16-
- `2.x.x`: MySQL 5.7 and 8.0
16+
- `2.x.x`: MySQL 5.7
17+
- **`3.x.x`: MySQL 8.0 with SRID support (Current branch)**
1718

1819
This 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.
1920

2021
## Installation
2122

2223
Add the package using composer:
2324

25+
```sh
26+
$ composer require grimzy/laravel-mysql-spatial
27+
```
28+
29+
For MySQL 5.7:
30+
2431
```shell
25-
composer require grimzy/laravel-mysql-spatial
32+
$ composer require grimzy/laravel-mysql-spatial:^2.0
2633
```
2734

2835
For MySQL 5.6 and 5.5:
2936

3037
```shell
31-
composer require grimzy/laravel-mysql-spatial:^1.0
38+
$ composer require grimzy/laravel-mysql-spatial:^1.0
3239
```
3340

3441
For Laravel versions before 5.5 or if not using auto-discovery, register the service provider in `config/app.php`:
@@ -80,6 +87,19 @@ class CreatePlacesTable extends Migration {
8087
$table->polygon('area')->nullable();
8188
$table->timestamps();
8289
});
90+
91+
// Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid)
92+
93+
// Schema::create('places', function(Blueprint $table)
94+
// {
95+
// $table->increments('id');
96+
// $table->string('name')->unique();
97+
// // Add a Point spatial data field named location with SRID 4326
98+
// $table->point('location', 4326)->nullable();
99+
// // Add a Polygon spatial data field named area with SRID 4326
100+
// $table->polygon('area', 4326)->nullable();
101+
// $table->timestamps();
102+
// });
83103
}
84104

85105
/**
@@ -158,11 +178,37 @@ $place1->area = new Polygon([new LineString([
158178
new Point(40.74894149554006, -73.98615270853043)
159179
])]);
160180
$place1->save();
181+
```
182+
183+
Or if your database fields were created with a specific SRID:
184+
185+
```php
186+
use Grimzy\LaravelMysqlSpatial\Types\Point;
187+
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
188+
use Grimzy\LaravelMysqlSpatial\Types\LineString;
189+
190+
$place1 = new Place();
191+
$place1->name = 'Empire State Building';
161192

162-
$place1->area = new Polygon();
193+
// saving a point with SRID 4326 (WGS84 spheroid)
194+
$place1->location = new Point(40.7484404, -73.9878441, 4326); // (lat, lng, srid)
195+
$place1->save();
163196

197+
// saving a polygon with SRID 4326 (WGS84 spheroid)
198+
$place1->area = new Polygon([new LineString([
199+
new Point(40.74894149554006, -73.98615270853043),
200+
new Point(40.74848633046773, -73.98648262023926),
201+
new Point(40.747925497790725, -73.9851602911949),
202+
new Point(40.74837050671544, -73.98482501506805),
203+
new Point(40.74894149554006, -73.98615270853043)
204+
])], 4326);
205+
$place1->save();
164206
```
165207

208+
> **Note**: When saving collection Geometries (`LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, and `GeometryCollection`), only the top-most geometry should have an SRID set in the constructor.
209+
>
210+
> 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.
211+
166212
### Retrieving a model
167213

168214
```php
@@ -177,13 +223,13 @@ $lng = $place2->location->getLng(); // -73.9878441
177223

178224
| Grimzy\LaravelMysqlSpatial\Types | OpenGIS Class |
179225
| ------------------------------------------------------------ | ------------------------------------------------------------ |
180-
| `Point($lat, $lng)` | [Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) |
181-
| `MultiPoint(Point[])` | [MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) |
182-
| `LineString(Point[])` | [LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) |
183-
| `MultiLineString(LineString[])` | [MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) |
184-
| `Polygon(LineString[])` *([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) |
185-
| `MultiPolygon(Polygon[])` | [MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) |
186-
| `GeometryCollection(Geometry[])` | [GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) |
226+
| `Point($lat, $lng, $srid = 0)` | [Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html) |
227+
| `MultiPoint(Point[], $srid = 0)` | [MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html) |
228+
| `LineString(Point[], $srid = 0)` | [LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html) |
229+
| `MultiLineString(LineString[], $srid = 0)` | [MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html) |
230+
| `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) |
231+
| `MultiPolygon(Polygon[], $srid = 0)` | [MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html) |
232+
| `GeometryCollection(Geometry[], $srid = 0)` | [GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html) |
187233

188234
Check out the [Class diagram](https://user-images.githubusercontent.com/1837678/30788608-a5afd894-a16c-11e7-9a51-0a08b331d4c4.png).
189235

@@ -193,7 +239,7 @@ In order for your Eloquent Model to handle the Geometry classes, it must use the
193239

194240
#### IteratorAggregate and ArrayAccess
195241

196-
The "composite" 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:
242+
The 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:
197243

198244
```php
199245
$polygon = $multipolygon[10]; // ArrayAccess
@@ -207,10 +253,10 @@ for($polygon as $i => $linestring) {
207253

208254
#### Helpers
209255

210-
##### From/To Well Known Text ([WKT](https://dev.mysql.com/doc/refman/5.7/en/gis-data-formats.html#gis-wkt-format))
256+
##### From/To Well Known Text ([WKT](https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-wkt-format))
211257

212258
```php
213-
// fromWKT($wkt)
259+
// fromWKT($wkt, $srid = 0)
214260
$point = Point::fromWKT('POINT(2 1)');
215261
$point->toWKT(); // POINT(2 1)
216262

@@ -221,9 +267,9 @@ $polygon->toWKT(); // POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
221267
##### From/To String
222268

223269
```php
224-
// fromString($wkt)
270+
// fromString($wkt, $srid = 0)
225271
$point = new Point(1, 2); // lat, lng
226-
(string)$point // lng, lat: 2 1
272+
(string)$point // lng, lat: 2 1
227273

228274
$polygon = Polygon::fromString('(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)');
229275
(string)$polygon; // (0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)
@@ -255,9 +301,9 @@ To deserialize a GeoJSON string into a Geometry class, you can use `Geometry::fr
255301

256302
```php
257303
$location = Geometry::fromJson('{"type":"Point","coordinates":[3.4,1.2]}');
258-
$location instanceof Point::class;// true
259-
$location->getLat();// 1.2
260-
$location->getLng()); // 3.4
304+
$location instanceof Point::class;// true
305+
$location->getLat();// 1.2
306+
$location->getLng()); // 3.4
261307
```
262308

263309
## Scopes: Spatial analysis functions
@@ -280,10 +326,10 @@ Available scopes:
280326
- `overlaps($geometryColumn, $geometry)`
281327
- `doesTouch($geometryColumn, $geometry)`
282328
- `orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')`
283-
- `orderByDistance($geometryColumn, $geometry, $direction = 'asc')`
284-
- `orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')`
329+
- `orderByDistance($geometryColumn, $geometry, $direction = 'asc')`
330+
- `orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')`
285331

286-
*Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf. [documentation](https://dev.mysql.com/doc/refman/5.7/en/spatial-function-reference.html)).*
332+
*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)).*
287333

288334
## Migrations
289335

@@ -300,16 +346,16 @@ class CreatePlacesTable extends Migration {
300346

301347
### Columns
302348

303-
Available [MySQL Spatial Types](https://dev.mysql.com/doc/refman/5.7/en/spatial-datatypes.html) migration blueprints:
349+
Available [MySQL Spatial Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) migration blueprints:
304350

305-
- `$table->geometry('column_name')`
306-
- `$table->point('column_name')`
307-
- `$table->lineString('column_name')`
308-
- `$table->polygon('column_name')`
309-
- `$table->multiPoint('column_name')`
310-
- `$table->multiLineString('column_name')`
311-
- `$table->multiPolygon('column_name')`
312-
- `$table->geometryCollection('column_name')`
351+
- `$table->geometry(string $column_name, int $srid = 0)`
352+
- `$table->point(string $column_name, int $srid = 0)`
353+
- `$table->lineString(string $column_name, int $srid = 0)`
354+
- `$table->polygon(string $column_name, int $srid = 0)`
355+
- `$table->multiPoint(string $column_name, int $srid = 0)`
356+
- `$table->multiLineString(string $column_name, int $srid = 0)`
357+
- `$table->multiPolygon(string $column_name, int $srid = 0)`
358+
- `$table->geometryCollection(string $column_name, int $srid = 0)`
313359

314360
### Spatial indexes
315361

@@ -318,9 +364,9 @@ You can add or drop spatial indexes in your migrations with the `spatialIndex` a
318364
- `$table->spatialIndex('column_name')`
319365
- `$table->dropSpatialIndex(['column_name'])` or `$table->dropSpatialIndex('index_name')`
320366

321-
Note about spatial indexes from the [MySQL documentation](https://dev.mysql.com/doc/refman/5.7/en/creating-spatial-indexes.html):
367+
Note about spatial indexes from the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/creating-spatial-indexes.html):
322368

323-
> For [`MyISAM`](https://dev.mysql.com/doc/refman/5.7/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`.
369+
> 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`.
324370
325371
Also please read this [**important note**](https://laravel.com/docs/5.5/migrations#indexes) regarding Index Lengths in the Laravel 5.6 documentation.
326372

@@ -381,18 +427,18 @@ class UpdatePlacesTable extends Migration
381427
## Tests
382428

383429
```shell
384-
composer test
430+
$ composer test
385431
# or
386-
composer test:unit
387-
composer test:integration
432+
$ composer test:unit
433+
$ composer test:integration
388434
```
389435

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

392438
```shell
393-
make start_db # starts MySQL 8.0
439+
$ make start_db # starts MySQL 8.0
394440
# or
395-
make start_db V=5.7# starts a MySQL 5.7
441+
$ make start_db V=5.7# starts MySQL 5.7
396442
```
397443

398444
## Contributing

‎composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
},
4444
"extra": {
4545
"branch-alias": {
46-
"dev-master": "2.0.x-dev"
46+
"dev-master": "3.0.x-dev"
4747
},
4848
"laravel": {
4949
"providers": [

‎src/Eloquent/BaseBuilder.php‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@ class BaseBuilder extends QueryBuilder
88
{
99
protected function cleanBindings(array $bindings)
1010
{
11-
$bindings = array_map(function ($binding) {
12-
return $binding instanceof SpatialExpression ? $binding->getSpatialValue() : $binding;
13-
}, $bindings);
11+
$spatialBindings = [];
12+
foreach ($bindings as &$binding) {
13+
if ($binding instanceof SpatialExpression) {
14+
$spatialBindings[] = $binding->getSpatialValue();
15+
$spatialBindings[] = $binding->getSrid();
16+
} else {
17+
$spatialBindings[] = $binding;
18+
}
19+
}
1420

15-
return parent::cleanBindings($bindings);
21+
return parent::cleanBindings($spatialBindings);
1622
}
1723
}

‎src/Eloquent/SpatialExpression.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ class SpatialExpression extends Expression
88
{
99
public function getValue()
1010
{
11-
return 'ST_GeomFromText(?)';
11+
return "ST_GeomFromText(?, ?, 'axis-order=long-lat')";
1212
}
1313

1414
public function getSpatialValue()
1515
{
1616
return $this->value->toWkt();
1717
}
18+
19+
public function getSrid()
20+
{
21+
return $this->value->getSrid();
22+
}
1823
}

‎src/Eloquent/SpatialTrait.php‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ public function scopeDistance($query, $geometryColumn, $geometry, $distance)
134134
{
135135
$this->isColumnAllowed($geometryColumn);
136136

137-
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) <= ?", [
137+
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) <= ?", [
138138
$geometry->toWkt(),
139+
$geometry->getSrid(),
139140
$distance,
140141
]);
141142

@@ -148,8 +149,9 @@ public function scopeDistanceExcludingSelf($query, $geometryColumn, $geometry, $
148149

149150
$query = $this->scopeDistance($query, $geometryColumn, $geometry, $distance);
150151

151-
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) != 0", [
152+
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) != 0", [
152153
$geometry->toWkt(),
154+
$geometry->getSrid(),
153155
]);
154156

155157
return $query;
@@ -165,17 +167,19 @@ public function scopeDistanceValue($query, $geometryColumn, $geometry)
165167
$query->select('*');
166168
}
167169

168-
$query->selectRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) as distance", [
170+
$query->selectRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) as distance", [
169171
$geometry->toWkt(),
172+
$geometry->getSrid(),
170173
]);
171174
}
172175

173176
public function scopeDistanceSphere($query, $geometryColumn, $geometry, $distance)
174177
{
175178
$this->isColumnAllowed($geometryColumn);
176179

177-
$query->whereRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?)) <= ?", [
180+
$query->whereRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) <= ?", [
178181
$geometry->toWkt(),
182+
$geometry->getSrid(),
179183
$distance,
180184
]);
181185

@@ -188,8 +192,9 @@ public function scopeDistanceSphereExcludingSelf($query, $geometryColumn, $geome
188192

189193
$query = $this->scopeDistanceSphere($query, $geometryColumn, $geometry, $distance);
190194

191-
$query->whereRaw("st_distance_sphere($geometryColumn, ST_GeomFromText(?)) != 0", [
195+
$query->whereRaw("st_distance_sphere($geometryColumn, ST_GeomFromText(?, ?, 'axis-order=long-lat')) != 0", [
192196
$geometry->toWkt(),
197+
$geometry->getSrid(),
193198
]);
194199

195200
return $query;
@@ -204,8 +209,9 @@ public function scopeDistanceSphereValue($query, $geometryColumn, $geometry)
204209
if (!$columns) {
205210
$query->select('*');
206211
}
207-
$query->selectRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?)) as distance", [
212+
$query->selectRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) as distance", [
208213
$geometry->toWkt(),
214+
$geometry->getSrid(),
209215
]);
210216
}
211217

@@ -217,8 +223,9 @@ public function scopeComparison($query, $geometryColumn, $geometry, $relationshi
217223
throw new UnknownSpatialRelationFunction($relationship);
218224
}
219225

220-
$query->whereRaw("st_{$relationship}(`$geometryColumn`, ST_GeomFromText(?))", [
226+
$query->whereRaw("st_{$relationship}(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat'))", [
221227
$geometry->toWkt(),
228+
$geometry->getSrid(),
222229
]);
223230

224231
return $query;
@@ -272,8 +279,9 @@ public function scopeOrderBySpatial($query, $geometryColumn, $geometry, $orderFu
272279
throw new UnknownSpatialFunctionException($orderFunction);
273280
}
274281

275-
$query->orderByRaw("st_{$orderFunction}(`$geometryColumn`, ST_GeomFromText(?)) {$direction}", [
282+
$query->orderByRaw("st_{$orderFunction}(`$geometryColumn`, ST_GeomFromText(?, ?, 'axis-order=long-lat')) {$direction}", [
276283
$geometry->toWkt(),
284+
$geometry->getSrid(),
277285
]);
278286

279287
return $query;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /