mirror of
https://github.com/barryvdh/laravel-ide-helper.git
synced 2026-08-23 12:33:08 +00:00
fix: Don't force |null on BelongsTo relations using ->withTrashed() (#1783)
When the related model uses SoftDeletes, `isRelationNullable()` was forcing the BelongsTo relation type to nullable even if the relation explicitly opted into trashed parents via `->withTrashed()`. Combined with a NOT NULL FK column and DB-level FK constraint, the relation is effectively non-nullable. The SoftDeletes branch is now skipped when the relation has removed the `SoftDeletingScope` and added no constraint on the qualified `deleted_at` column. `->onlyTrashed()` and `->withoutTrashed()` keep their nullable annotation because they restrict the parent to a specific soft-delete state. Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3a53071650
commit
5060909c37
@@ -44,6 +44,7 @@ use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Illuminate\Database\Schema\Builder;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Arr;
|
||||
@@ -943,13 +944,55 @@ class ModelsCommand extends Command
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->relatedModelUsesSoftDeletes($relationObj)) {
|
||||
if (
|
||||
$this->relatedModelUsesSoftDeletes($relationObj)
|
||||
&& !$this->relationIncludesNonTrashedParents($relationObj)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the relation explicitly opts into returning non-soft-deleted parents
|
||||
* via ->withTrashed(), in which case the SoftDeletes-based nullability no longer applies.
|
||||
*
|
||||
* Returns false for ->onlyTrashed() and ->withoutTrashed(), which still leave the
|
||||
* relation potentially empty depending on the parent's soft-delete state.
|
||||
*
|
||||
* @param Relation $relationObj
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function relationIncludesNonTrashedParents(Relation $relationObj): bool
|
||||
{
|
||||
$query = $relationObj->getQuery();
|
||||
|
||||
if (!in_array(SoftDeletingScope::class, $query->removedScopes(), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$relatedModel = $relationObj->getRelated();
|
||||
|
||||
if (!method_exists($relatedModel, 'getQualifiedDeletedAtColumn')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$deletedAtColumn = $relatedModel->getQualifiedDeletedAtColumn();
|
||||
|
||||
foreach ($query->getQuery()->wheres ?? [] as $where) {
|
||||
if (
|
||||
($where['column'] ?? null) === $deletedAtColumn
|
||||
&& in_array($where['type'] ?? null, ['Null', 'NotNull'], true)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the related model uses the SoftDeletes trait
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user