Skip to content

Commit

Permalink
Consider foreign key constraints with isRelationNullable (#1231)
Browse files Browse the repository at this point in the history
* Consider foreign key constraints with isRelationNullable

* test: add belongsTo Variation

* command: composer test-regenerate
  • Loading branch information
atushi-koga authored Aug 7, 2021
1 parent b268871 commit 52a4b64
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 3 deletions.
24 changes: 24 additions & 0 deletions src/Console/ModelsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class ModelsCommand extends Command
* @var bool[string]
*/
protected $nullableColumns = [];
/**
* @var string[]
*/
protected $foreignKeyConstraintsColumns = [];

/**
* During initialization we use Laravels Date Facade to
Expand Down Expand Up @@ -452,6 +456,7 @@ public function getPropertiesFromTable($model)
return;
}

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

if ($relation === 'belongsTo') {
return isset($this->nullableColumns[$fkProp->getValue($relationObj)]) ||
!in_array($fkProp->getValue($relationObj), $this->foreignKeyConstraintsColumns, true);
}

return isset($this->nullableColumns[$fkProp->getValue($relationObj)]);
}

Expand Down Expand Up @@ -1409,4 +1419,18 @@ protected function runModelHooks($model): void
$hookInstance->run($this, $model);
}
}

/**
* @param \Doctrine\DBAL\Schema\AbstractSchemaManager $schema
* @param string $table
* @throws DBALException
*/
protected function setForeignKeys($schema, $table)
{
foreach ($schema->listTableForeignKeys($table) as $foreignKeyConstraint) {
foreach ($foreignKeyConstraint->getLocalColumns() as $columnName) {
$this->foreignKeyConstraintsColumns[] = $columnName;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

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

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class BelongsToVariation extends Model
{
public function notNullColumnWithForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'not_null_column_with_foreign_key_constraint');
}

public function notNullColumnWithNoForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'not_null_column_with_no_foreign_key_constraint');
}

public function nullableColumnWithForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'nullable_column_with_foreign_key_constraint');
}

public function nullableColumnWithNoForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'nullable_column_with_no_foreign_key_constraint');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@

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

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models\BelongsToVariation
*
* @property integer $id
* @property integer $not_null_column_with_foreign_key_constraint
* @property integer $not_null_column_with_no_foreign_key_constraint
* @property integer|null $nullable_column_with_foreign_key_constraint
* @property integer|null $nullable_column_with_no_foreign_key_constraint
* @property-read BelongsToVariation $notNullColumnWithForeignKeyConstraint
* @property-read BelongsToVariation|null $notNullColumnWithNoForeignKeyConstraint
* @property-read BelongsToVariation|null $nullableColumnWithForeignKeyConstraint
* @property-read BelongsToVariation|null $nullableColumnWithNoForeignKeyConstraint
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation query()
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNotNullColumnWithForeignKeyConstraint($value)
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNotNullColumnWithNoForeignKeyConstraint($value)
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNullableColumnWithForeignKeyConstraint($value)
* @method static \Illuminate\Database\Eloquent\Builder|BelongsToVariation whereNullableColumnWithNoForeignKeyConstraint($value)
* @mixin \Eloquent
*/
class BelongsToVariation extends Model
{
public function notNullColumnWithForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'not_null_column_with_foreign_key_constraint');
}

public function notNullColumnWithNoForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'not_null_column_with_no_foreign_key_constraint');
}

public function nullableColumnWithForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'nullable_column_with_foreign_key_constraint');
}

public function nullableColumnWithNoForeignKeyConstraint(): BelongsTo
{
return $this->belongsTo(self::class, 'nullable_column_with_no_foreign_key_constraint');
}
}
<?php

declare(strict_types=1);

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

use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\ModelsOtherNamespace\AnotherModel;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Traits\HasTestRelations;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -20,15 +73,15 @@
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Relations\Models\Simple
*
* @property integer $id
* @property-read Simple $relationBelongsTo
* @property-read AnotherModel $relationBelongsToInAnotherNamespace
* @property-read Simple|null $relationBelongsTo
* @property-read AnotherModel|null $relationBelongsToInAnotherNamespace
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToMany
* @property-read int|null $relation_belongs_to_many_count
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToManyWithSub
* @property-read int|null $relation_belongs_to_many_with_sub_count
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationBelongsToManyWithSubAnother
* @property-read int|null $relation_belongs_to_many_with_sub_another_count
* @property-read AnotherModel $relationBelongsToSameNameAsColumn
* @property-read AnotherModel|null $relationBelongsToSameNameAsColumn
* @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $relationHasMany
* @property-read int|null $relation_has_many_count
* @property-read Simple|null $relationHasOne
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class BelongsToVariationTable extends Migration
{
public function up(): void
{
Schema::create('belongs_to_variations', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('not_null_column_with_foreign_key_constraint');
$table->integer('not_null_column_with_no_foreign_key_constraint');
$table->integer('nullable_column_with_foreign_key_constraint')->nullable();
$table->integer('nullable_column_with_no_foreign_key_constraint')->nullable();
$table->foreign('not_null_column_with_foreign_key_constraint')->references('id')->on('belongs_to_variations');
$table->foreign('nullable_column_with_foreign_key_constraint')->references('id')->on('belongs_to_variations');
});
}
}

0 comments on commit 52a4b64

Please sign in to comment.