Installation:
composer require becklyn/route-tree-bundle
Register the bundle in config/bundles.php (Laravel 5.4+) or AppKernel.php (Symfony):
Becklyn\RouteTreeBundle\BecklynRouteTreeBundle::class => ['all' => true],
First Use Case:
Define a root route in routes.yaml (or routes.php):
homepage:
path: /
options:
tree:
title: "Home"
Then add a child route:
about:
path: /about
options:
tree:
parent: homepage
title: "About Us"
Accessing the Tree:
Inject the RouteTree service in a controller or Twig template:
use Becklyn\RouteTreeBundle\Service\RouteTree;
public function index(RouteTree $routeTree) {
$tree = $routeTree->getTree();
return view('menu', ['tree' => $tree]);
}
Dynamic Menu Generation: Use the tree in Twig to render a navigation menu:
<ul>
{% for node in tree %}
<li>
<a href="{{ path(node.route) }}">{{ node.title }}</a>
{% if node.children|length > 0 %}
<ul>
{% include 'partials/_menu.html.twig' with {'tree': node.children} %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
Conditional Rendering: Filter nodes based on security or other logic:
$filteredTree = $routeTree->getTree()->filter(function ($node) {
return $node->getSecurity() === null || $this->isGranted($node->getSecurity());
});
Parameterized Routes: Set default parameters for child routes:
products:
path: /products/{category}
options:
tree:
title: "Products"
parameters: { category: "all" }
Integration with Symfony Router:
Combine with Symfony’s RouterInterface for path generation:
$url = $router->generate($node->getRouteName(), $node->getParameters());
admin.dashboard).$tree = $routeTree->getTree(); // Cache this in a service or controller.
Circular References:
Ensure parent routes exist and avoid circular dependencies (e.g., A → B → A).
Debug: Use php bin/console debug:router to verify routes.
Priority Conflicts:
Nodes with the same priority are sorted alphabetically by route name. Explicitly set priorities for consistent ordering:
options:
tree:
priority: 10 # Higher = higher in the list
Security Expressions:
If security is not set, the node is always accessible. Omit or set to ~ to disable security checks:
options:
tree:
security: ROLE_ADMIN # Requires ROLE_ADMIN
Parameter Overrides: Child routes inherit parent parameters but can override them. Test edge cases where parameters might conflict:
parent_route:
path: /parent/{id}
options:
tree:
parameters: { id: 1 }
child_route:
path: /child
options:
tree:
parent: parent_route
parameters: { id: 2 } # Overrides parent's default
dd($routeTree->getTree()) to inspect the structure in development.php bin/console debug:router
Custom Node Classes:
Extend \Becklyn\RouteTreeBundle\Model\Node to add metadata:
class CustomNode extends Node {
public function getIcon() { return $this->icon; }
}
Override the bundle’s node.class service configuration.
Tree Builders:
Implement \Becklyn\RouteTreeBundle\Builder\TreeBuilderInterface for custom logic (e.g., filtering by role).
Twig Extensions: Add custom filters to Twig for node manipulation:
$twig->addFilter(new \Twig\TwigFilter('is_active', function ($node, $currentRoute) {
return $node->getRouteName() === $currentRoute->getName();
}));
options.tree in YAML over PHP route definitions. Ensure consistency:
// routes.php
Route::get('/dynamic', function () {})->options(['tree' => ['parent' => 'home']]);
routes.yaml may override earlier ones. Group related routes logically.$tree->getChildren($node->getRouteName()); // Load children on demand.
How can I help you explore Laravel packages today?