thormeier/breadcrumb-bundle
Symfony bundle for building and rendering breadcrumb navigation. Define breadcrumb trails for routes and controllers, customize labels and URLs, and render them in Twig with a simple, flexible API. Keeps breadcrumb logic maintainable and consistent without repeating navigation setup across your app.
First, the important caveat: thormeier/breadcrumb-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/breadcrumbs.php. A Laravel developer cannot composer require it and start using it in a Laravel app — the classes are wired for Symfony's DI container, event system, and Twig bridge. Treat this as a reference implementation / pattern to port, not a dependency to install.
With that framing, the "getting started" steps for a Laravel dev are:
DependencyInjection/, Service/, and Resources/views/ directories first. You are looking for two things: the manager/service that accumulates breadcrumb items, and the Twig template that renders them. Those are the only parts worth porting.[label, url] items, a Twig function or global that renders a template, and a config block controlling home label/separator. Confirm the exact method names (addItem, add, prepend, etc.) against the source — do not trust the README.BreadcrumbManager bound as a singleton in a service provider, a Breadcrumb value object, and a Blade component (<x-breadcrumbs :items="$crumbs" />) to replace the Twig template. That's usually ~100 lines and gives you the same ergonomics without the Symfony baggage.HasBreadcrumbs trait or a Breadcrumbs::for('posts.show', ...) registry (Laravel-native style, à la davejamesmiller/laravel-breadcrumbs) so controllers don't manually push items. The bundle's controller-driven approach is fine for one-off pages but does not scale; borrow the idea, not the wiring.If you genuinely must run this inside a Symfony app, the steps are: composer require thormeier/breadcrumb-bundle, register the bundle in config/bundles.php, add the config block under config/packages/, autowire the manager into controllers, and call the Twig function in your layout. Verify the bundle loads on your Symfony version first — 2019-era bundles frequently break on Symfony 6+ due to removed Controller base classes and container API changes.
Because the package is a pattern source rather than a usable Laravel dependency, the useful "patterns" are translations of its design into Laravel terms.
Controller-driven accumulation. The bundle's core model is imperative: inject the manager, push items in the order you traverse the page, render at the end. In Laravel this maps cleanly to:
public function show(Post $post)
{
Breadcrumbs::push('Blog', route('posts.index'))
->push($post->title); // no URL = current page
return view('posts.show');
}
Registry / named trails instead of inline pushes. The bundle's biggest weakness is that breadcrumb definitions live in controllers, duplicating route knowledge. For day-to-day Laravel work, prefer a named registry keyed by route name (posts.index, posts.show) resolved by a middleware or a view composer. This survives route changes and keeps controllers clean.
Layout-level rendering. The bundle renders via a Twig function in the base template, which is the right instinct — breadcrumbs are a layout concern, not a view-data concern. Mirror that with a Blade component in layouts/app.blade.php that reads from the container-bound manager, so individual views never pass $breadcrumbs.
Config-driven presentation. The bundle exposes home label, separator, and template path. Keep those in config/breadcrumbs.php and reference them from the Blade component. Resist hardcoding the separator in the template — it's the one config knob you'll actually change per project.
Trailing-item semantics. A recurring design decision in these bundles is whether the last item is linked. The bundle generally treats the final item as plain text. Preserve that rule explicitly in your value object ($crumb->isCurrent()), because it's the first thing that breaks when someone appends a "Home" crumb in the wrong order.
Integration tips. If you're in a mixed Symfony/Laravel shop, port the service but keep the renderer separate: the manager should be framework-agnostic (pure PHP array of DTOs), and only the Blade component should touch Laravel. That keeps the port honest and testable.
composer.json.symfony/framework-bundle, the DI container, and Twig. Laravel ships none of these (Blade ≠ Twig; Laravel's container ≠ Symfony's compiler passes). Any attempt to install it in Laravel will either fail dependency resolution or silently register services that are never invoked.services.yaml argument wiring, Controller base class removal, and Twig extension signatures changed between Symfony 4 and 6. bin/console debug:container is where you start when a service won't autowire.public function in the service directory before writing any call.{{ label }} (escaped) — if you port to Blade and use {!! !!} for convenience you'll introduce an XSS hole for user-supplied titles.davejamesmiller/laravel-breadcrumbs (or diglactic/laravel-breadcrumbs, its maintained fork) gives you the registry pattern, Blade rendering, and active maintenance. If the goal is breadcrumbs rather than this specific bundle, use that.How can I help you explore Laravel packages today?