/laravel-breadcrumbs

Laravel Breadcrumbs - A simple Laravel-style way to create breadcrumbs in Laravel 4+. [Laravel]

Primary LanguagePHPMIT LicenseMIT

Laravel Breadcrumbs

Latest Stable Version Total Downloads Build Status Coverage Status MIT License

A simple Laravel-style way to create breadcrumbs in Laravel 4+.

Installation

1. Install with Composer

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.)

2. Add to config/app.php

    'providers' => [
        // ...
        'DaveJamesMiller\Breadcrumbs\ServiceProvider',
    ],

And:

    'aliases' => [
        // ...
        'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
    ],

This registers the package with Laravel and creates an alias called Breadcrumbs.

Usage

1. Define breadcrumbs in app/Http/breadcrumbs.php

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));
});

2. Choose/create a template to render the breadcrumbs

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

Creating a custom template

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 above
  • url - The URL you set above
  • first - true for the first breadcrumb, false otherwise
  • last - true for the last breadcrumb, false otherwise

Then update your config file with the custom view name, e.g.:

'view' => '_partials.breadcrumbs',

3. Output the breadcrumbs in your view

With Blade

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).

With Blade layouts and @section

In the main page:

@extends('layout.name')

@section('breadcrumbs', Breadcrumbs::render('category', $category))

In the layout:

@yield('breadcrumbs')

Pure PHP, without Blade

<?= Breadcrumbs::render('category', $category) ?>

Or the long syntax if you prefer:

<?php echo Breadcrumbs::render('category', $category) ?>

Defining breadcrumbs

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:

Static pages

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

Parent links

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

Dynamic titles and links

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.

Nested categories

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

Advanced usage

Breadcrumbs with no URL

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.

Breadcrumbs with custom data

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.

Defining breadcrumbs in a different file

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.

Switching views dynamically

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)]) }}

Overriding the "current" route

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).

Passing an array of parameters

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);

Checking if a breadcrumb exists

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.

API Reference

Facade

  • 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)

Defining breadcrumbs (inside the callback)

  • $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)

Outputting the breadcrumbs (in the view)

  • $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)

Changelog

See the CHANGELOG for a list of changes and upgrade instructions.

Issues & Pull Requests

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 and aliases sections of config/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.

Contributing

See the CONTRIBUTING file for details of how to contribute to Laravel Breadcrumbs.

Thanks to

This package is largely based on the Gretel plugin for Ruby on Rails, which I used for a while before discovering Laravel.

Contributors

License

MIT License. See LICENSE.txt.

Alternatives

So far I've only found one other breadcrumb package for Laravel: