Skip to content

Instantly share code, notes, and snippets.

@kmuenkel
Last active January 28, 2020 19:21
Show Gist options
  • Save kmuenkel/dcc6cd0da9b2c1928c1c753f88be31a6 to your computer and use it in GitHub Desktop.
Save kmuenkel/dcc6cd0da9b2c1928c1c753f88be31a6 to your computer and use it in GitHub Desktop.
Link any two models according to the nature of the specified parent Model relation
<?php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
if (!function_exists('relate_models')) {
/**
* @param Model $model
* @param Model $relatedModel
* @param string $relationName
* @param bool $suppressEvents
*/
function relate_models(Model $model, Model $relatedModel, $relationName, $suppressEvents = true)
{
/** @var Relations\Relation $relation */
$relation = $model->$relationName();
$expectedModel = $relation->getModel();
if (!($relatedModel instanceof $expectedModel)) {
$relation = get_class($model)."::$relationName()";
$expectedModel = get_class($expectedModel);
$givenModel = get_class($relatedModel);
throw new InvalidArgumentException("$relation expects the related model to be a $expectedModel."
." $givenModel given."
);
}
$save = function (Model $model) {
return function () use ($model) {
$model::unguarded(function () use ($model) {
$model->save();
});
};
};
if ($relation instanceof Relations\BelongsTo) {
$relation->associate($relatedModel);
$suppressEvents ? $model::withoutEvents($save($model)) : $save($model);
} elseif ($relation instanceof Relations\HasOneOrMany) {
$foreignKeyName = $relation->getForeignKeyName();
$localKeyName = $relation->getLocalKeyName();
$localKey = $model->getAttribute($localKeyName);
$relatedModel->$foreignKeyName = $localKey;
if ($relation instanceof Relations\MorphOneOrMany) {
$morphTypeField = $relation->getMorphType();
$morphType = $relation->getMorphClass();
$relatedModel->$morphTypeField = $morphType;
}
$suppressEvents ? $relatedModel::withoutEvents($save($relatedModel)) : $save($relatedModel);
$relationship = ($relation instanceof Relations\HasMany || $relation instanceof Relations\MorphMany) ?
app(EloquentCollection::class, ['items' => [$relatedModel]]) : $relatedModel;
$model->setRelation($relationName, $relationship);
} elseif ($relation instanceof Relations\BelongsToMany) {
$relation->attach($relatedModel);
} else {
throw new InvalidArgumentException('Unsupported relation type ' . get_class($relation));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment