Skip to content

Commit 828daa1

Browse files
author
Hendrik Nijmeijer
committed
Add support for phpstan generics
1 parent 7b0e643 commit 828daa1

File tree

8 files changed

+103
-7
lines changed

8 files changed

+103
-7
lines changed

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,52 @@ N.B. This example uses our [swisnl/php-http-fixture-client](https://github.com/s
477477
This package allows you to easily mock requests with static fixtures.
478478
Definitely worth a try!
479479

480+
## Using generics
481+
482+
This package provides support for generic types in repositories and relationships,
483+
so your IDE can provide type hinting and auto-completion for the items you are working with.
484+
485+
This is achieved by using [generics in PHPDoc annotations](https://phpstan.org/blog/generics-in-php-using-phpdocs).
486+
487+
### Repositories
488+
489+
```php
490+
491+
/** @implements \Swis\JsonApi\Client\Interfaces\RepositoryInterface<BlogItem> */
492+
class BlogRepository extends \Swis\JsonApi\Client\Repository {...}
493+
494+
```
495+
496+
Now, when you use the `BlogRepository` class, your IDE understands the correct return types for the `all()`, `find()` and `save()` methods.
497+
498+
### Relationships
499+
500+
You can also use generics in your relationships to specify the type of the related item.
501+
Just use the `OneRelationInterface` or `ManyRelationInterface` interfaces in your relation method and specify the type of the related item:
502+
503+
```php
504+
505+
/** @return \Swis\JsonApi\Client\Interfaces\OneRelationInterface<AuthorItem> */
506+
public function author(): OneRelationInterface
507+
{
508+
return $this->hasOne(AuthorItem::class);
509+
}
510+
511+
```
512+
513+
This way, when accessing the `$blog->author()->getData()`, your IDE will understand that it returns an `AuthorItem` instance.
514+
515+
The same can be achieved for ManyRelations (`HasMany`, `MorphToMany`):
516+
517+
```php
518+
519+
/** @return \Swis\JsonApi\Client\Interfaces\ManyRelationInterface<AuthorItem> */
520+
public function comments(): ManyRelationInterface
521+
{
522+
return $this->hasMany(CommentItem::class);
523+
}
524+
525+
```
480526

481527
## Advanced usage
482528

src/Collection.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
use Swis\JsonApi\Client\Interfaces\DataInterface;
88

9+
/**
10+
* @template TKey of array-key
11+
* @template TValue of \Swis\JsonApi\Client\Interfaces\ItemInterface
12+
*
13+
* @extends \Illuminate\Support\Collection<TKey, TValue>
14+
*/
915
class Collection extends \Illuminate\Support\Collection implements DataInterface
1016
{
1117
/**

src/Concerns/HasRelations.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ trait HasRelations
2626
/**
2727
* Create a singular relation to another item.
2828
*
29+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
2930
*
30-
* @return \Swis\JsonApi\Client\Relations\HasOneRelation
31+
* @param class-string<TItem> $itemClass
32+
* @return \Swis\JsonApi\Client\Interfaces\OneRelationInterface<TItem>
3133
*/
3234
public function hasOne(string $itemClass, ?string $name = null): OneRelationInterface
3335
{
@@ -48,8 +50,10 @@ protected function newHasOne(string $type): OneRelationInterface
4850
/**
4951
* Create a plural relation to another item.
5052
*
53+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
5154
*
52-
* @return \Swis\JsonApi\Client\Relations\HasManyRelation
55+
* @param class-string<TItem> $itemClass
56+
* @return \Swis\JsonApi\Client\Interfaces\ManyRelationInterface<TItem>
5357
*/
5458
public function hasMany(string $itemClass, ?string $name = null): ManyRelationInterface
5559
{

src/Interfaces/CollectionDocumentInterface.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
namespace Swis\JsonApi\Client\Interfaces;
66

7+
/**
8+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
9+
*/
710
interface CollectionDocumentInterface extends DocumentInterface
811
{
912
/**
10-
* @return \Swis\JsonApi\Client\Collection
13+
* @return \Swis\JsonApi\Client\Collection<array-key, TItem>
1114
*/
1215
public function getData();
1316
}

src/Interfaces/ItemDocumentInterface.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
namespace Swis\JsonApi\Client\Interfaces;
66

7+
/**
8+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
9+
*/
710
interface ItemDocumentInterface extends DocumentInterface
811
{
912
/**
10-
* @return \Swis\JsonApi\Client\Interfaces\ItemInterface
13+
* @return TItem
1114
*/
1215
public function getData();
1316
}

src/Interfaces/ManyRelationInterface.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,20 @@
88
use Swis\JsonApi\Client\Links;
99
use Swis\JsonApi\Client\Meta;
1010

11+
/**
12+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
13+
*/
1114
interface ManyRelationInterface
1215
{
16+
/**
17+
* @param \Swis\JsonApi\Client\Collection<array-key, TItem>|null $data
18+
* @return static
19+
*/
1320
public function setData(?Collection $data);
1421

22+
/**
23+
* @return \Swis\JsonApi\Client\Collection<array-key, TItem>|null
24+
*/
1525
public function getData(): ?Collection;
1626

1727
public function hasData(): bool;
@@ -23,6 +33,7 @@ public function getIncluded(): Collection;
2333
public function hasIncluded(): bool;
2434

2535
/**
36+
* @param \Swis\JsonApi\Client\Collection<array-key, TItem> $included
2637
* @return static
2738
*/
2839
public function associate(Collection $included);

src/Interfaces/OneRelationInterface.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,38 @@
77
use Swis\JsonApi\Client\Links;
88
use Swis\JsonApi\Client\Meta;
99

10+
/**
11+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
12+
*/
1013
interface OneRelationInterface
1114
{
15+
/**
16+
* @param TItem|null $data
17+
* @return static
18+
*/
1219
public function setData(?ItemInterface $data);
1320

21+
/**
22+
* @return TItem|null
23+
*/
1424
public function getData(): ?ItemInterface;
1525

1626
public function hasData(): bool;
1727

28+
/**
29+
* @param TItem|null $included
30+
*/
1831
public function setIncluded(?ItemInterface $included);
1932

33+
/**
34+
* @return TItem|null
35+
*/
2036
public function getIncluded(): ?ItemInterface;
2137

2238
public function hasIncluded(): bool;
2339

2440
/**
41+
* @param TItem $included
2542
* @return static
2643
*/
2744
public function associate(ItemInterface $included);
@@ -31,6 +48,9 @@ public function associate(ItemInterface $included);
3148
*/
3249
public function dissociate();
3350

51+
/**
52+
* @return TItem|null
53+
*/
3454
public function getAssociated(): ?ItemInterface;
3555

3656
public function hasAssociated(): bool;

src/Interfaces/RepositoryInterface.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@
44

55
namespace Swis\JsonApi\Client\Interfaces;
66

7+
/**
8+
* @template TItem of \Swis\JsonApi\Client\Interfaces\ItemInterface
9+
*/
710
interface RepositoryInterface
811
{
912
/**
10-
* @return \Swis\JsonApi\Client\Interfaces\CollectionDocumentInterface
13+
* @return \Swis\JsonApi\Client\Interfaces\CollectionDocumentInterface<TItem>
1114
*/
1215
public function all();
1316

1417
/**
15-
* @return \Swis\JsonApi\Client\Interfaces\ItemDocumentInterface
18+
* @return \Swis\JsonApi\Client\Interfaces\ItemDocumentInterface<TItem>
1619
*/
1720
public function find(string $id);
1821

1922
/**
20-
* @return \Swis\JsonApi\Client\Interfaces\ItemDocumentInterface
23+
* @return \Swis\JsonApi\Client\Interfaces\ItemDocumentInterface<TItem>
2124
*/
2225
public function save(ItemInterface $item);
2326

0 commit comments

Comments
 (0)