Skip to content

Commit ad46d82

Browse files
dominikbAlexVanderbist
authored andcommitted
Enable the usage of an alias for a column name when using Sorts (#164)
* allow for alias on sort * Fix tests and add column name to sort class * drop array syntax for aliasing allowed sorts adjust documentation * drop test for array syntax * add hyperlink to readme
1 parent f3087c5 commit ad46d82

File tree

5 files changed

+83
-12
lines changed

5 files changed

+83
-12
lines changed

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ use Spatie\QueryBuilder\Filter;
184184

185185
// GET /users?filter[name]=John
186186
$users = QueryBuilder::for(User::class)
187-
->allowedFilters(Filter::exact('name', 'user_name')) // public filter, column name
187+
->allowedFilters(Filter::exact('name', 'user_name')) // public filter, column name
188188
->get();
189189
// filter by the column 'user_name'
190190
```
@@ -383,6 +383,21 @@ $users = QueryBuilder::for(User::class)
383383
// $users will be sorted by name in ascending order with a secondary sort on street in descending order.
384384
```
385385

386+
#### Using an alias for sorting
387+
388+
There may be occasions where it is not appropriate to expose the column name to the user.
389+
390+
Similar to using [an alias when filtering](#property-column-alias) you can do this with for sorts as well.
391+
392+
The column name can be passed as optional parameter and defaults to the property string.
393+
394+
``` php
395+
// GET /users?sort=-street
396+
$users = QueryBuilder::for(User::class)
397+
->allowedSorts(Sort::field('street', 'actual_column_street')
398+
->get();
399+
```
400+
386401
### Selecting specific columns
387402

388403
Sometimes you'll want to fetch only a couple fields to reduce the overall size of your SQL query. This can be done using the `fields` query parameter. The following fetch only the users' `id` and `name`

src/Filter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
class Filter
1313
{
14-
/** @var string */
14+
/** @var string|\Spatie\QueryBuilder\Filters\Filter */
1515
protected $filterClass;
1616

1717
/** @var string */
@@ -23,7 +23,7 @@ class Filter
2323
/** @var Collection */
2424
protected $ignored;
2525

26-
public function __construct(string $property, $filterClass, $columnName = null)
26+
public function __construct(string $property, $filterClass, ?string $columnName = null)
2727
{
2828
$this->property = $property;
2929

@@ -47,7 +47,7 @@ public function filter(Builder $builder, $value)
4747
($filterClass)($builder, $valueToFilter, $this->columnName);
4848
}
4949

50-
public static function exact(string $property, $columnName = null) : self
50+
public static function exact(string $property, ?string $columnName = null) : self
5151
{
5252
return new static($property, FiltersExact::class, $columnName);
5353
}

src/QueryBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ protected function filterDuplicates(Collection $sorts): Collection
317317

318318
return $sorts->reject(function (string $sort) use ($orders) {
319319
$toSort = [
320-
'column' => ltrim($sort, '-'),
320+
'column' => ltrim($sort, '-'),
321321
'direction' => ($sort[0] === '-') ? 'desc' : 'asc',
322322
];
323323
foreach ($orders as $order) {

src/Sort.php

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,24 @@ class Sort
1212
/** @var string */
1313
protected $sortClass;
1414

15-
/** @var string */
15+
/** @var string|\Spatie\QueryBuilder\Sorts\Sort */
1616
protected $property;
1717

1818
/** @var string */
1919
protected $defaultDirection;
2020

21-
public function __construct(string $property, $sortClass)
21+
/** @var string */
22+
protected $columnName;
23+
24+
public function __construct(string $property, $sortClass, ?string $columnName = null)
2225
{
2326
$this->property = ltrim($property, '-');
27+
2428
$this->sortClass = $sortClass;
29+
2530
$this->defaultDirection = static::parsePropertyDirection($property);
31+
32+
$this->columnName = $columnName ?? $property;
2633
}
2734

2835
public static function parsePropertyDirection(string $property): string
@@ -36,17 +43,17 @@ public function sort(Builder $builder, ?bool $descending = null)
3643

3744
$descending = $descending ?? ($this->defaultDirection === SortDirection::DESCENDING);
3845

39-
($sortClass)($builder, $descending, $this->property);
46+
($sortClass)($builder, $descending, $this->columnName);
4047
}
4148

42-
public static function field(string $property) : self
49+
public static function field(string $property, ?string $columnName = null) : self
4350
{
44-
return new static($property, SortsField::class);
51+
return new static($property, SortsField::class, $columnName);
4552
}
4653

47-
public static function custom(string $property, $sortClass) : self
54+
public static function custom(string $property, $sortClass, ?string $columnName = null) : self
4855
{
49-
return new static($property, $sortClass);
56+
return new static($property, $sortClass, $columnName);
5057
}
5158

5259
public function getProperty(): string
@@ -67,4 +74,9 @@ private function resolveSortClass(): CustomSort
6774

6875
return new $this->sortClass;
6976
}
77+
78+
public function getColumnName(): string
79+
{
80+
return $this->columnName;
81+
}
7082
}

tests/SortTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Support\Facades\DB;
88
use Spatie\QueryBuilder\QueryBuilder;
99
use Illuminate\Database\Eloquent\Builder;
10+
use Spatie\QueryBuilder\Sorts\SortsField;
1011
use Spatie\QueryBuilder\Tests\Models\TestModel;
1112
use Spatie\QueryBuilder\Exceptions\InvalidSortQuery;
1213
use Spatie\QueryBuilder\Sorts\Sort as SortInterface;
@@ -177,6 +178,49 @@ public function __invoke(Builder $query, $descending, string $property) : Builde
177178
$this->assertSortedAscending($sortedModels, 'name');
178179
}
179180

181+
/** @test */
182+
public function it_can_take_an_argument_for_custom_column_name_resolution()
183+
{
184+
$sort = Sort::custom('property_name', SortsField::class, 'property_column_name');
185+
186+
$this->assertInstanceOf(Sort::class, $sort);
187+
$this->assertClassHasAttribute('columnName', get_class($sort));
188+
}
189+
190+
/** @test */
191+
public function it_sets_property_column_name_to_property_name_by_default()
192+
{
193+
$sort = Sort::custom('property_name', SortsField::class);
194+
195+
$this->assertEquals($sort->getProperty(), $sort->getColumnName());
196+
}
197+
198+
/** @test */
199+
public function it_resolves_queries_using_property_column_name()
200+
{
201+
$sort = Sort::custom('nickname', SortsField::class, 'name');
202+
203+
$testModel = TestModel::create(['name' => 'zzzzzzzz']);
204+
205+
$models = $this
206+
->createQueryFromSortRequest('nickname')
207+
->allowedSorts($sort)
208+
->get();
209+
210+
$this->assertSorted($models, 'name');
211+
$this->assertTrue($testModel->is($models->last()));
212+
}
213+
214+
/** @test */
215+
public function it_can_sort_descending_with_an_alias()
216+
{
217+
$this->createQueryFromSortRequest('-exposed_property_name')
218+
->allowedSorts(Sort::field('exposed_property_name', 'name'))
219+
->get();
220+
221+
$this->assertQueryExecuted('select * from "test_models" order by "name" desc');
222+
}
223+
180224
protected function createQueryFromSortRequest(string $sort): QueryBuilder
181225
{
182226
$request = new Request([

0 commit comments

Comments
 (0)