Skip to content

Commit 67239f3

Browse files
authored
Merge pull request #5 from tarfin-labs/optimizations
Optimizations for Point class and HasSpatial trait.
2 parents 818edf4 + 365e337 commit 67239f3

File tree

8 files changed

+149
-79
lines changed

8 files changed

+149
-79
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
All notable changes to `laravel-spatial` will be documented in this file
44

5-
## 1.2.0 - 2012-02-08
5+
## 1.3.0 - 2022-06-24
6+
- `toWkt()` method added to `Point` class for getting the coordinates as well known text.
7+
- `toPair()` method added to `Point` class for getting the coordinates as pair.
8+
- `toArray()` method added to `Point` class for getting the coordinates as array.
9+
10+
## 1.2.0 - 2022-02-08
611
- Laravel 9 support added.
712

813
# 1.1.2 - 2022-03-08

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,33 @@ Address::create([
208208
]);
209209
```
210210

211+
#### Usage in Resource:
212+
To get an array representation of a location-casted field from a resource, you can return `parent::toArray($request)`.
213+
214+
If you need to return a custom array from a resource, you can use the `toArray()` method of the `Point` object.
215+
216+
```php
217+
class LocationResource extends JsonResource
218+
{
219+
public function toArray($request)
220+
{
221+
return [
222+
'location' => $this->location->toArray(),
223+
];
224+
}
225+
}
226+
```
227+
228+
Either way, you will get the following output for the location casted field:
229+
230+
```json
231+
{
232+
"lat": 25.45634,
233+
"lng": 35.54331,
234+
"srid": 4326
235+
}
236+
```
237+
211238
### Testing
212239

213240
```bash

src/Casts/LocationCast.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace TarfinLabs\LaravelSpatial\Casts;
66

7-
use Exception;
7+
use InvalidArgumentException;
88
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
99
use Illuminate\Contracts\Database\Eloquent\SerializesCastableAttributes;
1010
use Illuminate\Database\Query\Expression;
@@ -35,24 +35,22 @@ public function get($model, string $key, $value, array $attributes): ?Point
3535
public function set($model, string $key, $value, array $attributes): Expression
3636
{
3737
if (!$value instanceof Point) {
38-
throw new Exception(message: 'The '.$key.' field must be instance of '.Point::class);
38+
throw new InvalidArgumentException(
39+
sprintf('The %s field must be instance of %s', $key, Point::class)
40+
);
3941
}
4042

4143
if ($value->getSrid() > 0) {
4244
return DB::raw(
43-
value: "ST_GeomFromText('POINT({$value->getLng()} {$value->getLat()})', {$value->getSrid()}, 'axis-order=long-lat')"
45+
value: "ST_GeomFromText('{$value->toWkt()}', {$value->getSrid()}, 'axis-order=long-lat')"
4446
);
4547
}
4648

47-
return DB::raw(value: "ST_GeomFromText('POINT({$value->getLng()} {$value->getLat()})')");
49+
return DB::raw(value: "ST_GeomFromText('{$value->toWkt()}')");
4850
}
4951

5052
public function serialize($model, string $key, $value, array $attributes): array
5153
{
52-
return [
53-
'lat' => $value->getLat(),
54-
'lng' => $value->getLng(),
55-
'srid' => $value->getSrid(),
56-
];
54+
return $value->toArray();
5755
}
5856
}

src/Traits/HasSpatial.php

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,46 @@ public function scopeSelectDistanceTo(Builder $query, string $column, Point $poi
1818
$query->select('*');
1919
}
2020

21-
$query->selectRaw("ST_Distance(
22-
ST_SRID({$column}, ?),
23-
ST_SRID(Point(?, ?), ?)
24-
) as distance", [
25-
$point->getSrid(),
26-
$point->getLng(),
27-
$point->getLat(),
28-
$point->getSrid(),
29-
]);
21+
$query->selectRaw(
22+
"ST_Distance(ST_SRID({$column}, ?), ST_SRID(Point(?, ?), ?)) as distance",
23+
[
24+
$point->getSrid(),
25+
$point->getLng(),
26+
$point->getLat(),
27+
$point->getSrid(),
28+
]
29+
);
3030
}
3131

3232
public function scopeWithinDistanceTo(Builder $query, string $column, Point $point, int $distance): void
3333
{
34-
$query->whereRaw("ST_Distance(
35-
ST_SRID({$column}, ?),
36-
ST_SRID(Point(?, ?), ?)
37-
) <= ?", [...[
38-
$point->getSrid(),
39-
$point->getLng(),
40-
$point->getLat(),
41-
$point->getSrid(),
42-
], $distance]);
34+
$query->whereRaw(
35+
"ST_Distance(ST_SRID({$column}, ?), ST_SRID(Point(?, ?), ?)) <= ?",
36+
[
37+
...[
38+
$point->getSrid(),
39+
$point->getLng(),
40+
$point->getLat(),
41+
$point->getSrid(),
42+
],
43+
$distance,
44+
]
45+
);
4346
}
4447

4548
public function scopeOrderByDistanceTo(Builder $query, string $column, Point $point, string $direction = 'asc'): void
4649
{
4750
$direction = strtolower($direction) === 'asc' ? 'asc' : 'desc';
4851

49-
$query->orderByRaw("ST_Distance(
50-
ST_SRID({$column}, ?),
51-
ST_SRID(Point(?, ?), ?)
52-
) ".$direction, [
53-
$point->getSrid(),
54-
$point->getLng(),
55-
$point->getLat(),
56-
$point->getSrid(),
57-
]);
52+
$query->orderByRaw(
53+
"ST_Distance(ST_SRID({$column}, ?), ST_SRID(Point(?, ?), ?)) " . $direction,
54+
[
55+
$point->getSrid(),
56+
$point->getLng(),
57+
$point->getLat(),
58+
$point->getSrid(),
59+
]
60+
);
5861
}
5962

6063
public function newQuery(): Builder

src/Types/Point.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,23 @@ public function getSrid(): int
3636
{
3737
return $this->srid;
3838
}
39+
40+
public function toWkt(): string
41+
{
42+
return sprintf('POINT(%s)', $this->toPair());
43+
}
44+
45+
public function toPair(): string
46+
{
47+
return "{$this->getLng()} {$this->getLat()}";
48+
}
49+
50+
public function toArray(): array
51+
{
52+
return [
53+
'lat' => $this->lat,
54+
'lng' => $this->lng,
55+
'srid' => $this->srid,
56+
];
57+
}
3958
}

tests/HasSpatialTest.php

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77

88
class HasSpatialTest extends TestCase
99
{
10-
/**
11-
* @test
12-
* @see
13-
*/
10+
/** @test */
1411
public function it_generates_sql_query_for_selectDistanceTo_scope(): void
1512
{
1613
// Arrange
@@ -22,18 +19,12 @@ public function it_generates_sql_query_for_selectDistanceTo_scope(): void
2219

2320
// Assert
2421
$this->assertEquals(
25-
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr, ST_Distance(
26-
ST_SRID($castedAttr, ?),
27-
ST_SRID(Point(?, ?), ?)
28-
) as distance from `addresses`",
22+
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr, ST_Distance(ST_SRID($castedAttr, ?), ST_SRID(Point(?, ?), ?)) as distance from `addresses`",
2923
actual: $query->toSql()
3024
);
3125
}
3226

33-
/**
34-
* @test
35-
* @see
36-
*/
27+
/** @test */
3728
public function it_generates_sql_query_for_withinDistanceTo_scope(): void
3829
{
3930
// 1. Arrange
@@ -45,18 +36,12 @@ public function it_generates_sql_query_for_withinDistanceTo_scope(): void
4536

4637
// 3. Assert
4738
$this->assertEquals(
48-
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` where ST_Distance(
49-
ST_SRID($castedAttr, ?),
50-
ST_SRID(Point(?, ?), ?)
51-
) <= ?",
39+
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` where ST_Distance(ST_SRID($castedAttr, ?), ST_SRID(Point(?, ?), ?)) <= ?",
5240
actual: $query->toSql()
5341
);
5442
}
5543

56-
/**
57-
* @test
58-
* @see
59-
*/
44+
/** @test */
6045
public function it_generates_sql_query_for_orderByDistanceTo_scope(): void
6146
{
6247
// 1. Arrange
@@ -69,26 +54,17 @@ public function it_generates_sql_query_for_orderByDistanceTo_scope(): void
6954

7055
// 3. Assert
7156
$this->assertEquals(
72-
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` order by ST_Distance(
73-
ST_SRID($castedAttr, ?),
74-
ST_SRID(Point(?, ?), ?)
75-
) asc",
57+
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` order by ST_Distance(ST_SRID($castedAttr, ?), ST_SRID(Point(?, ?), ?)) asc",
7658
actual: $queryForAsc->toSql()
7759
);
7860

7961
$this->assertEquals(
80-
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` order by ST_Distance(
81-
ST_SRID($castedAttr, ?),
82-
ST_SRID(Point(?, ?), ?)
83-
) desc",
62+
expected: "select *, CONCAT(ST_AsText(addresses.$castedAttr, 'axis-order=long-lat'), ',', ST_SRID(addresses.$castedAttr)) as $castedAttr from `addresses` order by ST_Distance(ST_SRID($castedAttr, ?), ST_SRID(Point(?, ?), ?)) desc",
8463
actual: $queryForDesc->toSql()
8564
);
8665
}
8766

88-
/**
89-
* @test
90-
* @see
91-
*/
67+
/** @test */
9268
public function it_generates_sql_query_for_location_casted_attributes(): void
9369
{
9470
// 1. Arrange
@@ -102,10 +78,7 @@ public function it_generates_sql_query_for_location_casted_attributes(): void
10278
);
10379
}
10480

105-
/**
106-
* @test
107-
* @see
108-
*/
81+
/** @test */
10982
public function it_returns_location_casted_attributes(): void
11083
{
11184
// 1. Arrange

tests/LocationCastTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace TarfinLabs\LaravelSpatial\Tests;
44

5-
use Exception;
5+
use InvalidArgumentException;
66
use Illuminate\Support\Facades\DB;
77
use TarfinLabs\LaravelSpatial\Casts\LocationCast;
88
use TarfinLabs\LaravelSpatial\Tests\TestModels\Address;
@@ -16,10 +16,10 @@ public function it_throws_an_exception_if_casted_attribute_set_to_a_non_point_va
1616
// 1. Arrange
1717
$address = new Address();
1818

19-
// 3. Expect
20-
$this->expectException(Exception::class);
19+
// 2. Expect
20+
$this->expectException(InvalidArgumentException::class);
2121

22-
// 2. Act
22+
// 3. Act
2323
$address->location = 'dummy';
2424
}
2525

@@ -36,7 +36,7 @@ public function it_can_set_the_casted_attribute_to_a_point(): void
3636
$response = $cast->set($address, 'location', $point, $address->getAttributes());
3737

3838
// 3. Assert
39-
$this->assertEquals(DB::raw("ST_GeomFromText('POINT({$point->getLng()} {$point->getLat()})')"), $response);
39+
$this->assertEquals(DB::raw("ST_GeomFromText('{$point->toWkt()}')"), $response);
4040
}
4141

4242
/** @test */
@@ -52,7 +52,7 @@ public function it_can_set_the_casted_attribute_to_a_point_with_srid(): void
5252
$response = $cast->set($address, 'location', $point, $address->getAttributes());
5353

5454
// 3. Assert
55-
$this->assertEquals(DB::raw("ST_GeomFromText('POINT({$point->getLng()} {$point->getLat()})', {$point->getSrid()}, 'axis-order=long-lat')"), $response);
55+
$this->assertEquals(DB::raw("ST_GeomFromText('{$point->toWkt()}', {$point->getSrid()}, 'axis-order=long-lat')"), $response);
5656
}
5757

5858
/** @test */

tests/PointTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,49 @@ public function it_returns_default_srid_in_config_if_it_is_not_null(): void
5252
$this->assertSame(expected: 0.0, actual: $point->getLng());
5353
$this->assertSame(expected: 4326, actual: $point->getSrid());
5454
}
55+
56+
/** @test */
57+
public function it_returns_point_as_wkt(): void
58+
{
59+
// 1. Arrange
60+
$point = new Point(25.1515, 36.1212, 4326);
61+
62+
// 2. Act
63+
$wkt = $point->toWkt();
64+
65+
// 3. Assert
66+
$this->assertSame("POINT({$point->getLng()} {$point->getLat()})", $wkt);
67+
}
68+
69+
/** @test */
70+
public function it_returns_point_as_pair(): void
71+
{
72+
// 1. Arrange
73+
$point = new Point(25.1515, 36.1212, 4326);
74+
75+
// 2. Act
76+
$pair = $point->toPair();
77+
78+
// 3. Assert
79+
$this->assertSame("{$point->getLng()} {$point->getLat()}", $pair);
80+
}
81+
82+
/** @test */
83+
public function it_returns_points_as_array(): void
84+
{
85+
// 1. Arrange
86+
$point = new Point(25.1515, 36.1212, 4326);
87+
88+
// 2. Act
89+
$array = $point->toArray();
90+
91+
$expected = [
92+
'lat' => $point->getLat(),
93+
'lng' => $point->getLng(),
94+
'srid' => $point->getSrid(),
95+
];
96+
97+
// 3. Assert
98+
$this->assertSame($expected, $array);
99+
}
55100
}

0 commit comments

Comments
 (0)