Skip to content

Instantly share code, notes, and snippets.

@thecrypticace
Last active February 20, 2020 07:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thecrypticace/7e635cfc98b08c5009572a08a82019d0 to your computer and use it in GitHub Desktop.
Save thecrypticace/7e635cfc98b08c5009572a08a82019d0 to your computer and use it in GitHub Desktop.
Eloquent recursive relationships
<?php
// Default setup of parent/child relationship for a hierarchichal category structure
// This prevents queries when iterating over them recursively
$categories = ParentChildHierarchy::apply(Category::all())
// Customized example where threaded comments have a custom relationship and key names
// $post->threadedCmments returns _all_ comments in a given post. Not just the top-level ones.
$comments = ParentChildHierarchy::apply($post->threadedCmments, "id", "parent_comment_id", "parentComment", "children");
<?php
namespace App;
use Illuminate\Database\Eloquent\Collection;
class ParentChildHierarchy
{
public static function apply($entities, $primaryKey = "id", $parentKey = "parent_id", $parentRelation = "parent", $childRelation = "children")
{
$parents = $entities->keyBy($primaryKey);
$children = $entities->groupBy($parentKey);
// This is a manual eagerloading setup
// that handles recursive relationships
return $entities->map(function ($entity) use ($parents, $children, $primaryKey, $parentKey, $parentRelation, $childRelation) {
if ($entity->$parentKey) {
$entity->setRelation($parentRelation, $parents[$entity->$parentKey]);
}
$entity->setRelation($childRelation, $children[$entity->$primaryKey] ?? new Collection());
return $entity;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment