Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2663cb0

Browse files
[Feature] Add has-one-through relationship (#429)
Adds a has-one-through relationship to work with the Eloquent relation of the same name that was added in Laravel 5.8.
1 parent 91dcd5f commit 2663cb0

File tree

18 files changed

+623
-9
lines changed

18 files changed

+623
-9
lines changed

‎docs/basics/adapters.md‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ for Eloquent models. The relationship types available are `belongsTo`, `hasOne`,
224224
| Eloquent | JSON API |
225225
| :-- | :-- |
226226
| `hasOne` | `hasOne` |
227+
| `hasOneThrough` | `hasOneThrough` |
227228
| `belongsTo` | `belongsTo` |
228229
| `hasMany` | `hasMany` |
229230
| `belongsToMany` | `hasMany` |
@@ -338,15 +339,16 @@ class Adapter extends AbstractAdapter
338339
}
339340
```
340341

341-
#### Has-Many-Through
342+
#### Has-One-Through and Has-Many-Through
342343

343-
The JSON API `hasManyThrough` relation can be used for an Eloquent `hasManyThrough` relation. The important thing
344-
to note about this relationship is it is **read-only**. This is because the relationship can be modified in your API
345-
by modifying the intermediary model. For example, a `countries` resource might have many `posts` resources through
346-
an intermediate `users` resource. The relationship is effectively modified by creating and deleting posts and/or a
347-
user changing which country they are associated to.
344+
The JSON API `hasOneThrough` and `hasManyThrough` relations can be used for an Eloquent `hasOneThrough`
345+
and `hasManyThrough` relation. The important thing to note about these relationships is that both are **read-only**.
346+
This is because the relationship can be modified in your API by modifying the intermediary model.
347+
For example, a `countries` resource might have many `posts` resources through an intermediate `users` resource.
348+
The relationship is effectively modified by creating and deleting posts and/or a user changing which country they
349+
are associated to.
348350

349-
Define a has-many-through relationship on an adapter as follows:
351+
Use the `hasOneThrough()` or `hasManyThrough()` methods on your adapter as follows:
350352

351353
```php
352354
class Adapter extends AbstractAdapter

‎src/Eloquent/AbstractAdapter.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,15 @@ protected function hasOne($modelKey = null)
555555
return new HasOne($modelKey ?: $this->guessRelation());
556556
}
557557

558+
/**
559+
* @param string|null $modelKey
560+
* @return HasOneThrough
561+
*/
562+
protected function hasOneThrough($modelKey = null)
563+
{
564+
return new HasOneThrough($modelKey ?: $this->guessRelation());
565+
}
566+
558567
/**
559568
* @param string|null $modelKey
560569
* @return HasMany

‎src/Eloquent/HasOneThrough.php‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* Copyright 2019 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace CloudCreativity\LaravelJsonApi\Eloquent;
19+
20+
use CloudCreativity\LaravelJsonApi\Exceptions\RuntimeException;
21+
use Illuminate\Database\Eloquent\Relations;
22+
use Neomerx\JsonApi\Contracts\Encoder\Parameters\EncodingParametersInterface;
23+
24+
class HasOneThrough extends BelongsTo
25+
{
26+
27+
/**
28+
* @inheritDoc
29+
*/
30+
public function update($record, array $relationship, EncodingParametersInterface $parameters)
31+
{
32+
throw new RuntimeException('Modifying a has-one-through Eloquent relation is not supported.');
33+
}
34+
35+
/**
36+
* @inheritDoc
37+
*/
38+
public function replace($record, array $relationship, EncodingParametersInterface $parameters)
39+
{
40+
throw new RuntimeException('Modifying a has-one-through Eloquent relation is not supported.');
41+
}
42+
43+
/**
44+
* @inheritdoc
45+
*/
46+
protected function acceptRelation($relation)
47+
{
48+
return $relation instanceof Relations\HasOneThrough;
49+
}
50+
}

‎tests/dummy/app/History.php‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace DummyApp;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
7+
8+
class History extends Model
9+
{
10+
11+
/**
12+
* @var array
13+
*/
14+
protected $fillable = ['detail'];
15+
16+
/**
17+
* @return BelongsTo
18+
*/
19+
public function user(): BelongsTo
20+
{
21+
return $this->belongsTo(User::class);
22+
}
23+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* Copyright 2019 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace DummyApp\JsonApi\Histories;
19+
20+
use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter;
21+
use DummyApp\History;
22+
use Illuminate\Support\Collection;
23+
24+
class Adapter extends AbstractAdapter
25+
{
26+
27+
/**
28+
* Adapter constructor.
29+
*/
30+
public function __construct()
31+
{
32+
parent::__construct(new History());
33+
}
34+
35+
/**
36+
* @inheritDoc
37+
*/
38+
protected function filter($query, Collection $filters)
39+
{
40+
// TODO: Implement filter() method.
41+
}
42+
43+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace DummyApp\JsonApi\Histories;
4+
5+
use DummyApp\History;
6+
use Neomerx\JsonApi\Schema\SchemaProvider;
7+
8+
class Schema extends SchemaProvider
9+
{
10+
11+
/**
12+
* @var string
13+
*/
14+
protected $resourceType = 'histories';
15+
16+
/**
17+
* @param History $resource
18+
* @return string
19+
*/
20+
public function getId($resource)
21+
{
22+
return (string) $resource->getRouteKey();
23+
}
24+
25+
/**
26+
* @param History $resource
27+
* @return array
28+
*/
29+
public function getAttributes($resource)
30+
{
31+
return ['detail' => $resource->detail];
32+
}
33+
34+
/**
35+
* @param History $resource
36+
* @param bool $isPrimary
37+
* @param array $includeRelationships
38+
* @return array
39+
*/
40+
public function getRelationships($resource, $isPrimary, array $includeRelationships)
41+
{
42+
return [
43+
'user' => [
44+
self::SHOW_SELF => false,
45+
self::SHOW_RELATED => false,
46+
self::SHOW_DATA => isset($includeRelationships['user']),
47+
self::DATA => static function () use ($resource) {
48+
return $resource->user;
49+
},
50+
],
51+
];
52+
}
53+
54+
55+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
/**
3+
* Copyright 2019 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace DummyApp\JsonApi\Histories;
19+
20+
use CloudCreativity\LaravelJsonApi\Validation\AbstractValidators;
21+
22+
class Validators extends AbstractValidators
23+
{
24+
25+
/**
26+
* @var array
27+
*/
28+
protected $allowedIncludePaths = ['user'];
29+
30+
/**
31+
* @var array
32+
*/
33+
protected $allowedSortParameters = [
34+
'created-at',
35+
'updated-at',
36+
];
37+
38+
/**
39+
* @inheritDoc
40+
*/
41+
protected function rules($record = null): array
42+
{
43+
return [
44+
'detail' => ['required', 'string'],
45+
];
46+
}
47+
48+
/**
49+
* @inheritDoc
50+
*/
51+
protected function queryRules(): array
52+
{
53+
return [];
54+
}
55+
56+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/**
3+
* Copyright 2019 Cloud Creativity Limited
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace DummyApp\JsonApi\Suppliers;
19+
20+
use CloudCreativity\LaravelJsonApi\Eloquent\AbstractAdapter;
21+
use CloudCreativity\LaravelJsonApi\Eloquent\HasOneThrough;
22+
use DummyApp\Supplier;
23+
use Illuminate\Support\Collection;
24+
25+
class Adapter extends AbstractAdapter
26+
{
27+
28+
/**
29+
* Adapter constructor.
30+
*/
31+
public function __construct()
32+
{
33+
parent::__construct(new Supplier());
34+
}
35+
36+
/**
37+
* @return HasOneThrough
38+
*/
39+
protected function userHistory(): HasOneThrough
40+
{
41+
return $this->hasOneThrough();
42+
}
43+
44+
/**
45+
* @inheritDoc
46+
*/
47+
protected function filter($query, Collection $filters)
48+
{
49+
// TODO: Implement filter() method.
50+
}
51+
52+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /