Skip to content

Commit 66d7b1c

Browse files
authored
Display filters and sortables. (#295)
* Display filters and sortables. * Apply fixes from StyleCI (#296) * Adding Searchable field * Apply fixes from StyleCI (#297) * Docs. * Apply fixes from StyleCI (#298)
1 parent e2a73c6 commit 66d7b1c

File tree

16 files changed

+348
-19
lines changed

16 files changed

+348
-19
lines changed

UPGRADING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Because there are many breaking changes an upgrade is not that easy. There are m
66

77
- Dropped support for laravel passport
88
- Now you have to explicitly define the `allowRestify` method in the model policy, by default Restify don't allow you to use repositories.
9-
- `viewAny` policy is not used anymore, you can delete it.
9+
- `viewAny` policy isn't used anymore, you can delete it.
1010
- The default exception handler is the Laravel one, see `restify.php -> handler`
1111
- `fillCallback` signature has changed
1212
- By default it will do not allow you to attach `belongsToMany` and `morphToMany` relationships. You will have to add `BelongsToMany` or `MorphToMany` field into your repository

config/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
'password_reset_url' => env('FRONTEND_APP_URL').'/password/reset?token={token}&email={email}',
4747

48-
'user_verify_url' => env('FRONTEND_APP_URL').'/verify?id={id}&hash={emailHash}',
48+
'user_verify_url' => env('FRONTEND_APP_URL').'/verify/{id}/{emailHash}',
4949
],
5050

5151
/*

docs/docs/4.0/auth/auth.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,20 @@ You'll finally enjoy the auth setup (`register`, `login`, `forgot` and `reset pa
99

1010
- Migrate the `personal_access_tokens` table, provided by sanctum.
1111

12+
- Install laravel sanctum. See the docs [here](https://laravel.com/docs/sanctum#installation). You don't need to add `\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,` in your `'api'` middleware group. So you only need to run these 3 commands:
13+
14+
```shell script
15+
composer require laravel/sanctum
16+
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
17+
php artisan migrate
18+
```
19+
1220
- Make sure your authenticatable entity (usually `App\Models\User`) implements: `Illuminate\Contracts\Auth\Authenticatable` (or simply extends the `Illuminate\Foundation\Auth\User` class as it does into a fresh laravel app.)
1321

1422
- Make sure the `App\Models\User` model implements the `Binaryk\LaravelRestify\Contracts\Sanctumable` contract.
1523

24+
- Add `\Laravel\Sanctum\HasApiTokens` trait to your `User` model.
25+
1626
## Define routes
1727

1828
Restify provides you a simple way to add all of your auth routes ready. Simply add in your `routes/api.php`:
@@ -137,7 +147,7 @@ This method could look like this:
137147

138148
public function sendEmailVerificationNotification()
139149
{
140-
$this->notify(new VerifyEmail);
150+
$this->notify(new \Binaryk\LaravelRestify\Notifications\VerifyEmail);
141151
}
142152
```
143153

docs/docs/4.0/custom-filters/custom-filters.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,9 @@ The response will look like this:
230230
]
231231
```
232232

233+
Along with custom filters, you can also include in the response the primary filters (as matches), by using `?include` query param:
234+
235+
```http request
236+
/api/restify/posts/filters?include=matches,searchables,sortables
237+
```
238+

docs/docs/4.0/filtering/filtering.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ request:
2020
GET: /api/restify/posts?search="Test title"
2121
```
2222

23+
### Get available searchables
24+
25+
You can use the following request to available searchable attributes for a repository:
26+
27+
```http request
28+
/api/restify/posts/filters?only=searchables
29+
```
30+
2331
## Match
2432

2533
Matching by specific attributes may be useful if you want an exact matching.
@@ -187,6 +195,14 @@ The next step is to associate this class with the match key name in your `$match
187195
];
188196
```
189197

198+
### Get available matches
199+
200+
You can use the following request to get all repository matches:
201+
202+
```http request
203+
/api/restify/posts/filters?only=matches
204+
```
205+
190206
## Sort
191207
When index query entities, usually we have to sort by specific attributes.
192208
This requires the `$sort` configuration:
@@ -217,10 +233,22 @@ or with plus sign before the field:
217233
GET: /api/restify/posts?sort=+id
218234
```
219235

236+
### Get available sorts
237+
238+
You can use the following request to get sortable attributes for a repository:
239+
240+
```http request
241+
/api/restify/posts/filters?only=sortables
242+
```
243+
244+
:::tip All filters
245+
You can use `/api/restify/posts/filters?only=sortables` request, and concatenate: `?only=sortables,matches, searchables` to get all of them at once.
246+
:::
247+
220248
## Eager loading - aka withs
221249

222250
When get a repository index or details about a single entity, often we have to get the related entities (we have access to).
223-
This eager loading is configurable by Restify as follow:
251+
This eager loading is configurable by Restify as following:
224252

225253
```php
226254
public static $related = ['posts'];
@@ -229,7 +257,7 @@ public static $related = ['posts'];
229257
This means that we could use `posts` query for eager loading posts:
230258

231259
```http request
232-
GET: /api/restify/users?with=posts
260+
GET: /api/restify/users?related=posts
233261
```
234262

235263
## Pagination

docs/docs/4.0/quickstart.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ One important configuration is the restify default middlewares:
7272

7373
### Sanctum authorization
7474

75-
Usually you want to authorize your api (allow access only to authenticated users). For this purpose you can simply add another middleware. For the `sanctum`, Restify provides `Binaryk\LaravelRestify\Http\Middleware\RestifySanctumAuthenticate` middleware.
75+
Usually you want to authorize your api (allow access only to authenticated users). For this purpose you can simply add another middleware. For the `sanctum`, Restify provides `Binaryk\LaravelRestify\Http\Middleware\RestifySanctumAuthenticate::class` middleware. Make sure you put this right after `api` middleware.
76+
77+
You may notice that Restify also use the `EnsureJsonApiHeaderMiddleware` middleware, which enforce you to use the `application/vnd.api+json` Accept header for your API requests. So make sure, even when using Postman (or something else) for making requests, that this `Accept header` is applied.
7678

7779
### Exception Handling
7880

docs/docs/4.0/repository-pattern/repository-pattern.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ Having this in place you're basically ready for the CRUD actions over posts. You
5656
| GET | `/api/restify/posts/{post}` | show |
5757
| POST | `/api/restify/posts` | store |
5858
| POST | `/api/restify/posts/bulk` | store multiple |
59-
| POST | `/api/restify/posts/bulk/update` | store multiple |
60-
| PATCH | `/api/restify/posts/{post}` | update |
61-
| PUT | `/api/restify/posts/{post}` | update |
62-
| POST | `/api/restify/posts/{post}` | update |
59+
| POST | `/api/restify/posts/bulk/update` | update multiple |
60+
| PATCH | `/api/restify/posts/{post}` | partial update |
61+
| PUT | `/api/restify/posts/{post}` | full update |
62+
| POST | `/api/restify/posts/{post}` | partial of full update including attachments |
6363
| DELETE | `/api/restify/posts/{post}` | destroy |
6464

6565
:::tip Update with files As you can see we provide 3 Verbs for the model update (PUT, PATCH, POST), the reason of that
@@ -195,14 +195,14 @@ You can customize the `meta` by creating your own `resolveShowMeta` method:
195195
}
196196
```
197197

198-
:::tip Resource property In the previous example we have used the `$this->resource` call, well, keep in mind, that you
198+
:::tip $resource property
199+
In the previous example we have used the `$this->resource` call, well, keep in mind, that you
199200
always have access to the current resource in your not static methods of the repository, were the resource is the actual
200201
current model. In the case above, the `$this->resource` represents the `Post` model with the `id=1`, because we're
201202
looking for the route: `/api/restify/posts/1`. A similar way to get the model is the `$this->model()` method.
202203
:::
203204

204-
Well, a lot of methods to modify the serialization partials, however, you are free to customize the entire response at
205-
once by defining:
205+
As we saw before, there are many ways to partially modify the response (ie separate way to modify meta), however, you are free to customize the entire response at once by defining:
206206

207207
```php
208208
// PostRepository.php

src/Filter.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Binaryk\LaravelRestify\Traits\Make;
77
use Closure;
88
use Illuminate\Http\Request;
9+
use Illuminate\Support\Str;
910
use JsonSerializable;
1011

1112
abstract class Filter implements JsonSerializable
@@ -18,6 +19,8 @@ abstract class Filter implements JsonSerializable
1819

1920
public $canSeeCallback;
2021

22+
public static $uriKey;
23+
2124
public function __construct()
2225
{
2326
$this->booted();
@@ -73,10 +76,31 @@ public function resolve(RestifyRequest $request, $filter)
7376
$this->value = $filter;
7477
}
7578

79+
/**
80+
* Get the URI key for the filter.
81+
*
82+
* @return string
83+
*/
84+
public static function uriKey()
85+
{
86+
if (property_exists(static::class, 'uriKey') && is_string(static::$uriKey)) {
87+
return static::$uriKey;
88+
}
89+
90+
$kebabWithoutRepository = Str::kebab(Str::replaceLast('Filter', '', class_basename(get_called_class())));
91+
92+
/**
93+
* e.g. UserRepository => users
94+
* e.g. LaravelEntityRepository => laravel-entities.
95+
*/
96+
return Str::plural($kebabWithoutRepository);
97+
}
98+
7699
public function jsonSerialize()
77100
{
78101
return [
79102
'class' => static::class,
103+
'key' => static::uriKey(),
80104
'type' => $this->getType(),
81105
'options' => collect($this->options(app(Request::class)))->map(function ($value, $key) {
82106
return is_array($value) ? ($value + ['property' => $key]) : ['label' => $key, 'property' => $value];

src/Filters/MatchFilter.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Filters;
4+
5+
use Binaryk\LaravelRestify\Filter;
6+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
7+
use Binaryk\LaravelRestify\Repositories\Repository;
8+
use Illuminate\Support\Collection;
9+
10+
class MatchFilter extends Filter
11+
{
12+
public $column = 'id';
13+
14+
public static $uriKey = 'matches';
15+
16+
public function filter(RestifyRequest $request, $query, $value)
17+
{
18+
//@todo improve this
19+
$query->where($this->column, $value);
20+
}
21+
22+
public static function makeFromSimple($column, $type): self
23+
{
24+
return tap(new static, function (MatchFilter $filter) use ($column, $type) {
25+
$filter->type = $type;
26+
$filter->column = $column;
27+
});
28+
}
29+
30+
public static function makeForRepository(Repository $repository): Collection
31+
{
32+
return collect($repository::getMatchByFields())->map(function ($type, $column) {
33+
return static::makeFromSimple($column, $type);
34+
})->values();
35+
}
36+
37+
public function jsonSerialize()
38+
{
39+
return [
40+
'class' => static::class,
41+
'type' => $this->getType(),
42+
'key' => static::uriKey(),
43+
'column' => $this->column,
44+
];
45+
}
46+
}

src/Filters/SearchableFilter.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Filters;
4+
5+
use Binaryk\LaravelRestify\Filter;
6+
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
7+
use Binaryk\LaravelRestify\Repositories\Repository;
8+
use Illuminate\Support\Collection;
9+
10+
class SearchableFilter extends Filter
11+
{
12+
public $column = 'id';
13+
14+
public static $uriKey = 'searchables';
15+
16+
public function filter(RestifyRequest $request, $query, $value)
17+
{
18+
//@todo improve this
19+
$query->where($this->column, 'LIKE', "%{$value}%");
20+
}
21+
22+
public static function makeFromSimple($column): self
23+
{
24+
return tap(new static, function (SearchableFilter $filter) use ($column) {
25+
$filter->column = $column;
26+
});
27+
}
28+
29+
public static function makeForRepository(Repository $repository): Collection
30+
{
31+
return collect($repository::getSearchableFields())->map(function ($column) {
32+
return static::makeFromSimple($column);
33+
});
34+
}
35+
36+
public function jsonSerialize()
37+
{
38+
return [
39+
'class' => static::class,
40+
'key' => static::uriKey(),
41+
'column' => $this->column,
42+
];
43+
}
44+
}

0 commit comments

Comments
 (0)