nielskrijger/breadcrumbs-bundle
A breadcrumbs bundle for PHP applications that builds and renders navigable breadcrumb trails from your routes and configuration, making it easy to add consistent, context-aware navigation to every page with minimal setup.
Reality check first: this is a Symfony2 bundle, not a Laravel package. It was archived in 2015, has 8 stars, 0 dependents, and its composer constraints target symfony/symfony ~2.x, Twig 1.x and PHP ~5.4–5.6. composer require nielskrijger/breadcrumbs-bundle in a Laravel app will either fail resolution outright or install dead code that nothing boots — there is no ServiceProvider, no facade, no Blade directive, no illuminate/* constraint. Do not put it in composer.json of a Laravel project.
Where to look first, if you're evaluating it as a reference:
BreadcrumbsBundle.php — the bundle class; tells you what the DI extension loads.DependencyInjection/ (*Extension.php, Configuration.php) — the config tree, which is the closest thing to a "config file" you'd port.Resources/config/services.yml — service ids and constructor args; the actual wiring.Resources/views/ — the render template, if present.The whole package is a few hundred lines. Read it in one sitting; that is faster than trying to make it run.
First use case in Laravel terms: you want a trail like Home / Users / Jane Doe rendered in every layout and emitted as JSON-LD. The maintained equivalent you should actually install is diglactic/laravel-breadcrumbs (the actively maintained fork of davejamesmiller/laravel-breadcrumbs):
composer require diglactic/laravel-breadcrumbs
php artisan vendor:publish --tag=breadcrumbs-config # optional
// routes/breadcrumbs.php
use Diglactic\Breadcrumbs\Breadcrumbs;
use Diglactic\Breadcrumbs\Generator as Trail;
Breadcrumbs::for('home', fn (Trail $trail) => $trail->push('Home', route('home')));
Breadcrumbs::for('users.show', function (Trail $trail, $user) {
$trail->parent('home');
$trail->push($user->name, route('users.show', $user));
});
{{-- resources/views/layouts/app.blade.php --}}
{{ Breadcrumbs::render('users.show', $user) }}
If you are maintaining a legacy Symfony 2.8 app, the bundle's own path is: composer require nielskrijger/breadcrumbs-bundle, register new Nielskrijger\BreadcrumbsBundle\BreadcrumbsBundle() (namespace approximate — check the file) in app/AppKernel.php, then call the Twig function in your layout. Verify the service id with php app/console debug:container | grep breadcrumb before writing templates.
Symfony-to-Laravel translation table. The bundle is built on three Symfony idioms; map them mentally before porting anything:
| Symfony2 bundle | Laravel equivalent |
|---|---|
Bundle + DI extension + services.yml |
Service provider + config/breadcrumbs.php |
| Twig function / extension | Blade directive, component, or global helper |
| Annotation or YAML route metadata | Explicit definitions in routes/breadcrumbs.php |
@Template render of bundle view |
resources/views/partials/breadcrumbs.blade.php |
Pattern 1 — registry keyed by route name. Definitions live in one file, keyed to route()->getName(). A tiny resolver walks the trail and renders. This is the pattern both the bundle and every Laravel breadcrumb library converge on, and it's the one to copy if you roll your own:
// app/Support/Breadcrumbs.php (~80 lines, replaces the whole package)
namespace App\Support;
class Breadcrumbs
{
protected static array $definitions = [];
public static function for(string $route, callable $callback): void
{
static::$definitions[$route] = $callback;
}
public static function render(string $route, mixed ...$params): string
{
$trail = new Trail();
static::$definitions[$route]($trail, ...$params);
return view('partials.breadcrumbs', ['trail' => $trail->items()])->render();
}
}
Pattern 2 — render in the layout, not the page. Put the call in layouts/app.blade.php guarded by Breadcrumbs::exists(request()->route()->getName()). Otherwise every welcome and login view needs a trail or throws.
Pattern 3 — structured data for SEO. Emit schema.org/BreadcrumbList JSON-LD from the same trail object the UI uses; never maintain two lists.
<script type="application/ld+json">
{!! json_encode([
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => collect($trail->items())->values()->map(fn ($i, $n) => [
'@type' => 'ListItem',
'position' => $n + 1,
'name' => $i['title'],
'item' => $i['url'],
])->all(),
], JSON_UNESCAPED_SLASHES) !!}
</script>
Pattern 4 — pass bound models, not scalars. Use route model binding so the definition receives User $user and calls route('users.show', $user). This survives route prefix changes; hardcoded '/users/'.$id does not.
Pattern 5 — test the trail, not the HTML. In a feature test, assert on route() URLs and titles from the trail array rather than grepping rendered markup for <li> — the markup is a template concern and will be restyled.
getProviders(), no Illuminate\Support\ServiceProvider subclass. There is nothing to register in config/app.php.each()-adjacent patterns, string offsets with {}, and untyped dynamic properties — all deprecated or removed in PHP 8.x. If you try to run it, expect E_DEPRECATED floods before E_ERROR.getName() from Twig_Extension and renamed classes to Twig\Extension\AbstractExtension. A 2015 bundle targeting Twig 1.x will not load under Twig 2/3 without edits.@service / %parameter% YAML refs. The services.yml uses string service references, fine in Symfony 2.x, invalid under Symfony 4+ autowiring defaults. Irrelevant to Laravel, but it is why you cannot "just port the YAML" into config/.@Breadcrumb-style annotations, it pulls doctrine/annotations. Laravel 9+ has no annotation routing; port to explicit arrays or PHP 8 attributes with spatie/laravel-route-attributes.app/Support/ transfers maintenance to you — which is fine for ~80 lines, and preferable to a dead dependency.debug:container, debug:router, and the profiler's breadcrumb panel; in Laravel the equivalents are php artisan route:list --name=users, php artisan about, and dump(Breadcrumbs::generate('users.show', $user)) inside a route or test.Breadcrumbs::exists() guard, and a macro hook. All three are cheap to implement and all three are what people actually miss when they hand-roll this.diglactic/laravel-breadcrumbs. If you want zero dependencies, the ~80-line registry above covers 95% of real use. Treat nielskrijger/breadcrumbs-bundle as a reading exercise only.How can I help you explore Laravel packages today?