Генерация хлебных крошек

Сегодня при просмотре лога изменений в CakePHP обнаружил что в HtmlHelper есть функции для генерации хлебных крошек.

Всего 3 функции:

  1. addCrumb -добавление элемента хлебных крошек

  2. getCrumbs - генерирует хлебные крошки ввиде строки с сылками

  3. getCrumbList - генерирует хлебные крошки ввиде списка с сылками

Для начала добавим элементы которые нужно будет вывести. Это необходимо делать в представлениях (View) или подобных местах - элементах или хелперах.

$this->Html->addCrumb(‘<i class="fa fa-home home-icon"></i> Главная’, ‘/’, array(‘escape’ => false));
$this->Html->addCrumb(‘Каталог’, ‘/catalog’);
$this->Html->addCrumb(‘Сланцы’, Router::url(array(‘controller’ => ‘catalogs’, ‘action’ => ‘view’, 3)));

Теперь можно вывести хлебные крошки.

echo $this->Html->getCrumbs(' > ');

Это создаст простую строку:

Главная > Каталог > Сланцы

Если Вы хотите вывести хлебные крошки в список - как например это делается в Bootstrap, то Вам нужен getCrumbList.

echo $this->Html->getCrumbList();

Для Bootstrap.

echo $this->Html->getCrumbList(array(
	'lastClass' => 'active',
	'class' => 'breadcrumb',
	'escape' => false
));

Компонент для сохранения хлебных крошек

Этот хелпер не удобен тем что он хелпер и соответственно использовать его в контроллере проблематично. Например я обычно делаю так: в AppController->beforeFilter() добавляю в хлебные крошки ссылку на главную страницу, за тем так же в каждом контроллере в beforeFilter ссылку на index для текущего контроллера и для каждой функции так же свой элемент. Если есть плагин, то можно добавить и в AppControllerPlugin если необходимо показать такую иерархию.

Вот сам код компонента:

<?php
//app/Controller/Component/BreadcrumbsComponent.php
App::uses('Component', 'Controller');
 
/**
* Компонент для управления отображением "хлебными крошками"
*/
class BreadcrumbsComponent extends Component {
	private $breadcrumbs = array();
 
	public function initialize(Controller $controller) {
		$this->add(__('Главная'), Router::url('/'));
	}
 
	public function beforeRender(Controller $controller) {
		$controller->set('breadcrumbs', $this->breadcrumbs);
	}
 
	/**
	* Добавление ссылки
	*
	* @param string|array $title Если передано string то добавляется одна
	*      ссылка указывающая на $url.
	*        Если передавать array, то будет добавлена группа ссылок, но
	*        в каждом элементе массива обязательно должны быть ключи 'title' и
	*        'url'.
	* @param string $url Строка представляющая относительную ссылку. Значение
	*        параметра в случае необходимости должно быть заранее подготовлено
	*        с помощью функции Router::url().
	* @return boolean В случае ошибки возвращается false иначе true
	*/
	public function add($title, $url = '', $icon = '') {
		if (is_array($title)) {
			return $this->_add($title);
		}
		if (empty($this->breadcrumbs) || ($this->breadcrumbs[count($this->breadcrumbs) -1]['url'] != $url)) {
			$this->breadcrumbs[] = array(
				'title' => $title,
				'url' => $url,
				'icon' => $icon
			);
		}
		return true;
	}
 
	public function clear() {
		$this->breadcrumbs = array();
		return true;
	}
 
	/**
	* Добавление списка ссылок
	*
	* @param array $params Массив с описанием ссылок. В каждом элементе массива
	*        обязательно должны присутствовать ключи 'title' и 'url'.
	*/
	private function _add($params) {
		if (!is_array($params)) return false;
		foreach ($params as $param) {
			$this->add($param['title'], $param['url']);
		}
		return true;
	}
}

Элемент для вывода хлебных крошек

Так же есть компонент элемент для вывода хлебных крошек. Раньше список в нём генерировался с помощью sprintf, теперь же я его переделал так что бы использовались выше описанные функции.

<?php
if (!empty($breadcrumbs) && (count($breadcrumbs) > 1)) {
	foreach($breadcrumbs as $key => $breadcrumb) {
		$this->Html->addCrumb(
			((isset($breadcrumb['icon']) && $breadcrumb['icon'])?sprintf('<i class="%s"></i> ', $breadcrumb['icon']):'').$breadcrumb['title'],
			($key == (count($breadcrumbs) - 1))?null:$breadcrumb['url'],
			array('escape' => false)
		);
	}
	echo $this->Html->getCrumbList(array(
		'lastClass' => 'active',
		'class' => 'breadcrumb',
		'escape' => false
	));
}

Данный элемент может поддерживать иконки, а так же последний элемент списка всегда выводится без ссылки - что бы не создавать на странице ссылку на саму себя.

Использование

Для использования компонента и элемента в начале необходимо подключить компонент в AppController.

class AppController extends Controller {
	public $components = array(
		...
		'Breadcrumbs',
		...
	);
	...
}

За тем в коде можем проставить добавление элементов в хлебные крошки.

<?php
App::uses('AppController', 'Controller');
 
class PagesController extends AppController {
	public function beforeFilter() {
		parent::beforeFilter();
		$this->Breadcrumbs->add(__('Страницы'), Router::url(array('plugin' => false, 'controller' => 'pages', 'action' => 'index')));
	}
 
	public function about(){
		$this->Breadcrumbs->add(__(‘О нас’), Router::url(array('plugin' => false, 'controller' => 'pages', 'action' => 'about')));
		...
	}
	…
}

И наконец выводим сам элемент. Я это делаю в шаблоне (Layout), но так же это можно делать и в представление (View).

<div class="breadcrumbs">
	<?php echo $this->element('breadcrumbs');?>
</div>

Заключение

На самом деле функции ещё сыроваты, например я обычно иконки для элементов выводил не оборачивая их в ссылки, но с помощью этих функций у меня не получилось так сделать. Как вариант можно попробовать элементам передавать параметры before.

Больше информации можно посмотреть в API - http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper

Желаю всем приятной навигации на Ваших сайтах!

Автор: Сергей Степанов

Поделиться @
, 11 июня 2020 в 20:20