Skip to content

Commit 78c96b5

Browse files
committed
Merge remote-tracking branch 'dutch-and-bold/ISSUE-48'
2 parents 254aa68 + 2827313 commit 78c96b5

File tree

7 files changed

+127
-10
lines changed

7 files changed

+127
-10
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
},
1818
"require-dev": {
1919
"phpunit/phpunit": "~4.8||~5.7",
20-
"mockery/mockery": "^0.9.9",
20+
"mockery/mockery": "^1.1.0",
2121
"laravel/laravel": "^5.2",
2222
"doctrine/dbal": "^2.5",
2323
"laravel/browser-kit-testing": "^2.0",

docker-compose.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: '3.3'
2+
services:
3+
db:
4+
image: mysql:5.7
5+
ports:
6+
- "3306:3306"
7+
environment:
8+
MYSQL_DATABASE: 'spatial_test'
9+
MYSQL_ROOT_PASSWORD: ''
10+
MYSQL_ALLOW_EMPTY_PASSWORD: 1

src/Eloquent/BaseBuilder.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Grimzy\LaravelMysqlSpatial\Eloquent;
4+
5+
use Illuminate\Database\Query\Builder;
6+
7+
class BaseBuilder extends Builder
8+
{
9+
protected function cleanBindings(array $bindings)
10+
{
11+
$bindings = array_map(function ($binding) {
12+
return $binding instanceof SpatialExpression ? $binding->getSpatialValue() : $binding;
13+
}, $bindings);
14+
15+
return parent::cleanBindings($bindings);
16+
}
17+
}

src/Eloquent/Builder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ public function update(array $values)
2020

2121
protected function asWKT(GeometryInterface $geometry)
2222
{
23-
return $this->getQuery()->raw("ST_GeomFromText('".$geometry->toWKT()."')");
23+
return new SpatialExpression($geometry);
2424
}
2525
}

src/Eloquent/SpatialExpression.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Grimzy\LaravelMysqlSpatial\Eloquent;
4+
5+
use Illuminate\Database\Query\Expression;
6+
7+
class SpatialExpression extends Expression
8+
{
9+
public function getValue()
10+
{
11+
return 'ST_GeomFromText(?)';
12+
}
13+
14+
public function getSpatialValue()
15+
{
16+
return $this->value->toWkt();
17+
}
18+
}

src/Eloquent/SpatialTrait.php

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Grimzy\LaravelMysqlSpatial\Eloquent;
44

55
use Grimzy\LaravelMysqlSpatial\Exceptions\SpatialFieldsNotDefinedException;
6+
use Grimzy\LaravelMysqlSpatial\Exceptions\UnknownSpatialRelationFunction;
67
use Grimzy\LaravelMysqlSpatial\Types\Geometry;
78
use Grimzy\LaravelMysqlSpatial\Types\GeometryInterface;
89
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
@@ -37,6 +38,17 @@ trait SpatialTrait
3738

3839
public $geometries = [];
3940

41+
protected $stRelations = [
42+
'within',
43+
'crosses',
44+
'contains',
45+
'disjoint',
46+
'equals',
47+
'intersects',
48+
'overlaps',
49+
'touches',
50+
];
51+
4052
/**
4153
* Create a new Eloquent query builder for the model.
4254
*
@@ -49,12 +61,21 @@ public function newEloquentBuilder($query)
4961
return new Builder($query);
5062
}
5163

64+
protected function newBaseQueryBuilder()
65+
{
66+
$connection = $this->getConnection();
67+
68+
return new BaseBuilder(
69+
$connection, $connection->getQueryGrammar(), $connection->getPostProcessor()
70+
);
71+
}
72+
5273
protected function performInsert(EloquentBuilder $query, array $options = [])
5374
{
5475
foreach ($this->attributes as $key => $value) {
5576
if ($value instanceof GeometryInterface) {
5677
$this->geometries[$key] = $value; //Preserve the geometry objects prior to the insert
57-
$this->attributes[$key] = $this->getConnection()->raw(sprintf("ST_GeomFromText('%s')", $value->toWKT()));
78+
$this->attributes[$key] = new SpatialExpression($value);
5879
}
5980
}
6081

@@ -89,61 +110,105 @@ public function getSpatialFields()
89110
}
90111
}
91112

113+
public function isColumnAllowed($geometryColumn)
114+
{
115+
if (!in_array($geometryColumn, $this->getSpatialFields())) {
116+
throw new SpatialFieldsNotDefinedException();
117+
}
118+
119+
return true;
120+
}
121+
92122
public function scopeDistance($query, $geometryColumn, $geometry, $distance)
93123
{
94-
$query->whereRaw("st_distance(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) <= {$distance}");
124+
$this->isColumnAllowed($geometryColumn);
125+
126+
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) <= ?", [
127+
$geometry->toWkt(),
128+
$distance,
129+
]);
95130

96131
return $query;
97132
}
98133

99134
public function scopeDistanceExcludingSelf($query, $geometryColumn, $geometry, $distance)
100135
{
136+
$this->isColumnAllowed($geometryColumn);
137+
101138
$query = $this->scopeDistance($query, $geometryColumn, $geometry, $distance);
102139

103-
$query->whereRaw("st_distance(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) != 0");
140+
$query->whereRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) != 0", [
141+
$geometry->toWkt(),
142+
]);
104143

105144
return $query;
106145
}
107146

108147
public function scopeDistanceValue($query, $geometryColumn, $geometry)
109148
{
149+
$this->isColumnAllowed($geometryColumn);
150+
110151
$columns = $query->getQuery()->columns;
111152

112153
if (!$columns) {
113154
$query->select('*');
114155
}
115-
$query->selectRaw("st_distance(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) as distance");
156+
157+
$query->selectRaw("st_distance(`$geometryColumn`, ST_GeomFromText(?)) as distance", [
158+
$geometry->toWkt(),
159+
]);
116160
}
117161

118162
public function scopeDistanceSphere($query, $geometryColumn, $geometry, $distance)
119163
{
120-
$query->whereRaw("st_distance_sphere(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) <= {$distance}");
164+
$this->isColumnAllowed($geometryColumn);
165+
166+
$query->whereRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?)) <= ?", [
167+
$geometry->toWkt(),
168+
$distance,
169+
]);
121170

122171
return $query;
123172
}
124173

125174
public function scopeDistanceSphereExcludingSelf($query, $geometryColumn, $geometry, $distance)
126175
{
176+
$this->isColumnAllowed($geometryColumn);
177+
127178
$query = $this->scopeDistanceSphere($query, $geometryColumn, $geometry, $distance);
128179

129-
$query->whereRaw("st_distance_sphere(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) != 0");
180+
$query->whereRaw("st_distance_sphere($geometryColumn, ST_GeomFromText(?)) != 0", [
181+
$geometry->toWkt(),
182+
]);
130183

131184
return $query;
132185
}
133186

134187
public function scopeDistanceSphereValue($query, $geometryColumn, $geometry)
135188
{
189+
$this->isColumnAllowed($geometryColumn);
190+
136191
$columns = $query->getQuery()->columns;
137192

138193
if (!$columns) {
139194
$query->select('*');
140195
}
141-
$query->selectRaw("st_distance_sphere(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) as distance");
196+
$query->selectRaw("st_distance_sphere(`$geometryColumn`, ST_GeomFromText(?)) as distance", [
197+
$geometry->toWkt(),
198+
]);
142199
}
143200

144201
public function scopeComparison($query, $geometryColumn, $geometry, $relationship)
145202
{
146-
$query->whereRaw("st_{$relationship}(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}'))");
203+
$this->isColumnAllowed($geometryColumn);
204+
205+
if (!in_array($relationship, $this->stRelations)) {
206+
throw new UnknownSpatialRelationFunction($relationship);
207+
}
208+
209+
$query->whereRaw("st_{$relationship}(`$geometryColumn`, ST_GeomFromText(?))", [
210+
$geometry->toWkt(),
211+
]);
147212

148213
return $query;
149214
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Grimzy\LaravelMysqlSpatial\Exceptions;
4+
5+
class UnknownSpatialRelationFunction extends \RuntimeException
6+
{
7+
}

0 commit comments

Comments
 (0)