Skip to content

Instantly share code, notes, and snippets.

@fenos
Created February 24, 2017 16:39
Show Gist options
  • Save fenos/1b2c2ad4c3d6bc3db252eaf5085202d4 to your computer and use it in GitHub Desktop.
Save fenos/1b2c2ad4c3d6bc3db252eaf5085202d4 to your computer and use it in GitHub Desktop.
nested relations
/**
* Get includes that are valid relations
* on models, it can go deep as much as we need
* it will also cut off the not existing relations
*
* @param array $relations
* @return array|bool
*/
public function validateRelations(array $relations = [])
{
$model = $this->model();
$validRelations = [];
// I'm going to check if the relations
// are valid
foreach ($relations as $include) {
if ($validatedRelation = $this->isValidRelationship($include, $model)) {
// If the valid relations are more then 2 means
// that we have nested relations let's join them
if (count($validatedRelation) >= 2) {
$parentRelation = array_shift($validatedRelation);
$validRelations[] = $parentRelation . '.' . implode('.', $validatedRelation);
} else {
$validRelations[] = $validatedRelation;
}
}
}
return $this->relationsValidated = array_reverse(array_flatten($validRelations));
}
/**
* This function will define if the relation
* and the nested one are valid relations
*
* @param $nameRelation
* @param $parentModel
* @param int $deepness
* @return array
*/
public function isValidRelationship($nameRelation, $parentModel, $deepness = 1)
{
$breakingPoint = false;
$model = $parentModel;
$validRelations = [];
$parts = explode('.', $nameRelation);
// Todo: this while loop might be refactor in a short way
// I'll check if every include given is a
// valid model relation
while ($relation = array_shift($parts)) {
if (method_exists($model, $relation)) {
// I'll trigger the method to check if the relation
// return to me a Relation Instance
$rel = call_user_func([$model, $relation]);
// only if this pass I can consider the
// relation valid
if ($rel instanceof Relation) {
$model = $rel->getRelated();
// I save the models that are related to this
// Rest instance so i can reuse them later
if (!($model instanceof $parentModel) or ($rel instanceof BelongsTo) or ($rel instanceof BelongsToMany)) {
$this->modelsRelated[ $deepness ][ $relation ] = $model;
}
$validRelations[] = $relation;
$deepness++;
} else {
$breakingPoint = true;
}
} else {
$breakingPoint = true;
}
if ($breakingPoint) {
break;
}
}
return $validRelations;
}
// USAGE
$this->validateRelations([
'user',
'users.cars',
'users.cars.models'
])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment