/** * Synchronizes the keys for a HasMany relation. This is a special case, * since the actual new relations should already be linked after the * update/create handling recursive call. * * @param RelationInfo $info * @param array $keys */ protected function syncKeysForHasManyRelation(RelationInfo $info, array $keys) { // the relations might be disconnected, but only if the key is nullable // if deletion is not configured, we should attempt setting the key to // null // if it is a has-one relation, has a different default for detaching $isNotHasOne = is_a($info->relationClass(), HasOne::class, true); // do not detach by default (for hasmany), unless configured otherwise $detaching = null === $info->getDetachMissing() ? $isNotHasOne : $info->getDetachMissing(); if (!$detaching && !$info->isDeleteDetached()) { return; } // find keys for all models that are linked to the model but omitted in nested data $oldKeys = $this->model->{$info->relationMethod()}()->pluck($info->model()->getKeyName())->toArray(); $oldKeys = array_diff($oldKeys, $keys); if (!count($oldKeys)) { return; } if ($info->isDeleteDetached()) { foreach ($oldKeys as $oldKey) { $this->deleteFormerlyRelatedModel($info->model()->find($oldKey), $info); } return; } if ($detaching) { foreach ($oldKeys as $oldKey) { /** @var Model $model */ $detachModel = $info->model()->find($oldKey); if (!$detachModel) { continue; } $foreignKey = $this->model->{$info->relationMethod()}()->getPlainForeignKey(); $detachModel->{$foreignKey} = null; $detachModel->save(); } } }