symfony-cmf/tree-browser-bundle
Installation:
composer require symfony-cmf/tree-browser-bundle
Ensure your config/bundles.php includes:
SymfonyCmf\TreeBrowserBundle\TreeBrowserBundle::class => ['all' => true],
Configuration:
Add to config/packages/symfony_cmf_tree_browser.yaml:
symfony_cmf_tree_browser:
tree_manager: your_custom_tree_manager_service
tree_node_class: App\Entity\YourTreeNodeEntity
First Use Case: Render a tree in a Twig template:
{{ render(controller('SymfonyCmfTreeBrowserBundle:Tree:tree', {
'treeManager': treeManager,
'rootNode': rootNode
})) }}
config/packages/symfony_cmf_tree_browser.yaml (default config)src/Resources/views/Tree/tree.html.twig (default Twig template)src/DependencyInjection/Configuration.php (configuration schema)Tree Rendering:
Use the TreeController to render hierarchical data:
$treeManager = $container->get('your_tree_manager_service');
$rootNode = $treeManager->findRootNode(); // Custom logic
return $this->render('SymfonyCmfTreeBrowserBundle:Tree:tree', [
'treeManager' => $treeManager,
'rootNode' => $rootNode,
]);
Custom Tree Managers:
Extend SymfonyCmf\TreeBrowserBundle\Manager\TreeManagerInterface:
class CustomTreeManager implements TreeManagerInterface {
public function findRootNode() { /* ... */ }
public function findNodeById($id) { /* ... */ }
public function getChildren($node) { /* ... */ }
}
Twig Integration: Pass the tree manager to Twig for dynamic rendering:
{% for node in treeManager.getChildren(rootNode) %}
<li>{{ node.title }}
{% if treeManager.getChildren(node) %}
{{ render(controller('SymfonyCmfTreeBrowserBundle:Tree:tree', {
'treeManager': treeManager,
'rootNode': node
})) }}
{% endif %}
</li>
{% endfor %}
Drag-and-Drop (Legacy): Enable via JavaScript (Symfony 4.2+ requires manual JS integration):
// Use jQuery UI or similar for drag-and-drop
$('.tree-node').draggable({ /* ... */ });
SymfonyCmf\TreeBrowserBundle\Doctrine\PhpcrTreeManager for PHPCR-ODM or adapt for Doctrine ORM.$builder->add('parentNode', EntityType::class, [
'class' => YourTreeNode::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('n')
->where('n.level < :maxLevel')
->setParameter('maxLevel', 3);
},
]);
Deprecation Warnings:
{% render controller %}).Drag-and-Drop Issues:
Configuration Overrides:
tree_manager service must implement TreeManagerInterface exactly; mismatched methods will cause runtime errors.Performance:
render calls for large trees cause high memory usage. Use pagination or lazy-loading:
{% for node in treeManager.getChildren(rootNode)[:10] %} {# Limit to 10 children #}
Blank Trees:
Check if findRootNode() returns null or if getChildren() is empty. Verify your entity mappings.
// Debug tree manager
var_dump($treeManager->findRootNode()->getChildren());
Twig Errors: Update template syntax for Symfony 4.2+:
{# Old (may fail in Symfony 4.2+) #}
{{ render(controller('SymfonyCmfTreeBrowserBundle:Tree:tree', {...})) }}
{# New #}
{{ include('SymfonyCmfTreeBrowserBundle:Tree:tree.html.twig', {
treeManager: treeManager,
rootNode: rootNode
}) }}
Custom Templates:
Override tree.html.twig in templates/SymfonyCmfTreeBrowserBundle/Tree/:
{# Example: Add icons #}
<li>
<i class="{{ node.icon }}"></i>
{{ node.title }}
{% if treeManager.getChildren(node) %}
{{ include('SymfonyCmfTreeBrowserBundle:Tree:_subtree.html.twig', {
treeManager: treeManager,
rootNode: node
}) }}
{% endif %}
</li>
Node Metadata: Extend your entity to include display logic:
class YourTreeNode {
public function getDisplayTitle() {
return $this->title . ' (' . $this->getLevel() . ')';
}
}
Update Twig:
{{ node.getDisplayTitle() }}
AJAX Loading: Implement lazy-loading via JavaScript:
$('.tree-node').on('click', function() {
const nodeId = $(this).data('node-id');
$.get(`/ajax/load-children/${nodeId}`, (html) => {
$(this).append(html);
});
});
Symfony CMF in Laravel: This bundle is Symfony-only. For Laravel, consider alternatives like:
spatie/laravel-tree (for Eloquent)baeri/laravel-nestedsetwith() and whereIn.Service Container: Register the tree manager as a Laravel service provider:
public function register() {
$this->app->bind(TreeManagerInterface::class, CustomTreeManager::class);
}
How can I help you explore Laravel packages today?