Skip to content

Commit 52a4b64

Browse files
authored
Consider foreign key constraints with isRelationNullable (#1231)
* Consider foreign key constraints with isRelationNullable * test: add belongsTo Variation * command: composer test-regenerate
1 parent b268871 commit 52a4b64

File tree

4 files changed

+134
-3
lines changed

4 files changed

+134
-3
lines changed

src/Console/ModelsCommand.php

+24
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class ModelsCommand extends Command
102102
* @var bool[string]
103103
*/
104104
protected $nullableColumns = [];
105+
/**
106+
* @var string[]
107+
*/
108+
protected $foreignKeyConstraintsColumns = [];
105109

106110
/**
107111
* During initialization we use Laravels Date Facade to
@@ -452,6 +456,7 @@ public function getPropertiesFromTable($model)
452456
return;
453457
}
454458

459+
$this->setForeignKeys($schema, $table);
455460
foreach ($columns as $column) {
456461
$name = $column->getName();
457462
if (in_array($name, $model->getDates())) {
@@ -726,6 +731,11 @@ protected function isRelationNullable(string $relation, Relation $relationObj):
726731
$fkProp = $reflectionObj->getProperty('foreignKey');
727732
$fkProp->setAccessible(true);
728733

734+
if ($relation === 'belongsTo') {
735+
return isset($this->nullableColumns[$fkProp->getValue($relationObj)]) ||
736+
!in_array($fkProp->getValue($relationObj), $this->foreignKeyConstraintsColumns, true);
737+
}
738+
729739
return isset($this->nullableColumns[$fkProp->getValue($relationObj)]);
730740
}
731741

@@ -1409,4 +1419,18 @@ protected function runModelHooks($model): void
14091419
$hookInstance->run($this, $model);
14101420
}
14111421
}
1422+
1423+
/**
1424+
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
1425+
* @param string $table
1426+
* @throws DBALException
1427+
*/
1428+
protected function setForeignKeys($schema, $table)
1429+
{
1430+
foreach ($schema->listTableForeignKeys($table) as $foreignKeyConstraint) {
1431+
foreach ($foreignKeyConstraint->getLocalColumns() as $columnName) {
1432+
$this->foreignKeyConstraintsColumns[] = $columnName;
1433+
}
1434+
}
1435+
}
14121436
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models;
6+
7+
use Illuminate\Database\Eloquent\Model;
8+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
9+
10+
class BelongsToVariation extends Model
11+
{
12+
public function notNullColumnWithForeignKeyConstraint(): BelongsTo
13+
{
14+
return $this->belongsTo(self::class, 'not_null_column_with_foreign_key_constraint');
15+
}
16+
17+
public function notNullColumnWithNoForeignKeyConstraint(): BelongsTo
18+
{
19+
return $this->belongsTo(self::class, 'not_null_column_with_no_foreign_key_constraint');
20+
}
21+
22+
public function nullableColumnWithForeignKeyConstraint(): BelongsTo
23+
{
24+
return $this->belongsTo(self::class, 'nullable_column_with_foreign_key_constraint');
25+
}
26+
27+
public function nullableColumnWithNoForeignKeyConstraint(): BelongsTo
28+
{
29+
return $this->belongsTo(self::class, 'nullable_column_with_no_foreign_key_constraint');
30+
}
31+
}

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

+56-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,59 @@
44

55
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models;
66

7+
use Illuminate\Database\Eloquent\Model;
8+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
9+
10+
/**
11+
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models\BelongsToVariation
12+
*
13+
* @property integer $id
14+
* @property integer $not_null_column_with_foreign_key_constraint
15+
* @property integer $not_null_column_with_no_foreign_key_constraint
16+
* @property integer|null $nullable_column_with_foreign_key_constraint
17+
* @property integer|null $nullable_column_with_no_foreign_key_constraint
18+
* @property-read BelongsToVariation $notNullColumnWithForeignKeyConstraint
19+
* @property-read BelongsToVariation|null $notNullColumnWithNoForeignKeyConstraint
20+
* @property-read BelongsToVariation|null $nullableColumnWithForeignKeyConstraint
21+
* @property-read BelongsToVariation|null $nullableColumnWithNoForeignKeyConstraint
22+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation newModelQuery()
23+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation newQuery()
24+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation query()
25+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereId($value)
26+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNotNullColumnWithForeignKeyConstraint($value)
27+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNotNullColumnWithNoForeignKeyConstraint($value)
28+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNullableColumnWithForeignKeyConstraint($value)
29+
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNullableColumnWithNoForeignKeyConstraint($value)
30+
* @mixin \Eloquent
31+
*/
32+
class BelongsToVariation extends Model
33+
{
34+
public function notNullColumnWithForeignKeyConstraint(): BelongsTo
35+
{
36+
return $this->belongsTo(self::class, 'not_null_column_with_foreign_key_constraint');
37+
}
38+
39+
public function notNullColumnWithNoForeignKeyConstraint(): BelongsTo
40+
{
41+
return $this->belongsTo(self::class, 'not_null_column_with_no_foreign_key_constraint');
42+
}
43+
44+
public function nullableColumnWithForeignKeyConstraint(): BelongsTo
45+
{
46+
return $this->belongsTo(self::class, 'nullable_column_with_foreign_key_constraint');
47+
}
48+
49+
public function nullableColumnWithNoForeignKeyConstraint(): BelongsTo
50+
{
51+
return $this->belongsTo(self::class, 'nullable_column_with_no_foreign_key_constraint');
52+
}
53+
}
54+
<?php
55+
56+
declare(strict_types=1);
57+
58+
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models;
59+
760
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\ModelsOtherNamespace\AnotherModel;
861
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Traits\HasTestRelations;
962
use Illuminate\Database\Eloquent\Model;
@@ -20,15 +73,15 @@
2073
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models\Simple
2174
*
2275
* @property integer $id
23-
* @property-read Simple $relationBelongsTo
24-
* @property-read AnotherModel $relationBelongsToInAnotherNamespace
76+
* @property-read Simple|null $relationBelongsTo
77+
* @property-read AnotherModel|null $relationBelongsToInAnotherNamespace
2578
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToMany
2679
* @property-read int|null $relation_belongs_to_many_count
2780
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToManyWithSub
2881
* @property-read int|null $relation_belongs_to_many_with_sub_count
2982
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToManyWithSubAnother
3083
* @property-read int|null $relation_belongs_to_many_with_sub_another_count
31-
* @property-read AnotherModel $relationBelongsToSameNameAsColumn
84+
* @property-read AnotherModel|null $relationBelongsToSameNameAsColumn
3285
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationHasMany
3386
* @property-read int|null $relation_has_many_count
3487
* @property-read Simple|null $relationHasOne
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
class BelongsToVariationTable extends Migration
10+
{
11+
public function up(): void
12+
{
13+
Schema::create('belongs_to_variations', function (Blueprint $table) {
14+
$table->bigIncrements('id');
15+
$table->integer('not_null_column_with_foreign_key_constraint');
16+
$table->integer('not_null_column_with_no_foreign_key_constraint');
17+
$table->integer('nullable_column_with_foreign_key_constraint')->nullable();
18+
$table->integer('nullable_column_with_no_foreign_key_constraint')->nullable();
19+
$table->foreign('not_null_column_with_foreign_key_constraint')->references('id')->on('belongs_to_variations');
20+
$table->foreign('nullable_column_with_foreign_key_constraint')->references('id')->on('belongs_to_variations');
21+
});
22+
}
23+
}

0 commit comments

Comments
 (0)