API query parameters like ?include=author,comments.user.profile need to be converted into nested arrays for eager loading. Here’s a minimal recursive approach that handles unlimited nesting depth.
public function parseIncludes(Request $request): array
{
$includes = explode(',', $request->input('include', ''));
$buildTree = function($relations) use (&$buildTree) {
$tree = [];
foreach ($relations as $relation) {
$parts = explode('.', $relation, 2);
$key = $parts[0];
if (isset($parts[1])) {
$tree[$key][] = $parts[1];
} else {
$tree[$key] = [];
}
}
foreach ($tree as $key => $nested) {
if (!empty($nested)) {
$tree[$key] = $buildTree($nested);
}
}
return $tree;
};
return $buildTree(array_filter($includes));
}
This converts comments.user.profile into ['comments' => ['user' => ['profile' => []]]], ready to pass to your eager loading logic:
public function index(Request $request)
{
$relations = $this->parseIncludes($request);
return Post::query()
->when($relations, fn($q) => $q->load($relations))
->paginate();
}
The recursive pattern keeps the code under 30 lines while handling any nesting depth. Each iteration splits on the first dot, creating a tree structure where the first level becomes the array key and everything after the dot gets recursively processed.
This is particularly useful for JSON:API implementations or GraphQL-like query patterns where clients specify exactly which relationships they need. Instead of always eager loading everything or writing manual if/else chains, you can dynamically build the relationship tree from user input.
Leave a Reply