Skip to content

Instantly share code, notes, and snippets.

@kmuenkel
Last active November 4, 2021 16:45
Show Gist options
  • Save kmuenkel/055f107139d904e30810bf53750d9c6e to your computer and use it in GitHub Desktop.
Save kmuenkel/055f107139d904e30810bf53750d9c6e to your computer and use it in GitHub Desktop.
Connect two models regardless of relationship type
<?php
if (!function_exists('associate_models')) {
/**
* @param Model $model
* @param Model $relatedModel
* @param string $relationName
*/
function associate_models(Model $model, Model $relatedModel, string $relationName)
{
/** @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 UnexpectedValueException("$relation expects the related model to be a $expectedModel."
. " $givenModel given."
);
}
if ($relation instanceof Relations\BelongsTo) {
$relation->associate($relatedModel)->save();
} elseif ($relation instanceof Relations\HasOneOrMany) {
$relation->save($relatedModel);
$relationships = $model->relationLoaded($relationName) ? $model->getRelation($relationName)
: app(EloquentCollection::class);
$relationships = ($relationships instanceof Model)
? app(EloquentCollection::class, ['items' => [$relationships]]) : $relationships;
$relationships->push($relatedModel);
$relation->match([$model], $relationships, $relationName);
} elseif ($relation instanceof Relations\BelongsToMany) {
$attributes = [];
if ($relation instanceof Relations\MorphToMany) {
foreach ($relation->getQuery()->getQuery()->wheres as $where) {
$conditionValidAssignment = $where['type'] == 'Basic' && $where['operator'] == '=';
$alreadyApplied = $where['column'] == $relation->getTable() . '.' . $relation->getMorphType();
$alreadyApplied |= $where['column'] == $relation->getMorphType();
$alreadyApplied |= $where['column'] == $relation->getQualifiedForeignPivotKeyName();
$alreadyApplied |= $where['column'] == $relation->getForeignPivotKeyName();
if ($conditionValidAssignment && !$alreadyApplied) {
$attributes[$where['column']] = $where['value'];
}
}
}
$relation->attach($relatedModel, $attributes);
} else {
throw new UnexpectedValueException('Unsupported relation type ' . get_class($relation));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment