Skip to content

Commit 7305504

Browse files
efinder2mfn
andauthored
Created a positiblity to add custom relation type (#987)
* Created a positiblity to add custom relation type * Changed access modifier Co-authored-by: Markus Podar <[email protected]> * fixed hints from code review * Added Test for #987 * composer fix-style * Clarify doc in config entry * Update CHANGELOG.md Co-authored-by: Markus Podar <[email protected]>
1 parent 186340b commit 7305504

File tree

9 files changed

+201
-21
lines changed

9 files changed

+201
-21
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
77

88
### Added
99
- Fix phpdoc generate for custom cast with parameter [\#986 / artelkr](https://github.com/barryvdh/laravel-ide-helper/pull/986)
10+
- Created a possibility to add custom relation type [\#987 / efinder2](https://github.com/barryvdh/laravel-ide-helper/pull/987)
1011

1112
2020-09-07, 2.8.1
1213
-----------------

config/ide-helper.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,17 @@
253253
|
254254
*/
255255
'force_fqn' => false,
256+
257+
/*
258+
|--------------------------------------------------------------------------
259+
| Additional relation types
260+
|--------------------------------------------------------------------------
261+
|
262+
| Sometimes it's needed to create custom relation types. The key of the array
263+
| is the Relationship Method name. The value of the array is the canonical class
264+
| name of the Relationship, e.g. `'relationName' => RelationShipClass::class`.
265+
|
266+
*/
267+
'additional_relation_types' => [],
268+
256269
];

src/Console/ModelsCommand.php

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@
1919
use Illuminate\Console\Command;
2020
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
2121
use Illuminate\Database\Eloquent\Model;
22+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
23+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
24+
use Illuminate\Database\Eloquent\Relations\HasMany;
25+
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
26+
use Illuminate\Database\Eloquent\Relations\HasOne;
27+
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
28+
use Illuminate\Database\Eloquent\Relations\MorphMany;
29+
use Illuminate\Database\Eloquent\Relations\MorphOne;
30+
use Illuminate\Database\Eloquent\Relations\MorphTo;
31+
use Illuminate\Database\Eloquent\Relations\MorphToMany;
2232
use Illuminate\Database\Eloquent\Relations\Relation;
2333
use Illuminate\Filesystem\Filesystem;
2434
use Illuminate\Support\Str;
@@ -36,6 +46,20 @@
3646
*/
3747
class ModelsCommand extends Command
3848
{
49+
protected const RELATION_TYPES = [
50+
'hasMany' => HasMany::class,
51+
'hasManyThrough' => HasManyThrough::class,
52+
'hasOneThrough' => HasOneThrough::class,
53+
'belongsToMany' => BelongsToMany::class,
54+
'hasOne' => HasOne::class,
55+
'belongsTo' => BelongsTo::class,
56+
'morphOne' => MorphOne::class,
57+
'morphTo' => MorphTo::class,
58+
'morphMany' => MorphMany::class,
59+
'morphToMany' => MorphToMany::class,
60+
'morphedByMany' => MorphToMany::class,
61+
];
62+
3963
/**
4064
* @var Filesystem $files
4165
*/
@@ -561,19 +585,7 @@ protected function getPropertiesFromMethods($model)
561585
$code = substr($code, $begin, strrpos($code, '}') - $begin + 1);
562586

563587
foreach (
564-
[
565-
'hasMany' => '\Illuminate\Database\Eloquent\Relations\HasMany',
566-
'hasManyThrough' => '\Illuminate\Database\Eloquent\Relations\HasManyThrough',
567-
'hasOneThrough' => '\Illuminate\Database\Eloquent\Relations\HasOneThrough',
568-
'belongsToMany' => '\Illuminate\Database\Eloquent\Relations\BelongsToMany',
569-
'hasOne' => '\Illuminate\Database\Eloquent\Relations\HasOne',
570-
'belongsTo' => '\Illuminate\Database\Eloquent\Relations\BelongsTo',
571-
'morphOne' => '\Illuminate\Database\Eloquent\Relations\MorphOne',
572-
'morphTo' => '\Illuminate\Database\Eloquent\Relations\MorphTo',
573-
'morphMany' => '\Illuminate\Database\Eloquent\Relations\MorphMany',
574-
'morphToMany' => '\Illuminate\Database\Eloquent\Relations\MorphToMany',
575-
'morphedByMany' => '\Illuminate\Database\Eloquent\Relations\MorphToMany',
576-
] as $relation => $impl
588+
$this->getRelationTypes() as $relation => $impl
577589
) {
578590
$search = '$this->' . $relation . '(';
579591
if (stripos($code, $search) || ltrim($impl, '\\') === ltrim((string)$type, '\\')) {
@@ -600,14 +612,6 @@ protected function getPropertiesFromMethods($model)
600612
get_class($relationObj->getRelated())
601613
);
602614

603-
$relations = [
604-
'hasManyThrough',
605-
'belongsToMany',
606-
'hasMany',
607-
'morphMany',
608-
'morphToMany',
609-
'morphedByMany',
610-
];
611615
if (strpos(get_class($relationObj), 'Many') !== false) {
612616
//Collection or array of models (because Collection is Arrayable)
613617
$relatedClass = '\\' . get_class($relationObj->getRelated());
@@ -929,6 +933,15 @@ protected function getCollectionClass($className)
929933
return '\\' . get_class($model->newCollection());
930934
}
931935

936+
/**
937+
* Returns the available relation types
938+
*/
939+
protected function getRelationTypes(): array
940+
{
941+
$configuredRelations = $this->laravel['config']->get('ide-helper.additional_relation_types', []);
942+
return array_merge(self::RELATION_TYPES, $configuredRelations);
943+
}
944+
932945
/**
933946
* @return bool
934947
*/

tests/Console/ModelsCommand/Relations/Models/Simple.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models;
66

77
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\ModelsOtherNamespace\AnotherModel;
8+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Traits\HasTestRelations;
89
use Illuminate\Database\Eloquent\Model;
910
use Illuminate\Database\Eloquent\Relations\BelongsTo;
1011
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@@ -17,6 +18,8 @@
1718

1819
class Simple extends Model
1920
{
21+
use HasTestRelations;
22+
2023
// Regular relations
2124
public function relationHasMany(): HasMany
2225
{
@@ -84,4 +87,14 @@ public function relationBelongsToSameNameAsColumn(): BelongsTo
8487
{
8588
return $this->belongsTo(AnotherModel::class, __FUNCTION__);
8689
}
90+
91+
public function relationSampleToManyRelationType()
92+
{
93+
return $this->testToOneRelation(Simple::class);
94+
}
95+
96+
public function relationSampleRelationType()
97+
{
98+
return $this->testToManyRelation(Simple::class);
99+
}
87100
}

tests/Console/ModelsCommand/Relations/Test.php

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

77
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
88
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
9+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types\SampleToManyRelationType;
10+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types\SampleToOneRelationType;
11+
use Illuminate\Support\Facades\Config;
912

1013
class Test extends AbstractModelsCommand
1114
{
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
Config::set('ide-helper.additional_relation_types', [
20+
'testToOneRelation' => SampleToOneRelationType::class,
21+
'testToManyRelation' => SampleToManyRelationType::class,
22+
]);
23+
}
24+
1225
public function test(): void
1326
{
1427
$command = $this->app->make(ModelsCommand::class);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Traits;
6+
7+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types\SampleToManyRelationType;
8+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types\SampleToOneRelationType;
9+
10+
trait HasTestRelations
11+
{
12+
public function testToOneRelation($related)
13+
{
14+
$instance = $this->newRelatedInstance($related);
15+
return new SampleToOneRelationType($instance->newQuery(), $this);
16+
}
17+
18+
public function testToManyRelation($related)
19+
{
20+
$instance = $this->newRelatedInstance($related);
21+
return new SampleToManyRelationType($instance->newQuery(), $this);
22+
}
23+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types;
6+
7+
use Illuminate\Database\Eloquent\Collection;
8+
use Illuminate\Database\Eloquent\Relations\Relation;
9+
10+
class SampleToManyRelationType extends Relation
11+
{
12+
public function addConstraints()
13+
{
14+
// Fake
15+
}
16+
17+
public function addEagerConstraints(array $models)
18+
{
19+
// Fake
20+
}
21+
22+
public function initRelation(array $models, $relation)
23+
{
24+
// Fake
25+
}
26+
27+
public function match(array $models, Collection $results, $relation)
28+
{
29+
// Fake
30+
}
31+
32+
public function getResults()
33+
{
34+
// Fake
35+
}
36+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Types;
6+
7+
use Illuminate\Database\Eloquent\Collection;
8+
use Illuminate\Database\Eloquent\Model;
9+
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
10+
use Illuminate\Database\Eloquent\Relations\Relation;
11+
12+
/**
13+
* Sample for custom relation
14+
*
15+
* the relation is a big fake and only for testing of the docblock generation
16+
*
17+
* @package Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations
18+
*/
19+
class SampleToOneRelationType extends Relation
20+
{
21+
use SupportsDefaultModels;
22+
23+
public function addConstraints()
24+
{
25+
// Fake
26+
}
27+
28+
public function addEagerConstraints(array $models)
29+
{
30+
// Fake
31+
}
32+
33+
public function initRelation(array $models, $relation)
34+
{
35+
// Fake
36+
}
37+
38+
public function match(array $models, Collection $results, $relation)
39+
{
40+
// Fake
41+
}
42+
43+
public function getResults()
44+
{
45+
// Fake
46+
}
47+
48+
protected function newRelatedInstanceFor(Model $parent)
49+
{
50+
// Fake
51+
}
52+
}

tests/Console/ModelsCommand/Relations/__snapshots__/Test__test__1.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models;
66

77
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\ModelsOtherNamespace\AnotherModel;
8+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Traits\HasTestRelations;
89
use Illuminate\Database\Eloquent\Model;
910
use Illuminate\Database\Eloquent\Relations\BelongsTo;
1011
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@@ -38,6 +39,9 @@
3839
* @property-read Model|\Eloquent $relationMorphTo
3940
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationMorphedByMany
4041
* @property-read int|null $relation_morphed_by_many_count
42+
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationSampleRelationType
43+
* @property-read int|null $relation_sample_relation_type_count
44+
* @property-read Simple $relationSampleToManyRelationType
4145
* @method static \Illuminate\Database\Eloquent\Builder|Simple newModelQuery()
4246
* @method static \Illuminate\Database\Eloquent\Builder|Simple newQuery()
4347
* @method static \Illuminate\Database\Eloquent\Builder|Simple query()
@@ -46,6 +50,8 @@
4650
*/
4751
class Simple extends Model
4852
{
53+
use HasTestRelations;
54+
4955
// Regular relations
5056
public function relationHasMany(): HasMany
5157
{
@@ -113,4 +119,14 @@ public function relationBelongsToSameNameAsColumn(): BelongsTo
113119
{
114120
return $this->belongsTo(AnotherModel::class, __FUNCTION__);
115121
}
122+
123+
public function relationSampleToManyRelationType()
124+
{
125+
return $this->testToOneRelation(Simple::class);
126+
}
127+
128+
public function relationSampleRelationType()
129+
{
130+
return $this->testToManyRelation(Simple::class);
131+
}
116132
}

0 commit comments

Comments
 (0)