Как сделать «хлебные крошки» на PHP?

Автор: | 25.09.2016

kak-sdelat-hlebnye-kroshki-na-phpДоброго времени суток :-)

Сегодня мы поговорим о том, как сделать «хлебные крошки» на PHP своими руками.

Задача довольно распространённая и достаточно простая с точки зрения реализации. В качестве вступления рассмотрим, что же такое «хлебные крошки» и зачем они нужны.

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

Итак, поехали :-)

Что такое «хлебные крошки» на сайте?

Сразу хочу сказать, что это не то, о чём подумало большинство людей, не связанных с веб-программированием :-)

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

«Хлебными крошками» в компьютерном мире является совокупность ссылок на разделы сайта, каталоги файловых систем и прочие сущности, к которым относится итоговый файл или страница сайта.

Именно поэтому синонимами «хлебных крошек» являются фразы «навигационная цепочка» и «дублирующее меню», которые наиболее полно характеризуют данный элемент.

Но они, по каким-то причинам (скорее всего, из-за своей «заумности», но это всего лишь моё мнение) они не прижились, и на сегодня самым распространённым и легкозапоминающимся термином навигационного меню является именно «хлебные крошки».

Вы наверняка видели их на каждом сайте, на котором существует хотя бы одна категория объектов. Статей, товаров, неважно чего, одним словом, мерных единиц вашего ресурса, которые зависят от типа сайта.

Ухх… вот это я завернул :-) Даже самому стало слегка не по себе от своих заумностей :-)

Но, как ни описывай «хлебные крошки», всё равно лучше один раз увидеть, чем сто раз услышать.

primer-hlebnyh-kroshek-cccp-blogТак выглядит навигационная цепочка на данном сайте. А вот так выглядят «хлебные крошки» крупнейшего Интернет-магазина России OZON:

primer-hlebnyh-kroshek-ozonКак видите, несмотря на различие в назначении ресурсов, навигационные меню у нас одинаковы.

Отличия заключаются только в цвете (тут уже кому что нравится) и принципе организации «хлебных крошек» — у меня они заканчиваются заголовком текущей страницы, а у OZON они состоят только лишь из ссылок на родительские категории.

Но, несмотря на эти мелочи, предназначение у них одинаково – предоставление пользователям ссылок на разделы, предшествующие текущей странице, чтобы можно было без труда попасть в нужное место, вплоть до главной страницы.

Кстати, «хлебные крошки» также играют немаловажную роль в SEO-оптимизации сайтов, т.к. помогают роботам поисковых систем более эффективно индексировать содержимое сайта благодаря ссылкам на категории, из которых «крошки» и состоят.

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

Кроме сайтов, данный элемент навигации существует также и в операционных системах (Windows, начиная с Vista), а также в различных файловых менеджерах (всем известный Total Commander, например, который позаимствовал эту фичу у Windows Vista Explorer).

Вот так, например, выглядят «хлебные крошки» в Windows 7:

hlebnye-kroshki-v-operacionnoj-sisteme-windowsВ данных примерах дублирующее меню существует именно для удобства пользователей, т.е. упрощая им навигацию по каталогам в файловой системе. Естественно, ни о каком SEO мы здесь и говорить не будем.

Поскольку данный проект посвящён веб-разработке, о «хлебных крошках» мы будем говорить только с точки зрения их применения на сайтах. Поэтому, если вдруг где-то вы увидите небольшие нестыковки с их спецификой использования внутри ОС и прочих программных продуктов, просьба не судить строго.

Хорошо, но откуда же взялась ассоциация навигационной цепочки с «хлебными крошками», спросят большинство пользователей?

Я сам, когда первый раз услышал данное определение, никак не мог понять, что же мне хотят сказать? О каких ещё крошках мне рассказывают? Даже малейшего предположения не возникло :-)

Корни данного термина, оказывается, уходят глубоко в фольклор, а именно к сказке братьев Гримм о Гензеле и Гретеле, где дети разбрасывали хлебные крошки, пытаясь по ним найти дорогу из леса. Однако, сходство с нашей навигационной цепочкой весьма ироничное, т.к. в сказке крошки склевали птицы, и дети заблудились.

Однако, если вспомнить сюжет, описанный в первоисточнике, способ навигации с помощью хлебных крошек был второй попыткой найти дорогу домой. Первая, когда дети разбрасывали камешки, была успешной.

Так что либо создатель термина «хлебные крошки» посчитал его более благозвучным (на английском звучит как «breadcrumbs»), либо он обладал весьма своеобразным чувством юмора :-)

Нам же остаётся только принимать это как факт.

Кому нужны хлебные крошки на сайте?

Как следует из материала выше – всем веб-мастерам, у которых на сайте больше 2 уровней вложенности (раздел/статья или категория/товар), и кто не безразличен к позициям своего творения в поисковой выдаче.

При этом совершенно не важно, какой у вас тип сайта. Также не важна платформа.

На чём бы ни был разработан ваш сайт – на WordPress, Joomla, ModX, OpenCart, на базе различных фреймворков (Yii, Laravel, Symfony, Zend) или вообще на «чистых» языках – всем вам без «хлебных крошек» не обойтись.

Так же не важен и язык бэкэнда вашего сайта, на котором, в большинстве случаев, breadcrumbs будут разрабатываться.

Кстати, раз уж мы завели разговор о CMS и фреймворках, следует сказать, что практически для каждой платформы уже существует целый набор готовых решений в виде плагинов и модулей, реализующих функционал «хлебных крошек».

Я мог бы посвятить этому отдельные статьи (возможно, что в будущем я на это и решусь), но для начала я решил познакомить вас с универсальным вариантом, который подойдёт для большинства площадок.

С этой целью я решил рассмотреть пример создания «хлебных крошек» на PHP, т.к. на сегодня это самый распространённый бэкэнд-язык веб-программирования.

Поэтому рассмотренный пример и подойдёт для большинства, а не для всех сайтов, ведь помимо PHP никто не мешает вам писать сайты на Java, Python, Ruby и прочих языках бэкэнда.

Но алгоритм, который используется при построении «хлебных крошек», всё равно будет неизменным.

Вот к нему-то мы наконец и переходим.

Создание «хлебных крошек» на PHP — алгоритм

Итак, как говорилось раньше, «хлебные крошки» — это совокупность ссылок на предшествующие страницы, которые, в большинстве своём, являются родительскими категориями текущей страницы.

Как правило, указание категорий содержится в самом url текущей страницы. Рассмотрим на примере данного сайта.

http://cccp-blog.com/blogosfera/schyotchik-prosmotrov-s-adblock-svoimi-rukami

Данный url страницы со статьёй состоит из нескольких частей, разделённых слэшами («/»):

  1. Корень сайта (cccp-blog.com)
  2. Категория сайта (blogosfera)
  3. Объект категории, в нашем случае статья (schyotchik-prosmotrov-s-adblock-svoimi-rukami)

То есть, по мере продвижения по сайту от его корня, к url ресурса постоянно добавляются части, соответствующие указателям на предшествующие уровни иерархии.

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

Итак, составим алгоритм формирования «хлебных крошек»:

  1. Получаем url текущей страницы;
  2. Парсим его (разбираем на части);
  3. Для каждой части задаём название элемента «хлебных крошек» и составляем для неё url;
  4. Записываем название элементов и их url в отдельную конструкцию (массив) для передачи в шаблон;
  5. Передаём полученные данные в шаблон и отображаем их там.

Данный алгоритм, как уже и говорилось, является универсальным, т.к., независимо от платформы сайта, «хлебные крошки», выводимые на странице сайта, составляются на основании url этой страницы.

Единственный нюанс – принципы формирования url на различных площадках отличаются, но об этом мы поговорим при реализации нашего алгоритма формирования «хлебных крошек» на языке PHP.

Делаем «хлебные крошки» на PHP – постановка задачи

Итак, мы наконец добрались до самого интересного :-)

В качестве наглядного примера мы будем делать «хлебные крошки» для типового корпоративного сайта, который я развернул на скорую року на базе завалявшегося у меня на компьютере шаблона.

В моём примере у сайта будет url «site.corp»

Структура нашего сайта будет следующая:

Название страницы Url
Главная страница site.corp/
О нас site.corp/about
Услуги site.corp/services
Блог site.corp/blog
Контакты site.corp/contacts

Естественно, ссылки на каждую страницу будут доступны в главном меню сайта. В итоге, шапка получилась следующая:

primer-shapki-sajta-dlya-vstatki-hlebnyh-kroshekКак раз в блоке с заголовком страницы мы и будем выводить наши «хлебные крошки».

По сути, для сайта-визитки компании больше ничего и не нужно, но в таком случае «хлебные крошки» будут содержать одну-единственную ссылку на главную страницу, что не продемонстрирует все возможности нашего кода :-)

Поэтому, с целью увеличения количества уровней иерархии нашего сайта для дальнейшего их отображения в «хлебных крошках» я решил добавить ещё две страницы, ссылки на которые будут доступны на странице «Услуги»:

Название страницы Url
Наши работы site.corp/services/portfolio
Цены site.corp/services/prices

Итак, начальные данные мы описали.

Постановка задачи будет максимально проста – необходимо сделать «хлебные крошки» на сайте, которые будут выводиться на каждой странице под её заголовком.

Теперь, непосредственно сам код.

Сразу хочу оговориться, что наш код «хлебных крошек» будет состоять из двух частей: формирования массива с названиями элементов и их url, а также кода вывода полученной структуры на странице сайта.

Код с логикой формирования «крошек» должен быть доступным на всех страницах сайта, поэтому разметить его нужно будет в контроллере, отвечающем за хэдер сайта (при условии, что у вас MVC-CMS или фреймворк) либо в файле с кодом, который будет вызываться при заходе на каждую страницу.

Только не размещайте его в шаблоне сайта – файле, содержащем html-код его страниц, т.к. это крайне нежелательно с точки зрения чистоты кода.

Формирования массива «хлебных крошек» на PHP

Приступим к написанию кода, формирующего наш массив с «хлебными крошками».

Итак, первым делом, следуя алгоритму, узнаем url текущей страницы. Для этого в PHP есть очень полезный механизм в виде суперглобального массива $_SERVER, который содержит различную информацию о выполняемом на сервере скрипте.

Текущий url будет доступен по индексу REQUEST_URI:

$cur_url = $_SERVER['REQUEST_URI'];

Далее нам необходимо разбить его на части. В нашем случае сделать это не сложно, т.к. составляющие urla отделены друг от друга слэшами, поэтому парсим текущий урл:

$urls = explode('/', $cur_url);

Создаём пустой массив, в который будем заносить информацию о названиях элементов «хлебных крошек» и их url:

$crumbs = array();

Следующий шаг алгоритма – это формирование ссылок и названий элементов. Для этого перебираем части текущего url в цикле, внутри которого создаём массив для url предыдущих элементов.

Да, «хлебные крошки», естественно, мы будем формировать для всех страниц сайта, кроме главной (лично я навигационную цепочку с единственной ссылкой на текущую страницу считаю неуместной).

В итоге, получился следующий код:

if (!empty($urls) && $cur_url != '/') {
   foreach ($urls as $key => $value) {
      $prev_urls = array();
   }
}

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

for ($i = 0; $i <= $key; $i++) {
    $prev_urls[] = $urls[$i];
}

Как видно из кода, для текущего элемента с ключом $key в массив $prev_urls будут записываться url всех предыдущих объектов, которые содержатся в url текущей страницы.

На данном этапе url предыдущих объектов содержатся в виде строковых элементов массива $prev_urls. Для сборки итогового url предшествующей страницы элементы массива нужно соединить слэшом.

Для части url текущей страницы, которая соответствует идентификатору этой же страницы мы url формировать не будем.

Поэтому добавляем во внутренний цикл следующий код:

if ($key == count($urls) - 1)
{
    $crumbs[$key]['url'] = '';
}
elseif (!empty($prev_urls))
{
    $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';
}

На данном этапе наш итоговый массив $crumbs содержит ссылки на родительские элементы иерархии. Например, для страницы «Наши работы» он будет иметь следующий вид:

Array (

    [0] => Array (
        [url] => /
    )

    [1] => Array (
        [url] => /services
    )

    [2] => Array (
        [url] =>
    )

)

Единственное, чего нам не хватает – это названия самих элементов «хлебных крошек». Для этого во внутренний цикл, после формирования url элементов, добавим заполнение массива $prev_urls названиями в следующем виде:

switch ($value) {
    case 'about' : $crumbs[$key]['text'] = 'О нас';
        break;

    case 'services' : $crumbs[$key]['text'] = 'Услуги';
        break;

    case 'blog' : $crumbs[$key]['text'] = 'Блог';
        break;

    case 'contacts' : $crumbs[$key]['text'] = 'Контакты';
        break;

    case 'portfolio' : $crumbs[$key]['text'] = 'Наши работы';
        break;

    case 'prices' : $crumbs[$key]['text'] = 'Цены';
        break;

    default : $crumbs[$key]['text'] = 'Главная страница';
        break;
}

Здесь, как видите, на основании url страницы мы прописываем название соответствующему элементу «хлебных крошек».

Да, прописывать для каждого элемента название вручную – не самый хороший вариант. Для небольших сайтов, где ограниченный порядок вложенности страниц (те же самые сайты-визитки или Интернет-магазины с 3-4 категориями) данный вариант будет терпимым.

А вот для ресурсов, где порядок вложенности задаётся динамически, т.е. для большинства крупных Интернет-проектов, такое формирование названий элементов «хлебных крошек» будет неприемлемым. Для них используются другие методы, о которых я расскажу немного позже.

Но, тем не менее, итоговый массив мы получили, который для той же страницы «Наши работы» будет иметь следующий вид:

Array(

    [0] => Array (
        [url] => /
        1 => Главная страница
    )

    [1] => Array (
        [url] => /services
        1 => Услуги
    )

    [2] => Array (
        [url] =>
        1 => Наши работы
    )

)

Осталось теперь только вывести его в шаблоне.

Вывод «хлебных крошек» в шаблоне

Итак, для вывода в шаблоне PHP-массив с «хлебными крошками» сначала нужно передать в HTML-шаблон. Универсальный способ описан в статье по ссылке, однако, в большинстве фреймворков и CMS есть свои механизмы, которые подробно описаны в их документациях.

Также, в зависимости от платформы, вывод в шаблоне массивов может производиться с помощью директив шаблонизаторов или платформенных директив.

Поскольку мы начали писать универсальный код на чистом PHP, который будет работать на любой PHP-базированной платформе, то и вывод в шаблоне мы также будем делать с помощью чистого PHP-скрипта, оформленного внутри директив <?php?>.

Для начала набросаем блок, внутри которого будут содержаться наши «хлебные крошки».

Я решил его оформить с помощью bootstrap-классов, т.к. данная библиотека включена в состав моего шаблона, вам рекомендую поискать подходящие классы в css-файлах ваших движков. Находиться блок будет под заголовком:

<section class = "title-section">
    <h1 class = "title-header"><!--Заголовок--></h1>
</section>

<section id = "inner-headline">
    <div class = "row">
        <div class = "col-lg-12">
            <!--Здесь будет код «хлебных крошек»-->
        </div>
    </div>
</section>

Итак, «хлебные крошки» мы будем делать списком с помощью тега <ul>, элементы которых будут выводиться в виде тегов <li>.

Вывод данных из массива мы будем организовывать внутри цикла, поэтому внутри заготовленного контейнера для «крошек» прописываем:

<?php if (!empty($crumbs)) { ?>
    <ul class="breadcrumb">
        <?php foreach ($crumbs as $item) { ?>
            <?php if (isset($item)) { ?>
                <li>
                    <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
                </li>
            <?php } ?>
        <?php } ?>
    </ul>
<?php } ?>

Как видите, мы выводим все элементы массива с «хлебными крошками» в виде ссылок, задав в качестве url значение элемента массива с индексом ‘url’, а текст – из значения с индексом‘text’.

Смотрим в браузере, что же у нас в итоге получилось:

primer-hlebnyh-kroshek-so-ssylkamiНеплохо, однако последний элемент, соответствующий текущей странице, также оформился в виде ссылки на текущую страницу, хотя у него значение ‘url’ пустое.

С точки зрения SEO, ссылка на странице, ведущая на саму себя, это не есть хорошо, поэтому элемент с пустым ‘url’ оформим в виде обычного текста (собственно говоря, мы его пустым и делали).

Для этого вставим в наш цикл следующую проверку:

<?php if (!empty($item['url'])) { ?>
    <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
<?php } else { ?>
    <?php echo $item['text'] ?>
<?php } ?>

Теперь наши «хлебные крошки» приобрели требуемый вид:

primer-gotovyh-hlebnyh-kroshekКрайний элемент цепочки, соответствующий текущей странице, некликабельный, а все остальные элементы оформлены в виде ссылок на соответствующие страницы, в чём можно убедиться при наведении на них курсором мышки, как на предыдущем изображении.

Как сделать «хлебные крошки» на PHP – итоговый код

В результате, код, формирующий массив с элементами «хлебных крошек» у нас принял такой вид:

$cur_url = $_SERVER['REQUEST_URI'];
$urls = explode('/', $cur_url);

$crumbs = array();

if (!empty($urls) && $cur_url != '/') {
    foreach ($urls as $key => $value) {
        $prev_urls = array();
        for ($i = 0; $i <= $key; $i++) {
            $prev_urls[] = $urls[$i];
        }
        if ($key == count($urls) - 1)
            $crumbs[$key]['url'] = '';
        elseif (!empty($prev_urls))
            $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';

        switch ($value) {
            case 'about' : $crumbs[$key]['text'] = 'О нас';
                break;
            case 'services' : $crumbs[$key]['text'] = 'Услуги';
                break;
            case 'blog' : $crumbs[$key]['text'] = 'Блог';
                break;
            case 'contacts' : $crumbs[$key]['text'] = 'Контакты';
                break;
            case 'portfolio' : $crumbs[$key]['text'] = 'Наши работы';
                break;
            case 'prices' : $crumbs[$key]['text'] = 'Цены';
                break;
            default : $crumbs[$key]['text'] = 'Главная страница';
                break;
        }
    }
}

Всё, что вам осталось для настройки данного кода на своём сайте – это прописать названия ваших страниц, принимая в качестве их идентификаторов соответствующие части текущего url.

Вообще, справедливости ради, стоит отметить, что рассмотренный нами способ хорошо подойдёт только для небольших сайтов с фиксированным количеством страниц либо для ресурсов, придерживающихся концепции ЧПУ (человеко-понятный url).

ЧПУ-сайты подойдут по той причине, что у них url страниц формируется по принципам, на которых базировался наш алгоритм – все элементы иерархии указываются в url текущей страницы.

Например, к таковым смело можно отнести популярную CMS WordPress, в которой ЧПУ идёт «из коробки».

К плюсам движков относится ещё и хранение информации о страницах в базе данных сайта, т.е. при формировании «хлебных крошек» не будет необходимости прописывать название элемента в зависимости от его url, как мы это делали в нашем примере.

Достаточно будет всего лишь достать название из БД.

Там же, в соответствующих таблицах БД хранятся связи между страницами сайта, в которых, как правило, для страниц указываются id их родительских элементов.

В таком случае, даже нет необходимости опираться на url текущей страницы и парсить его. Достаточно будет запросить из БД список всех родительских элементов текущей страницы и вывести их названия и url (также хранятся в БД) в виде «хлебных крошек».

Такой подход очень распространён в не-ЧПУ платформах, а также в проектах, где формирование текущего url происходит не добавлением родительских категорий в url, а иными способами.

К примеру, рассмотрим «коробочный» способ формирования url страниц в популярной CMS для Интернет-магазинов OpenCart:

hlebnye-kroshki-url-opencartКак видите, url не ЧПУ, т.е. в нём не присутствует никаких понятных человеку названий, только идентификаторы категории и товара, по которым можно уже достать из БД информацию о соответствующих страницах, предварительно произведя парсинг url с целью их извлечения.

Но, если в этом случае парсинг url ещё хоть как-то может быть оправдан, то в случае с OZON данные действия будут пустой тратой времени и сил, т.к. в url-е страниц нет никаких ссылок на родительские элементы:

hlebnye-kroshki-i-primer-url-ozonТут url, кстати, тоже не ЧПУ, поэтому единственный способ получения родительских элементов – это прямые запросы в БД с целью формирования «хлебных крошек», с которыми у OZON, несмотря на все особенности url, всё ОК :-)

Вывод же полученного массива «хлебных крошек» в шаблоне для всех платформ будет одинаковым и осуществляться с помощью следующего итогового кода:

<?php if (!empty($crumbs)) { ?>
    <section id="inner-headline">
        <div class="row">
            <div class="col-lg-12">
                <ul class="breadcrumb">
                    <?php foreach ($crumbs as $item) { ?>
                        <?php if (isset($item)) { ?>
                            <li>
                                <?php if (!empty($item['url'])) { ?>
                                    <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
                                <?php } else { ?>
                                    <?php echo $item['text'] ?>
                                <?php } ?>
                            </li>
                        <?php } ?>
                    <?php } ?>
                </ul>
            </div>
        </div>
    </section>
<?php } ?>

В данном случае вы также можете настраивать конфигурацию «хлебных крошек» для своего сайта, меняя стили оформления ссылок и надписей, положение «крошек» на странице и структуру блока в целом.

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

По всем вопросам настроек для вашего сайта и по поводу, как сделать «хлебные крошки» для различных CMS в целом пишите в комментариях под статьёй – ни один отзыв не останется без внимания.

Также не забывайте делиться записью со своими друзьями в социальных сетях и подписываться на обновления проекта, чтобы получать уведомления на почту о новых статьях.

На этом на сегодня всё. Жду ваших отзывов.

До новых встреч и удачи вам в сайтостроении :-)

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1
9 голосов, в среднем: 5 из 5

22 комментария к статье "Как сделать «хлебные крошки» на PHP?"

  1. Юлия

    Алексей, не поняла, прошу уточникть — php код мы прописываем в отдельном файле, а код для вставки на все страницы, где должны разместиться «крошки» он какой?

    1. Pashaster Автор

      Вообще-то и PHP код сборки хлебных крошек, и код вывода их на страницу должны присутствовать на всех страницах. Точнее, только на тех, на которых хлебные крошки нужно выводить.

      1. Юлия

        то есть на всех страницах сайта, где должны быть «хлебные крошки» во всех файлах php and html я должна на месте хлебных крошек разместить вот этот итоговый код?

        …..

        1. Pashaster Автор

          Что-то вместо кода в Вашем сообщении многоточие стоит) А вообще итоговый код — это ,блоки кода из последнего раздела «Как сделать «хлебные крошки» на PHP – итоговый код». Первый блок — это PHP, второй — HTML.

          О том, как подключать скрипты на разный языках на сайте, — читайте здесь.

      2. Александр

        Pashaster, добрый день, столкнулся с одной задачей, реализация хлебных крошек на шаблонизаторе smarty где используются контроллеры на категории и на товар, и url страницы выглядит так:
        на страницу категорий и списка товара категории: /?controller=category&id=300
        на страницу продукта: /?controller=product&id=710
        Мне необходимо создать хлебную крошку на странице продукта, которая будет выводить на предыдущую страницу категории откуда пришел, но что-то сколько в интернете ищу и читаю, ничего полезного не нахожу, встретил ваш сайт, почитал, все довольно интересно. Если у вас есть имеющийся опыт в решении подобных вопросов и идеи как правильно реализовать, подскажите пожалуйста.

        1. Pashaster Автор

          Приветсвую Вас :-) Ситуация у вас нетривиальная, но ничего сложного нет.

          Как вариант, содержимое массива «хлебных крошек» можно формировать прямо внутри классов PHP, которые выводят на экран smarty-шаблоны. На одном моём старом проекте так и было)

          Если же делать формирование «хлебных крошек» отдельным php скриптом, то я могу порекомендовать следующий алгоритм действий:

          1. Парсим текущий url, чтобы выделить тип сущности (category/product) и id сущности (конкретного товара/категории)
          2. В файле формирования «хлебных крошек» проверяем тип сущности и по её id вытягиваем её название из соответствующей таблицы БД.

          Код будет следующий:
          1. Распарсить можно с помощью регулярных выражений, но я их не очень люблю, если честно :-) Поэтому рекомендую воспользоваться следующей конструкцией:

          $url = $_SERVER['REQUEST_URI'];
                  
          $params = parse_url($url, PHP_URL_QUERY);
          parse_str($params, $matches);
          

          В результате, в массиве $matches будет следующий результат:

          Array
          (
              [controller] => category
              [id] => 211
          )
          

          2. Для получения заголовка сущности Вам нужно будет изменить switch case для формирования текста сегментов «хлебных крошек».

          Приведённый ниже код написан для Laravel PHP framework, потому что мне нужно было как-то описать извлечение данных из БД. Вы же вместо моих конструкций будете использовать свои классы и методы.

          switch ($matches['controller']) {
              case 'category' :
                  $crumbs[1]['url'] = '';
                  $crumbs[1]['text'] = Category::where('id', '=', $matches['id'])->first()->title;
                  break;
              case 'product' :
                  $product = Product::where('id', '=', $matches['id'])->first();
                  $category = $product->categories->first();
          
                  $crumbs[1]['url'] = '/?controller=category&id=' + $matches['id'];
                  $crumbs[1]['text'] = $category->name;
          
                  $crumbs[2]['url'] = '';
                  $crumbs[2]['text'] = $product->name;
                  break;
              default:
                  $crumbs[1]['url'] = '';
                  $crumbs[1]['text'] = 'Страница не найдена';
                  break;
          }
          

          Данный блок будет формировать «хлебные крошки» и на странице категории, и на странице продукта. Если наименование контроллера будет отлично от category/product или пустым, то в хлебных крошках будет текст «страница не найдена». В целом, скрипт, формирующий php breadcrumbs, в Вашем случае будет следующий:

          $url = $_SERVER['REQUEST_URI'];
          
          $params = parse_url($url, PHP_URL_QUERY);
          parse_str($params, $matches);
          
          $crumbs[0]['text'] = 'Главная';
          $crumbs[0]['url'] = '/';
          
          switch ($matches['controller']) {
              case 'category' :
                  $crumbs[1]['url'] = '';
                  $crumbs[1]['text'] = Category::where('id', '=', $matches['id'])->first()->title;
                  break;
              case 'product' :
                  $product = Product::where('id', '=', $matches['id'])->first();
                  $category = $product->categories->first();
          
                  $crumbs[1]['url'] = '/?controller=category&id=' + $matches['id'];
                  $crumbs[1]['text'] = $category->name;
          
                  $crumbs[2]['url'] = '';
                  $crumbs[2]['text'] = $product->name;
                  break;
              default:
                  $crumbs[1]['url'] = '';
                  $crumbs[1]['text'] = 'Страница не найдена';
                  break;
          }
          

          Если возникнут какие-то вопросы — пишите :-)

  2. Евгений

    У вас ошибка в коде вывода
    а должно быть

    Подскажите, как переделать этот код для URl со слешом на конце? А то в конце крошек опять выводит «Главная»

    1. Pashaster Автор

      Чтобы код формировал хлебные крошки на PHP корректно для URI со слешом на конце, нужно после строки

      $cur_url = $_SERVER['REQUEST_URI'];
      

      Вставить такой код:

      $cur_url = substr($cur_url, 0, -1);
      

      И ещё вместо строки

      $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';
      

      нужно вставить следующую:

      $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) . '/' : '/';
      

      Это нужно для формирования ссылок на предыдущие разделы иерархии со слешом в конце URI.
      «У вас ошибка в коде вывода» — какую именно ошибку Вы имели ввиду?

      1. Антон

        Идиотский мануал, очевидно не для чайников, например таких как я. А кто не чайник в php, и без подобных мануалов напишет хлебные крошки.
        Верно пишет Евгений — ошибка в выводе. Откуда вообще взялся $item?
        По результату, применив данный код имеем ошибку:
        Notice: Undefined variable: item in /public_html/bc.php on line 39
        39 строка, это:
        Заменив $crumbs[$key] на $item — получаем на выходе только «главная страница».

        1. Pashaster Автор

          Добрый вечер!

          $item — это элемент массива $breadcrumbs, на которые последний разбирается функцией PHP foreach:

          <?php foreach($breadcrumbs as $item){ ?>
          

          Ошибка, которую Вы указали, не является критичной, т.к. это всего лишь Notice, а не Error. От неё, кстати, легко можно избавиться добавлением банальной проверки на инициализацию переменной:

          <?php if(isset($item)){ ?>
              <?php if(!empty($item['url'])){ ?>
                  <a href="<?php echo $item['url'] ?>"><?php echo $item['text'] ?></a>
              <?php } else { ?>
                  <?php echo $item['text'] ?>
              <?php } ?>
          <?php } ?>
          

          Ну, а по поводу вывода в «хлебных крошках» только «Главная страница» — тут мой косяк, признаю :-) Дело в том, что мы формировали массив крошек $breadcrumbs, а в шаблоне делаем вывод содержимого массива $crumbs.

          Поменяйте строчку:

          <?php foreach($breadcrumbs as $item){ ?>
          

          на

          <?php foreach($crumbs as $item){ ?>
          

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

          P.S. Давайте на будущее договоримся. Если у Вас что-то не получилось при «прикручивании» кода — это ещё не повод ставить клеймо на весь материал. Достаточно конструктивно и тактично сообщить об ошибке — в таком случае больше шансов получить рабочий код :-)

          1. Евгений

            Точно, вот эта ошибка была с breadcrumbs и crumbs :)

      2. Евгений

        Спасибо большое, все работает! Самый лаконичный материал по крошкам, который удалось найти.
        По ошибке — было что-то из разряда простых опечаток, сейчас уже не могу найти, видимо вы исправили.
        Ps В моем предыдущем сообщении был код, но он не прошел видимо.

  3. Ант

    А как вывести только предпоследний каталог? Например что бы при нахождении на странице товара (телефон iPhone 7), была ссылка на предыдущий каталог продукции Apple.

    1. Pashaster Автор

      Добрый вечер. В вашем случае PHP скрипт, формирующий массив элементов «хлебных крошек» будет выглядеть примерно так:

      $cur_url = $_SERVER['REQUEST_URI'];
      $urls = explode('/', $cur_url);
       
      $crumbs = array();
       
      if (!empty($urls) && $cur_url != '/') {
      	
      	array_pop($urls);
      	
          foreach ($urls as $key => $value) {
              $prev_urls = array();
              for ($i = 0; $i <= $key; $i++) {
                  $prev_urls[] = $urls[$i];
              }
              if (!empty($prev_urls))
                  $crumbs[$key]['url'] = count($prev_urls) > 1 ? implode('/', $prev_urls) : '/';
      			
              switch ($value) {
      			case '' : $crumbs[$key]['text'] = 'Главная страница';
      				break;
                  default : $crumbs[$key]['text'] = ucfirst($value);
                      break;
              }
          }
      }
      

      Код вывода breadcrumbs на фронтальную часть сайта останется без изменений.

      1. Ант

        Спасибо за ответ) но выводится всё равно весь путь (главная->каталог->категория->раздел), а как получить ТОЛЬКО предыдущий раздел?
        То есть предположим вот структура (главная->каталог->категория->раздел->страница на которой мы находимся), как находясь на последней странице получить ОДНУ ссылку на предыдущий раздел «раздел»?
        Что бы её вставить в тег (а) — «предыдущий раздел». Что бы мы кликнув по ссылке перешли на уровень ниже

        1. Pashaster Автор

          В ситуации, когда в «хлебных крошках» должна быть одна-единственная ссылка на категорию, реализация вообще предельно упрощается.

          Массив крошек будет содержать один-единственный элемент, а сам массив будет формироваться следующим образом:

          $cur_url = $_SERVER['REQUEST_URI'];
          $urls = explode('/', $cur_url);
            
          $crumbs = array();
            
          if (!empty($urls) && $cur_url != '/') {
          	$category = $urls[count($urls) - 2];
          	$crumbs[] = ['url' => '/' . $category, 'text' => ucfirst($category)];
          }
          

          Вывод breadcrumbs на экран тоже можно существенно упростить, исключив перебор массива:

          <?php if (!empty($crumbs) && !empty($crumbs[0])) { ?>
              <section id="inner-headline">
                  <div class="row">
                      <div class="col-lg-12">
                          <ul class="breadcrumb">
                              <li>
                                  <?php if (!empty($crumbs[0]['url'])) { ?>
                                      <a href="<?php echo $crumbs[0]['url'] ?>"><?php echo $crumbs[0]['text'] ?></a>
                                  <?php } else { ?>
                                      <?php echo $crumbs[0]['text'] ?>
                                  <?php } ?>
                              </li>
                          </ul>
                      </div>
                  </div>
              </section>
          <?php } ?>
          

          Надеюсь, мой ответ был полезен :-)

          1. Ант

            Спасибо большое, ваши ответы очень полезны мне)
            Теперь ссылка действительно одна, и на предыдущий каталог, только она ведёт на несуществующую страницу т.к. в ссылке пропущены разделы.
            Получается ссылка вида (главная->(и сразу)->предыдущий раздел), но между главной и предыдущим разделом находятся ещё категории, и их нет в ссылке, в её пути.

          2. Pashaster Автор

            Это же Ваш вопрос был — «Спасибо за ответ) но выводится всё равно весь путь (главная->каталог->категория->раздел), а как получить ТОЛЬКО предыдущий раздел?». Я на него ответил. В последнем варианте кода в хлебных крошках будет исключительно ссылка на предыдущий раздел, взятая из URL текущей страницы. Даже ссылку на главную не будет, как Вы пишите — «(главная->(и сразу)->предыдущий раздел)».

            Вы уже определитесь, что Вам нужно :-)

            Если вопрос касается отсутствия ссылки на категорию, которой нет в URL, то тут я Вам ничем не помогу, т.к. изложенный в статье способ формирования «хлебных крошек» основан как раз на парсинге URL текущей страницы.

  4. Ант

    хаха)) извините за каламбур, сейчас объясню поподробнее что я имел ввиду)

    В первом варианте выводится вариант хлебных крошек в виде нескольких ссылок, на каждый предыдущий раздел:

    1 ссылка) главная->
    2 ссылка) главная->каталог->
    3 ссылка) главная->каталог->категория->
    4 ссылка) главная->каталог->категория->страница на которой мы находимся

    В итоге мы всё это упаковываем в строку и получаем хлебные крошки вида:
    1) / 2) / 3) / 4 — 4 ссылки, и каждая начинается от корня сайта.

    Можем ткнуть на любую и перейти в соответствующий раздел.

    А я имел ввиду вопрос: как реализовать одну хлебную крошку, на предыдущий раздел, то есть используя ту же логику что и выше, что бы получилось следующее:

    1 ссылка) главная->каталог->категория

    В итоге мы получаем одну хлебную крошку вида:
    1) — 1 ссылка начиная от корня сайта, до предыдущего раздела.

    А в последнем примере ссылка одна, но путь не полный:

    1 ссылка) главная->и сразу же предпоследняя категория, и получается что ссылка ведёт на страницу 404, так как страницы с подобным адресом не существует.

    1. Ант

      У вас есть картинка с примером магазина OZONE, и телефона Apple iPhone.

      Там есть хлебные крошки вида:

      Электроника/Телефоны/Смартфоны/Apple

      Дак вот представьте что нужно только предыдущий раздел

      Что бы было просто: Apple

      И ссылка была полной, от корня

      1. Pashaster Автор

        Тогда в вашем случае формирования массива «хлебных крошек» в PHP будет происходить так:

        $cur_url = $_SERVER['REQUEST_URI'];
        $urls = explode('/', $cur_url);
           
        $crumbs = array();
           
        if (!empty($urls) && $cur_url != '/') {
            $category = $urls[count($urls) - 2];
        	$category_url = substr($cur_url, 0, strrpos($cur_url, '/') + 1);
        	
            $crumbs[] = ['url' => $category_url, 'text' => ucfirst($category)];
        }
        

        Вывод breadcrumbs на экран будет происходить с помощью того же кода, что и в моём последнем примере. Надеюсь, теперь полученный код решит Вашу проблему :-)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *