Skip to content

Commit 208a1d5

Browse files
committed
Finish Laravel integration
1 parent 381768b commit 208a1d5

20 files changed

+759
-63
lines changed

README.md

+10-3
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,15 @@ use Tobyz\JsonApiServer\JsonApi;
4444

4545
class UsersResource extends EloquentResource
4646
{
47-
public readonly string $type = 'users';
48-
public readonly string $model = User::class;
47+
public function type(): string
48+
{
49+
return 'users';
50+
}
51+
52+
public function newModel(Context $context): object
53+
{
54+
return new User();
55+
}
4956

5057
public function endpoints(): array
5158
{
@@ -75,7 +82,7 @@ class UsersResource extends EloquentResource
7582

7683
public function filters(): array
7784
{
78-
return [Filter\WhereIdIn::make(), Filter\Where::make('name')];
85+
return [Filter\Where::make('id'), Filter\Where::make('name')];
7986
}
8087
}
8188

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
},
2424
"files": [
2525
"src/functions.php",
26-
"src/functions_laravel.php"
26+
"src/Laravel/functions.php"
2727
]
2828
},
2929
"autoload-dev": {

docs/index.md

+10-3
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,15 @@ use Tobyz\JsonApiServer\JsonApi;
4747

4848
class UsersResource extends EloquentResource
4949
{
50-
public readonly string $type = 'users';
51-
public readonly string $model = User::class;
50+
public function type(): string
51+
{
52+
return 'users';
53+
}
54+
55+
public function newModel(Context $context): object
56+
{
57+
return new User();
58+
}
5259

5360
public function endpoints(): array
5461
{
@@ -78,7 +85,7 @@ class UsersResource extends EloquentResource
7885

7986
public function filters(): array
8087
{
81-
return [Filter\WhereIdIn::make(), Filter\Where::make('name')];
88+
return [Filter\Where::make('id'), Filter\Where::make('name')];
8289
}
8390
}
8491

docs/laravel.md

+23-10
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,15 @@ use Tobyz\JsonApiServer\Laravel\EloquentResource;
4949

5050
class PostsResource extends EloquentResource
5151
{
52-
public readonly string $type = 'posts';
53-
public readonly string $model = Post::class;
52+
public function type(): string
53+
{
54+
return 'posts';
55+
}
56+
57+
public function newModel(Context $context): object
58+
{
59+
return new Post();
60+
}
5461

5562
public function endpoints(): array
5663
{
@@ -117,11 +124,11 @@ requests, and force delete a resource using a `DELETE` request.
117124

118125
To expose the soft-delete capability to the client, add the
119126
`Tobyz\JsonApiServer\Laravel\SoftDeletes` trait to your Eloquent resource, and a
120-
`Tobyz\JsonApiServer\Laravel\Fields\SoftDelete` field to your fields array:
127+
nullable `DateTime` field to your fields array:
121128

122129
```php
123-
use Tobyz\JsonApiServer\Laravel\Fields\SoftDelete; // [!code ++]
124130
use Tobyz\JsonApiServer\Laravel\SoftDeletes; // [!code ++]
131+
use Tobyz\JsonApiServer\Schema\Field\DateTime; // [!code ++]
125132

126133
class PostsResource extends EloquentResource
127134
{
@@ -132,20 +139,22 @@ class PostsResource extends EloquentResource
132139
public function fields(): array
133140
{
134141
return [
135-
SoftDelete::make('deletedAt'), // [!code ++]
142+
DateTime::make('deletedAt')->nullable(), // [!code ++]
136143
];
137144
}
138145
}
139146
```
140147

141148
If you prefer to use a boolean to indicate whether or not a resource is
142-
soft-deleted instead of a nullable date-time value, you can call the `asBoolean`
143-
method on the `SoftDelete` field:
149+
soft-deleted instead of a nullable date-time value, you can use a
150+
`BooleanDateTime` field instead:
144151

145152
```php
146-
SoftDelete::make('isDeleted')
153+
use Tobyz\JsonApiServer\Schema\Field\BooleanDateTime;
154+
155+
BooleanDateTime::make('isDeleted')
147156
->property('deleted_at')
148-
->asBoolean();
157+
->writable();
149158
```
150159

151160
## Filters
@@ -156,8 +165,12 @@ resources.
156165
### Where
157166

158167
```php
159-
Where::make('id');
160168
Where::make('name');
169+
Where::make('id')->commaSeparated();
170+
Where::make('isConfirmed')->asBoolean();
171+
Where::make('score')->asNumeric();
172+
WhereBelongsTo::make('user');
173+
Has::make('hasComments');
161174
WhereHas::make('comments');
162175
WhereDoesntHave::make('comments');
163176
WhereNull::make('draft')->property('published_at');

src/Laravel/EloquentBuffer.php

+10-26
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66
use Illuminate\Database\Eloquent\Model;
77
use Illuminate\Database\Eloquent\Relations\MorphTo;
88
use Tobyz\JsonApiServer\Context;
9-
use Tobyz\JsonApiServer\Schema\Relationship;
10-
11-
use function Tobyz\JsonApiServer\run_callbacks;
9+
use Tobyz\JsonApiServer\Schema\Field\Relationship;
1210

1311
abstract class EloquentBuffer
1412
{
15-
private static $buffer = [];
13+
private static array $buffer = [];
1614

1715
public static function add(Model $model, string $relationName): void
1816
{
@@ -43,32 +41,22 @@ public static function load(
4341
// may be multiple if this is a polymorphic relationship. We
4442
// start by getting the resource types this relationship
4543
// could possibly contain.
46-
$resourceTypes = $context->getApi()->getResourceTypes();
44+
$resources = $context->api->resources;
4745

48-
if ($type = $relationship->getType()) {
49-
if (is_string($type)) {
50-
$resourceTypes = [$resourceTypes[$type]];
51-
} else {
52-
$resourceTypes = array_intersect_key($resourceTypes, array_flip($type));
53-
}
46+
if ($type = $relationship->types) {
47+
$resources = array_intersect_key($resources, array_flip($type));
5448
}
5549

5650
// Now, construct a map of model class names -> scoping
5751
// functions. This will be provided to the MorphTo::constrain
5852
// method in order to apply type-specific scoping.
5953
$constrain = [];
6054

61-
foreach ($resourceTypes as $resourceType) {
62-
if (
63-
($model = $resourceType->getAdapter()->model()) &&
64-
!isset($constrain[get_class($model)])
65-
) {
66-
$constrain[get_class($model)] = function ($query) use (
67-
$resourceType,
68-
$context,
69-
) {
70-
$resourceType->applyScopes($query, $context);
71-
};
55+
foreach ($resources as $resource) {
56+
$modelClass = get_class($resource->newModel($context));
57+
58+
if ($resource instanceof EloquentResource && !isset($constrain[$modelClass])) {
59+
$constrain[$modelClass] = fn($query) => $resource->scope($query, $context);
7260
}
7361
}
7462

@@ -77,10 +65,6 @@ public static function load(
7765
} else {
7866
reset($constrain)($query);
7967
}
80-
81-
// Also apply any local scopes that have been defined on this
82-
// relationship.
83-
run_callbacks($relationship->getListeners('scope'), [$query, $context]);
8468
},
8569
]);
8670

0 commit comments

Comments
 (0)