A simple Laravel-style way to create breadcrumbs in Laravel 4+.
composer require davejamesmiller/laravel-breadcrumbs:~2.3.0
This will update composer.json
and install it into the vendor/
directory.
(See the Packagist website for a list of available version numbers and development releases.)
'providers' => [
// ...
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
],
And:
'aliases' => [
// ...
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
],
This registers the package with Laravel and creates an alias called
Breadcrumbs
.
Create a file called app/Http/breadcrumbs.php
(app/breadcrumbs.php
in
Laravel 4.x) to put your breadcrumbs in. This file will be loaded automatically.
It should look something like this - see the Defining breadcrumbs section below for an explanation.
<?php
Breadcrumbs::register('home', function($breadcrumbs) {
$breadcrumbs->push('Home', route('home'));
});
Breadcrumbs::register('blog', function($breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Blog', route('blog'));
});
Breadcrumbs::register('category', function($breadcrumbs, $category) {
$breadcrumbs->parent('blog');
foreach ($category->ancestors as $ancestor) {
$breadcrumbs->push($ancestor->title, route('category', $ancestor->id));
}
$breadcrumbs->push($category->title, route('category', $category->id));
});
Breadcrumbs::register('page', function($breadcrumbs, $page) {
$breadcrumbs->parent('category', $page->category);
$breadcrumbs->push($page->title, route('page', $page->id));
});
By default a Twitter Bootstrap v3-compatible unordered list will be rendered.
If you would like to change the template, first you need to generate a config file by running this command:
# Laravel 5
php artisan publish:config davejamesmiller/laravel-breadcrumbs
# Laravel 4
php artisan config:publish davejamesmiller/laravel-breadcrumbs
Then open config/packages/davejamesmiller/laravel-breadcrumbs/config.php
and edit this line:
'view' => 'laravel-breadcrumbs::bootstrap3',
The possible values are:
laravel-breadcrumbs::bootstrap3
(Twitter Bootstrap 3)laravel-breadcrumbs::bootstrap2
(Twitter Bootstrap 2)- A path to a custom template, e.g.
_partials.breadcrumbs
If you want to customise the HTML, create your own view file (e.g.
app/views/_partials/breadcrumbs.blade.php
) like this:
@if ($breadcrumbs)
<ul class="breadcrumb">
@foreach ($breadcrumbs as $breadcrumb)
@if (!$breadcrumb->last)
<li><a href="{{{ $breadcrumb->url }}}">{{{ $breadcrumb->title }}}</a></li>
@else
<li class="active">{{{ $breadcrumb->title }}}</li>
@endif
@endforeach
</ul>
@endif
As you can see above it will receive an array called $breadcrumbs
. Each
breadcrumb is an object with the following keys:
title
- The title you set aboveurl
- The URL you set abovefirst
-true
for the first breadcrumb,false
otherwiselast
-true
for the last breadcrumb,false
otherwise
Then update your config file with the custom view name, e.g.:
'view' => '_partials.breadcrumbs',
Finally, call Breadcrumbs::render()
in the view template for each page. You
can either pass the name of the breadcrumb to use (and parameters if needed):
<!-- Laravel 5 -->
{!! Breadcrumbs::render('home') !!}
{!! Breadcrumbs::render('category', $category) !!}
<!-- Laravel 4 -->
{{ Breadcrumbs::render('home') }}
{{ Breadcrumbs::render('category', $category) }}
Or in Laravel 4.1+ you can avoid the need to do this for every page by naming
your breadcrumbs the same as your routes. For example, if you have this in
routes.php
:
Route::model('category', 'Category');
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'home']);
Route::get('/category/{category}', ['uses' => 'CategoryController@show', 'as' => 'category']);
And in the layout you have this:
<!-- Laravel 5 -->
{!! Breadcrumbs::render() !!}
<!-- Laravel 4 -->
{{ Breadcrumbs::render() }}
Then on the homepage it will be the same as calling Breadcrumbs::render('home')
and on the category page it will be the same as calling
Breadcrumbs::render('category', $category)
.
The key here is the 'as'
parameter must match the breadcrumb name. The
parameters passed to the breadcrumbs callback will be the same as the ones
Laravel passes to the controller (see the Route
parameters section of the
Laravel documentation).
In the main page:
@extends('layout.name')
@section('breadcrumbs', Breadcrumbs::render('category', $category))
In the layout:
@yield('breadcrumbs')
<?= Breadcrumbs::render('category', $category) ?>
Or the long syntax if you prefer:
<?php echo Breadcrumbs::render('category', $category) ?>
Breadcrumbs will usually correspond to actions or types of page. For each breadcrumb you specify a name, the breadcrumb title and the URL to link it to. Since these are likely to change dynamically, you do this in a closure, and you pass any variables you need into the closure.
The following examples should make it clear:
The most simple breadcrumb is probably going to be your homepage, which will look something like this:
Breadcrumbs::register('home', function($breadcrumbs) {
$breadcrumbs->push('Home', route('home'));
});
As you can see, you simply call $breadcrumbs->push($title, $url)
inside the
closure.
For generating the URL, you can use any of the standard Laravel URL-generation methods, including:
url('path/to/route')
(URL::to()
)secure_url('path/to/route')
route('routename')
(URL::route()
)action('controller@action')
(URL::action()
)- Or just pass a string URL (
'http://www.example.com/'
)
This example would be rendered like this:
Home
This is another static page, but this has a parent link before it:
Breadcrumbs::register('blog', function($breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Blog', route('blog'));
});
It would be rendered like this:
Home / Blog
This is a dynamically generated page pulled from the database:
Breadcrumbs::register('page', function($breadcrumbs, $page) {
$breadcrumbs->parent('blog');
$breadcrumbs->push($page->title, route('page', $page->id));
});
The $page
variable would simply be passed in from the view:
<!-- Laravel 5 -->
{!! Breadcrumbs::render('page', $page) !!}
<!-- Laravel 4 -->
{{ Breadcrumbs::render('page', $page) }}
It would be rendered like this:
Home / Blog / Page Title
Tip: You can pass multiple parameters if necessary.
Finally if you have nested categories or other special requirements, you can
call $breadcrumbs->push()
multiple times:
Breadcrumbs::register('category', function($breadcrumbs, $category) {
$breadcrumbs->parent('blog');
foreach ($category->ancestors as $ancestor) {
$breadcrumbs->push($ancestor->title, route('category', $ancestor->id));
}
$breadcrumbs->push($category->title, route('category', $category->id));
});
Alternatively you could make a recursive function such as this:
Breadcrumbs::register('category', function($breadcrumbs, $category) {
if ($category->parent)
$breadcrumbs->parent('category', $category->parent);
else
$breadcrumbs->parent('blog');
$breadcrumbs->push($category->title, route('category', $category->slug));
});
Both would be rendered like this:
Home / Blog / Grandparent Category / Parent Category / Category Title
The second parameter to push()
is optional, so if you want a breadcrumb with
no URL you can do so:
$breadcrumbs->push('Sample');
The $breadcrumb->url
value will be null
.
The default Twitter Bootstrap templates provided render this with a CSS class of "active", the same as the last breadcrumb, because otherwise they default to black text not grey which doesn't look right.
Note: Support for this was added to the Twitter Bootstrap templates in 2.1.0. Before this you would need to create a custom template.
Added in 2.3.0.
The push()
method accepts an optional third parameter, $data
- an array of
arbitrary data to be passed to the breadcrumb, which you can use in your custom
template. For example, if you wanted each breadcrumb to have an icon, you could
do:
$breadcrumbs->push('Home', '/', ['icon' => 'home.png']);
The $data
array's entries will be merged into the breadcrumb as properties, so
you would access the icon as $breadcrumb->icon
in your template, like this:
<li><a href="{{{ $breadcrumb->url }}}"><img src="/images/icons/{{{ $breadcrumb->icon }}}">{{{ $breadcrumb->title }}}</a></li>
Do not use the following keys in your data array, as they will be overwritten:
title
, url
, first
, last
.
If you don't want to use app/Http/breadcrumbs.php
, you can define them in
app/Http/routes.php
or any other file as long as it's loaded by Laravel.
You can change the view at runtime by calling:
Breadcrumbs::setView('view.name');
If you need different views in different templates, you can call
Breadcrumbs::generate()
to get the $breadcrumbs
array and then load the view
manually:
@include('_partials/breadcrumbs2', ['breadcrumbs' => Breadcrumbs::generate('category', $category)])
or
<!-- Laravel 5 -->
{!! View::make('_partials/breadcrumbs2', ['breadcrumbs' => Breadcrumbs::generate('category', $category)]) !!}
<!-- Laravel 4 -->
{{ View::make('_partials/breadcrumbs2', ['breadcrumbs' => Breadcrumbs::generate('category', $category)]) }}
If you call Breadcrumbs::render()
or Breadcrumbs::generate()
with no
parameters, it will use the current route name and parameters, as returned by
Laravel's Route::current()
method, by default.
You can override this by calling
Breadcrumbs::setCurrentRoute($name, $param1, $param2...)
or
Breadcrumbs::setCurrentRouteArray($name, $params)
.
Added in 2.0.0.
If the breadcrumb requires multiple parameters, you would normally pass them like this:
Breadcrumbs::render('name', $param1, $param2, $param3);
Breadcrumbs::generate('name', $param1, $param2, $param3);
$breadcrumbs->parent('name', $param1, $param2, $param3);
If you want to pass an array of parameters instead you can use these methods:
Breadcrumbs::renderArray('name', $params);
Breadcrumbs::generateArray('name', $params);
$breadcrumbs->parentArray('name', $params);
Added in 2.2.0.
By default an exception will be thrown if the breadcrumb doesn't exist, so you know to add it. If you want suppress this you can call the following methods instead:
Breadcrumbs::renderIfExists()
(returns an empty string)Breadcrumbs::renderArrayIfExists()
(returns an empty string)Breadcrumbs::generateIfExists()
(returns an empty array)Breadcrumbs::generateArrayIfExists()
(returns an empty array)
Alternatively you can call Breadcrumbs::exists('name')
, which returns a
boolean.
Breadcrumbs::register($name, $callback)
Breadcrumbs::exists()
(returns boolean) (Added in 2.2.0)Breadcrumbs::exists($name)
(returns boolean) (Added in 2.2.0)Breadcrumbs::generate()
(returns array) (Added in 2.2.3)Breadcrumbs::generate($name)
(returns array)Breadcrumbs::generate($name, $param1, ...)
(returns array)Breadcrumbs::generateArray($name, $params)
(returns array) (Added in 2.0.0)Breadcrumbs::generateIfExists()
(returns array) (Added in 2.2.0)Breadcrumbs::generateIfExists($name)
(returns array) (Added in 2.2.0)Breadcrumbs::generateIfExists($name, $param1, ...)
(returns array) (Added in 2.2.0)Breadcrumbs::generateArrayIfExists($name, $params)
(returns array) (Added in 2.2.0)Breadcrumbs::render()
(returns string) (Added in 2.2.0)Breadcrumbs::render($name)
(returns string)Breadcrumbs::render($name, $param1, ...)
(returns string)Breadcrumbs::renderArray($name, $params)
(returns string) (Added in 2.0.0)Breadcrumbs::renderIfExists()
(returns string) (Added in 2.2.0)Breadcrumbs::renderIfExists($name)
(returns string) (Added in 2.2.0)Breadcrumbs::renderIfExists($name, $param1, ...)
(returns string) (Added in 2.2.0)Breadcrumbs::renderArrayIfExists($name, $params)
(returns string) (Added in 2.2.0)Breadcrumbs::setCurrentRoute($name)
Breadcrumbs::setCurrentRoute($name, $param1, ...)
Breadcrumbs::setCurrentRouteArray($name, $params)
(Added in 2.0.0)Breadcrumbs::clearCurrentRoute()
Breadcrumbs::setView($view)
Breadcrumbs::getView()
(returns string)
$breadcrumbs->push($title)
$breadcrumbs->push($title, $url)
$breadcrumbs->push($title, $url, $data)
(Added in 2.3.0)$breadcrumbs->parent($name)
$breadcrumbs->parent($name, $param1, ...)
$breadcrumbs->parentArray($name, $params)
(Added in 2.0.0)
$breadcrumbs
(array), contains:$breadcrumb->title
(string)$breadcrumb->url
(string or null)$breadcrumb->first
(boolean)$breadcrumb->last
(boolean)$breadcrumb->custom_attribute_name
(mixed - any custom data attributes you specified)
See the CHANGELOG for a list of changes and upgrade instructions.
Important: Don't be afraid to go into the Laravel Breadcrumbs code and use
var_dump()
(or print_r()
) to see what's happening and fix your own problems!
A pull request or detailed bug report is much more likely to
get attention than a vague error report. Also make sure you read the documentation
carefully.
Please submit issues and pull requests using GitHub issues.
Bug reports should include the following:
- The complete error message, including file & line numbers
- Steps to reproduce the problem
- Laravel Breadcrumbs version (should be the latest version)
- Laravel version
- PHP version
- The
providers
andaliases
sections ofconfig/app.php
(Note: not the Encryption Key section which should be kept private) - in case there's a conflict with another package
You may also need to include copies of:
app/Http/breadcrumbs.php
(app/breadcrumbs.php
in Laravel 4.x)config/packages/davejamesmiller/laravel-breadcrumbs/config.php
(if used)- The view or layout that outputs the breadcrumbs
- The custom breadcrumbs template (if applicable)
- Any other relevant files
If you have any suggestions for improving the documentation - especially if anything is unclear to you and could be explained better - please let me know.
See the CONTRIBUTING file for details of how to contribute to Laravel Breadcrumbs.
This package is largely based on the Gretel plugin for Ruby on Rails, which I used for a while before discovering Laravel.
- Miloš Levačić (levacic) - #56
- Ricky Wiens (rickywiens) - #41
- Boris Glumpler (shabushabu) - #28
- Andrej Badin (Andreyco) - #24
- Stef Horner (tedslittlerobot) - #11
MIT License. See LICENSE.txt.
So far I've only found one other breadcrumb package for Laravel: