diff --git a/API.md b/API.md index 5e29149..d7814c0 100644 --- a/API.md +++ b/API.md @@ -69,6 +69,7 @@ An enum is provided with the following values: * [withDistanceSphere](#withDistanceSphere) * [whereDistanceSphere](#whereDistanceSphere) * [orderByDistanceSphere](#orderByDistanceSphere) +* [whereBuffer](#whereBuffer) * [whereWithin](#whereWithin) * [whereNotWithin](#whereNotWithin) * [whereContains](#whereContains) @@ -253,6 +254,29 @@ echo $places[1]->name; // first ``` +### whereBuffer + +Filters records within a buffer. Uses [ST_Buffer](https://dev.mysql.com/doc/refman/8.0/en/spatial-operator-functions.html#function_st-buffer). + +| parameter name | type | +|---------------------|---------------------| +| `$column` | `Geometry \ string` | +| `$geometryOrColumn` | `Geometry \ string` | +| `$value` | `int \ float` | + +
Example + +```php +Place::create(['location' => new Point(1, 1.5)]); + +$placesCountWithinBuffer = Place::query() + ->whereBuffer('location', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'), 3) + ->count(); + +echo $placesCountWithinBuffer; // 1 +``` +
+ ### whereWithin Filters records by the [ST_Within](https://dev.mysql.com/doc/refman/8.0/en/spatial-relation-functions-object-shapes.html#function_st-within) function. diff --git a/src/Traits/HasSpatial.php b/src/Traits/HasSpatial.php index 14816f0..6e64b45 100644 --- a/src/Traits/HasSpatial.php +++ b/src/Traits/HasSpatial.php @@ -160,6 +160,22 @@ public function scopeOrderByDistanceSphere( ); } + public function scopeWhereBuffer( + Builder $query, + ExpressionContract|Geometry|string $column, + ExpressionContract|Geometry|string $geometryOrColumn, + int|float $value + ): void { + $query->whereRaw( + sprintf( + 'ST_WITHIN(%s, ST_BUFFER(%s, ?))', + $this->toExpressionString($column), + $this->toExpressionString($geometryOrColumn), + ), + [$value], + ); + } + public function scopeWhereWithin( Builder $query, ExpressionContract|Geometry|string $column, diff --git a/tests/HasSpatialTest.php b/tests/HasSpatialTest.php index a949ae2..069c249 100644 --- a/tests/HasSpatialTest.php +++ b/tests/HasSpatialTest.php @@ -196,6 +196,22 @@ expect($testPlacesOrderedByDistance[0]->id)->toBe($fartherTestPlace->id); }); +it('filters by buffer', function (): void { + $polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}', Srid::WGS84->value); + $pointWithinBuffer = new Point(1, 1.5, Srid::WGS84->value); + $pointOutsideBuffer = new Point(10, 10, Srid::WGS84->value); + TestPlace::factory()->create(['point' => $pointWithinBuffer]); + TestPlace::factory()->create(['point' => $pointOutsideBuffer]); + + /** @var TestPlace[] $placesWithinBuffer */ + $placesWithinBuffer = TestPlace::query() + ->whereBuffer('point', $polygon, 3) + ->get(); + + expect($placesWithinBuffer)->toHaveCount(1); + expect($placesWithinBuffer[0]->point)->toEqual($pointWithinBuffer); +}); + it('filters by within', function (): void { $polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}', Srid::WGS84->value); $pointWithinPolygon = new Point(0, 0, Srid::WGS84->value);