Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Breadcrumb Bundle Laravel Package

slope-it/breadcrumb-bundle

SlopeIt BreadcrumbBundle makes it easy to define, manage, and render breadcrumb navigation in PHP applications. Build breadcrumb trails with a simple API and output them in your templates, keeping site navigation clear and consistent with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you install: this is a Symfony bundle, not a Laravel package. composer require slope-it/breadcrumb-bundle in a Laravel app won't register anything — there's no service provider, no facade, no Blade directive. If you're working in Laravel, the reusable part is the pattern (named breadcrumb collections, builder service, Twig/Blade partial override), and diglactic/laravel-breadcrumbs is the direct equivalent. The rest of this assumes you're in a Symfony app (6.x/7.x, PHP 8.1+).

Minimal path:

  1. composer require slope-it/breadcrumb-bundle — Flex auto-registers the bundle; if not, add it to config/bundles.php.
  2. Read, in this order: the README usage snippet, Resources/config/services.yaml (to see the manager's service ID and any config keys), then the BreadcrumbManager / BreadcrumbItem classes. Two minutes there saves an hour of guessing at method names.
  3. Build a trail in a controller and render it in the layout.
// src/Controller/ProductController.php
public function show(Product $product, BreadcrumbManager $breadcrumbs): Response
{
    $breadcrumbs
        ->addItem('Home', ['path' => 'home'])
        ->addItem('Products', ['path' => 'product_list'])
        ->addItem($product->getName());

    return $this->render('product/show.html.twig', ['product' => $product]);
}
{# templates/layout.html.twig #}
<nav aria-label="breadcrumb">{{ slope_it_breadcrumb_render('default') }}</nav>

Confirm the Twig function name and collection argument with bin/console debug:twig — that's the fastest sanity check if the README snippet is slightly stale.

First real use case to target: a catalog/detail page (Home > Category > Product). Static pages don't need this bundle; anything with an entity-derived label does.

Implementation Patterns

One collection per navigation region. The main reason to pick this over a hand-rolled Twig partial is named collections: main, admin, docs each keep an independent item list on the same manager. Define the names as constants (BreadcrumbCollection::MAIN) so a typo can't silently produce an empty <ol>.

Wrap the manager in your own builder. Keep controllers thin and put the "how does a domain object become a crumb" logic in one place:

final class ProductBreadcrumbs
{
    public function __construct(private BreadcrumbManager $breadcrumbs) {}

    public function forProduct(Product $product): void
    {
        $this->breadcrumbs
            ->addItem('Home', ['path' => 'home'])
            ->addItem($product->getCategory()->getName(), [
                'path' => 'category_show',
                'params' => ['slug' => $product->getCategory()->getSlug()],
            ])
            ->addItem($product->getName());
    }
}

That wrapper is also the seam you'd port to Laravel later, since it has no Symfony dependencies beyond the manager.

Choose one build location per route. Either the controller builds the trail, or a kernel.controller / kernel.request listener builds it section-wide. Doing both is how you get duplicated "Home" entries. For a whole /admin/* area, a listener is less repetitive; for entity pages, the controller has the data.

Attribute/annotation route if available. If the bundle ships a #[Breadcrumb]-style attribute, use it for static trails (Home > Legal > Privacy) where there's nothing dynamic to compute. Fall back to imperative code the moment a segment needs an entity label — mixing both on one route is where confusion starts.

Override the template, not the internals. Copy the bundle's template into templates/bundles/SlopeItBreadcrumbBundle/... and change the markup there (Bootstrap breadcrumb-item, JSON-LD BreadcrumbList, aria-current="page" on the last item). That keeps your styling decisions in your repo and survives minor bundle releases.

Test the trail, not the HTML. Assert getItems() names/paths in a unit test against your builder service. Reserve one functional test for the rendered block — asserting list markup in every controller test is churn for no signal.

Gotchas and Tips

  • Framework mismatch is the headline. A Laravel developer inherits zero of this: no app/Providers, no Blade::directive, no config/breadcrumbs.php. Budget a rewrite, not an adaptation.
  • Collection name mismatch fails silently. Build into default, render main, get an empty nav with no error. Hard-code the name via a constant and you'll never debug this twice.
  • Build timing vs. route params. If a listener runs before the router resolves {slug}, entity lookups return null and you get a crumb labeled with an empty string. Build in the controller or in a listener bound to kernel.controller (after argument resolution), not kernel.request.
  • Route generation errors surface at render time. ['path' => 'product_list'] throws RouteNotFoundException when Twig renders, not when you add the item — the failure is far from the cause. Pass params for any route with required placeholders.
  • Translation keys, not final strings. Hand the crumb a key ('nav.products') if the app is multilingual; baking "Products" into the manager makes the trail the one untranslated surface on the page.
  • Duplicates from stacked listeners. A global listener that appends a "Search" segment plus a controller that also adds it produces two identical crumbs. Guard with a "skip if last item already matches" check in the listener.
  • Low bus factor. 16 stars, single vendor, NOASSERTION license — read the license before shipping, pin the version in composer.json, and skim the 2025-05-22 release notes. Because you own the template override, a markup change upstream can't surprise production, but a method signature change can. Wrap the manager in your builder service so an API change is a one-file fix.
  • Extension points worth knowing: the manager service (decorate it for cross-cutting behavior — e.g. auto-prepending Home) and the template (override for markup). Avoid subclassing BreadcrumbItem or the manager's internals; neither is a stability contract at this maturity level.
  • Debugging checklist: bin/console debug:container BreadcrumbManager to confirm the service exists and is public/injectable, debug:twig for the function name, and a temporary dump($breadcrumbs->getItems()) in the controller to see whether the problem is building or rendering. Nine times out of ten it's the second one.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib