PHPackages                             ramir1/laravel-breadcrumbs-plus - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. ramir1/laravel-breadcrumbs-plus

ActiveLibrary

ramir1/laravel-breadcrumbs-plus
===============================

Define breadcrumbs as classes instead of closures, resolved through the container, with or without registering a name - on top of diglactic/laravel-breadcrumbs.

v2.1.0(1mo ago)062↓62.5%MITPHPPHP ^8.1CI passing

Since Jul 12Pushed 1mo agoCompare

[ Source](https://github.com/ramir1/laravel-breadcrumbs-plus)[ Packagist](https://packagist.org/packages/ramir1/laravel-breadcrumbs-plus)[ Docs](https://github.com/ramir1/laravel-breadcrumbs-plus)[ RSS](/packages/ramir1-laravel-breadcrumbs-plus/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (3)Dependencies (4)Versions (4)Used By (0)

Laravel Breadcrumbs Plus
========================

[](#laravel-breadcrumbs-plus)

Adds `Breadcrumbs::rule()` on top of [`diglactic/laravel-breadcrumbs`](https://github.com/diglactic/laravel-breadcrumbs) — register a breadcrumb by class name (resolved through the container) instead of a closure, so the class is only instantiated when that specific breadcrumb is generated, not for every registered page on every request. The method defaults to `__invoke` for single-purpose classes and supports constructor dependency injection, matching how controllers work.

This started as a pull request against `diglactic/laravel-breadcrumbs` which wasn't merged upstream. Rather than maintaining a fork of the whole package, this is a small extension package: it requires the vanilla `diglactic/laravel-breadcrumbs` and points its `manager-class` / `generator-class` config hooks (already built into that package for this exact purpose) at extended `Manager` and `Generator` classes.

Installation
------------

[](#installation)

```
composer require ramir1/laravel-breadcrumbs-plus
```

Laravel's package auto-discovery registers the service provider automatically. No further setup is required.

### IDE type hints

[](#ide-type-hints)

`render()`/`generate()`/`view()` accept a `[class, method]` pair at runtime (see "Rendering by class directly" below), because this package swaps the bound `Manager` class via `config('breadcrumbs.manager-class')`. IDEs like PhpStorm don't follow that indirection - they read the type hints straight off `Diglactic\Breadcrumbs\Breadcrumbs`'s docblock (`?string $name`), so passing an array there gets flagged even though it works correctly. Import `Ramir1\BreadcrumbsPlus\Breadcrumbs` instead of `Diglactic\Breadcrumbs\Breadcrumbs` to get a correct docblock - it's the same facade, resolving to the exact same singleton, just with accurate types:

```
use Ramir1\BreadcrumbsPlus\Breadcrumbs; // instead of Diglactic\Breadcrumbs\Breadcrumbs

Breadcrumbs::render([PostBreadcrumb::class, 'show'], $post);
```

Usage
-----

[](#usage)

```
// routes/breadcrumbs.php

use Diglactic\Breadcrumbs\Breadcrumbs;
use App\Breadcrumbs\PostBreadcrumb;

Breadcrumbs::rule('post', PostBreadcrumb::class);
Breadcrumbs::rule('post.edit', PostEditBreadcrumb::class, 'edit');
```

```
// app/Breadcrumbs/PostBreadcrumb.php

namespace App\Breadcrumbs;

use Diglactic\Breadcrumbs\Generator;

class PostBreadcrumb
{
    public function __construct(private SomeService $service)
    {
    }

    public function __invoke(Generator $trail, Post $post): void
    {
        $trail->parent('posts');
        $trail->push($post->title, route('posts.show', $post));
    }
}
```

`Breadcrumbs::rule($name, $class, $method = '__invoke')` behaves like `Breadcrumbs::for()`, except the callback is a `[$class, $method]` pair. `$class` is resolved through the Laravel container the moment the breadcrumb is actually generated (like a controller), so it can use constructor dependency injection without being instantiated on every request that merely registers it.

### Registering rules from a service provider instead of `routes/breadcrumbs.php`

[](#registering-rules-from-a-service-provider-instead-of-routesbreadcrumbsphp)

`routes/breadcrumbs.php` is not required. `Breadcrumbs::rule()` / `Breadcrumbs::rules()` can be called from anywhere once the container is available — including a package or module's own `ServiceProvider::boot()`. This is useful in a modular app where breadcrumb classes live next to the feature they belong to, rather than in one central file that has to know about every module:

```
// Modules/Posts/PostsServiceProvider.php

use Diglactic\Breadcrumbs\Breadcrumbs;

class PostsServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Breadcrumbs::rules([
            'posts' => PostsIndexBreadcrumb::class,
            'posts.show' => PostBreadcrumb::class,
            'posts.edit' => [PostBreadcrumb::class, 'edit'],
        ]);
    }
}
```

`Breadcrumbs::rules(array $rules)` registers many rules in one call. Each entry is either a class name (defaults to `__invoke`) or a `[$class, $method]` pair, keyed by page name — same rules as `rule()`, just batched.

If `config('breadcrumbs.files')` is left at its default (`routes/breadcrumbs.php`) and that file doesn't exist, `diglactic/laravel-breadcrumbs` silently skips loading it, so nothing needs to be disabled explicitly.

### Rendering by class directly, without registering a name first

[](#rendering-by-class-directly-without-registering-a-name-first)

`render()`, `generate()`, and `view()` also accept a `[$class, $method]` pair in place of a registered name - `$method` defaults to `__invoke`, same as `rule()`. This calls the class/method directly through the container, skipping the `rule()` registration step entirely. Useful for a one-off page whose breadcrumb isn't reused/shared under a name:

```
// Instead of:
//   Breadcrumbs::rule('post.show', PostBreadcrumb::class);
//   ...
//   Breadcrumbs::render('post.show', $post);

Breadcrumbs::render([PostBreadcrumb::class], $post);
```

It works the same way with a custom view - e.g. the `breadcrumbs::json-ld` view bundled with `diglactic/laravel-breadcrumbs`, for structured data instead of the usual HTML list:

```
{{ Breadcrumbs::view('breadcrumbs::json-ld', [PageBreadcrumb::class, 'show'], $page) }}
```

Inside the class, `$trail->parent()` accepts the same `[$class, $method]` form to reference an ancestor breadcrumb directly, instead of a registered name:

```
class PostBreadcrumb
{
    public function __invoke(Generator $trail, Post $post): void
    {
        $trail->parent([PostsIndexBreadcrumb::class]); // instead of $trail->parent('posts')
        $trail->push($post->title, route('posts.show', $post));
    }
}
```

This complements `rule()` rather than replacing it - breadcrumbs reused across several pages are still worth registering under a name. It also doesn't affect route-bound rendering: `Breadcrumbs::render()` called with no arguments still resolves via the current route's name, which still needs a matching `for()`/`rule()` entry.

How it works
------------

[](#how-it-works)

`diglactic/laravel-breadcrumbs` already resolves its `Manager` and `Generator` classes through the container and exposes `config('breadcrumbs.manager-class')` / `config('breadcrumbs.generator-class')` specifically so they can be subclassed for "more advanced customisations". This package's `ServiceProvider` sets those two config values to its own `Manager` (adds `rule()`) and `Generator` (resolves `[class, method]` callbacks) subclasses — no files from `diglactic/laravel-breadcrumbs` are modified or copied.

License
-------

[](#license)

MIT

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

50d ago

Major Versions

v1.0.0 → v2.0.02026-07-12

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/971933?v=4)[Ramir1](/maintainers/Ramir1)[@ramir1](https://github.com/ramir1)

---

Top Contributors

[![ramir1](https://avatars.githubusercontent.com/u/971933?v=4)](https://github.com/ramir1 "ramir1 (8 commits)")

---

Tags

laravelbreadcrumbs

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ramir1-laravel-breadcrumbs-plus/health.svg)

```
[![Health](https://phpackages.com/badges/ramir1-laravel-breadcrumbs-plus/health.svg)](https://phpackages.com/packages/ramir1-laravel-breadcrumbs-plus)
```

###  Alternatives

[bagisto/bagisto

Bagisto Laravel E-Commerce

28.0k177.2k9](/packages/bagisto-bagisto)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)[krayin/laravel-crm

Krayin CRM

23.8k34.4k1](/packages/krayin-laravel-crm)[laravel/octane

Supercharge your Laravel application's performance.

4.0k30.7M279](/packages/laravel-octane)[grumpydictator/firefly-iii

Firefly III: a personal finances manager.

24.5k69.5k](/packages/grumpydictator-firefly-iii)[statamic/cms

The Statamic CMS Core Package

4.9k3.9M1.2k](/packages/statamic-cms)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
