Skip to content

Commit 5515cab

Browse files
FQCN bugfix when writing external eloquent builder methods inside models. (#1113)
* Fix code that was causing the test to break and fix bug with not built in types * Run cs fixer * Remove fetching the doc block type and the putting it as a type hint as a php doc block is sufficient * Revert doc block type hinting * Enchance doc block type hinting * Combine replacements * Use the full builder class instead of the parsed one after the getClassName function and remove in array check * Get the builder from the model itself instead of passing a string directly the function * Use the full builder class to get the builder methods and reflection, but use the parsed builder class after setting its method in the doc * Add test for fqn support on external eloquent builder * Use the external builder if necessary when building the magic wheres * Use the default eloquent builder if the user has disabled the external builder option
1 parent 9859958 commit 5515cab

File tree

7 files changed

+498
-156
lines changed

7 files changed

+498
-156
lines changed

src/Console/ModelsCommand.php

+19-10
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,13 @@ protected function getPropertiesFromTable($model)
490490
!$column->getNotnull()
491491
);
492492
if ($this->write_model_magic_where) {
493+
$builderClass = $this->write_model_external_builder_methods
494+
? get_class($model->newModelQuery())
495+
: '\Illuminate\Database\Eloquent\Builder';
496+
493497
$this->setMethod(
494498
Str::camel('where_' . $name),
495-
$this->getClassNameInDestinationFile($model, \Illuminate\Database\Eloquent\Builder::class)
499+
$this->getClassNameInDestinationFile($model, $builderClass)
496500
. '|'
497501
. $this->getClassNameInDestinationFile($model, get_class($model)),
498502
['$value']
@@ -562,7 +566,7 @@ protected function getPropertiesFromMethods($model)
562566
);
563567

564568
if ($this->write_model_external_builder_methods) {
565-
$this->writeModelExternalBuilderMethods($builder, $model);
569+
$this->writeModelExternalBuilderMethods($model);
566570
}
567571
} elseif (
568572
!method_exists('Illuminate\Database\Eloquent\Model', $method)
@@ -1149,26 +1153,31 @@ protected function getUsedClassNames(ReflectionClass $reflection): array
11491153
return $namespaceAliases;
11501154
}
11511155

1152-
protected function writeModelExternalBuilderMethods(string $builder, Model $model): void
1156+
protected function writeModelExternalBuilderMethods(Model $model): void
11531157
{
1154-
if (in_array($builder, ['\Illuminate\Database\Eloquent\Builder', 'EloquentBuilder'])) {
1155-
return;
1156-
}
1157-
1158-
$newBuilderMethods = get_class_methods($builder);
1158+
$fullBuilderClass = '\\' . get_class($model->newModelQuery());
1159+
$newBuilderMethods = get_class_methods($fullBuilderClass);
11591160
$originalBuilderMethods = get_class_methods('\Illuminate\Database\Eloquent\Builder');
11601161

11611162
// diff the methods between the new builder and original one
11621163
// and create helpers for the ones that are new
11631164
$newMethodsFromNewBuilder = array_diff($newBuilderMethods, $originalBuilderMethods);
11641165

1166+
if (!$newMethodsFromNewBuilder) {
1167+
return;
1168+
}
1169+
1170+
// after we have retrieved the builder's methods
1171+
// get the class of the builder based on the FQCN option
1172+
$builderClassBasedOnFQCNOption = $this->getClassNameInDestinationFile($model, get_class($model->newModelQuery()));
1173+
11651174
foreach ($newMethodsFromNewBuilder as $builderMethod) {
1166-
$reflection = new \ReflectionMethod($builder, $builderMethod);
1175+
$reflection = new \ReflectionMethod($fullBuilderClass, $builderMethod);
11671176
$args = $this->getParameters($reflection);
11681177

11691178
$this->setMethod(
11701179
$builderMethod,
1171-
$builder . '|' . $this->getClassNameInDestinationFile($model, get_class($model)),
1180+
$builderClassBasedOnFQCNOption . '|' . $this->getClassNameInDestinationFile($model, get_class($model)),
11721181
$args
11731182
);
11741183
}

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

+73-73
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilderWithFqn\Builders;
6+
7+
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
8+
use Illuminate\Database\Eloquent\Builder;
9+
10+
class PostExternalQueryBuilder extends Builder
11+
{
12+
public function isActive(): self
13+
{
14+
return $this;
15+
}
16+
17+
public function isStatus(string $status): self
18+
{
19+
return $this;
20+
}
21+
22+
public function isLoadingWith(?string $with): self
23+
{
24+
return $this;
25+
}
26+
27+
/**
28+
* @param int|null $number
29+
* @return $this
30+
*/
31+
public function withTheNumber($number): self
32+
{
33+
return $this;
34+
}
35+
36+
/**
37+
* @param integer|null $number
38+
* @return $this
39+
*/
40+
public function withTheNumberDifferently($number): self
41+
{
42+
return $this;
43+
}
44+
45+
/**
46+
* @param bool|null $number
47+
* @return $this
48+
*/
49+
public function withBool($booleanVar): self
50+
{
51+
return $this;
52+
}
53+
54+
/**
55+
* @param bool|null $number
56+
* @return $this
57+
*/
58+
public function withBoolDifferently($booleanVar): self
59+
{
60+
return $this;
61+
}
62+
63+
public function withBoolTypeHinted(bool $booleanVar): self
64+
{
65+
return $this;
66+
}
67+
68+
/**
69+
* @param int|string $someone
70+
* @return $this
71+
*/
72+
public function withSomeone($someone): self
73+
{
74+
return $this;
75+
}
76+
77+
/**
78+
* @param mixed $option
79+
* @return $this
80+
*/
81+
public function withMixedOption($option): self
82+
{
83+
return $this;
84+
}
85+
86+
public function withTestCommand(ModelsCommand $testCommand): self
87+
{
88+
return $this;
89+
}
90+
91+
public function withNullTestCommand(?ModelsCommand $testCommand): self
92+
{
93+
return $this;
94+
}
95+
96+
public function withNullAndAssignmentTestCommand(?ModelsCommand $testCommand = null): self
97+
{
98+
return $this;
99+
}
100+
101+
/**
102+
* @param ModelsCommand $testCommand
103+
* @return $this
104+
*/
105+
public function withNullTestCommandInDocBlock($testCommand): self
106+
{
107+
return $this;
108+
}
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilderWithFqn\Models;
6+
7+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilderWithFqn\Builders\PostExternalQueryBuilder;
8+
use Illuminate\Database\Eloquent\Model;
9+
10+
class Post extends Model
11+
{
12+
public function newEloquentBuilder($query): PostExternalQueryBuilder
13+
{
14+
return new PostExternalQueryBuilder($query);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GeneratePhpdocWithExternalEloquentBuilderWithFqn;
6+
7+
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
8+
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
9+
10+
class Test extends AbstractModelsCommand
11+
{
12+
public function test(): void
13+
{
14+
$command = $this->app->make(ModelsCommand::class);
15+
16+
$tester = $this->runCommand($command, [
17+
'--write' => true,
18+
]);
19+
20+
$this->assertSame(0, $tester->getStatusCode());
21+
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
22+
$this->assertMatchesMockedSnapshot();
23+
}
24+
}

0 commit comments

Comments
 (0)