Hướng dẫn custom Drupal breadcrumbs

Hướng dẫn custom Drupal breadcrumbs

In which GUI and breadcrumbs don't get along

Ah, breadcrumbs, how I hate you. Such a tiny little piece of a site, yet so much complexity and time spent. For some clients, you would think this is their number one must have feature based on how much time they spend checking and critiquing them page-by-page.

Existing solutions

In typical Drupal fashion, "there's a module for that!" Or more truthfully, "there are 17 modules for that!" Let's run down a few.

Please note that I am NOT hating on these modules because they're bad. Most of them are actually quite good for the tough problem they're trying to solve.

Custom Breadcrumbs

Custom Breadcrumbs is perhaps one of the earliest modules for this, dating all the way back to 2006. It has a bunch of submodules and a fancy interface that looks like this:

Hướng dẫn custom Drupal breadcrumbs

And that's just nodes. There are also interfaces for Views, Panels, Taxonomy, and Paths. Now, I'm not saying this interface is bad--it's not. But I bet you couldn't understand it at first glance. That's because breadcrumbs are just a hard thing to configure visually.(I'm going to say that again so be ready).

How much code does Custom Breadcrumbs ship with?

wc -l **/*


870 custom_breadcrumbs.admin.inc

wc: custom_breadcrumbsapi: Is a directory

0 custom_breadcrumbsapi

15 custom_breadcrumbsapi/custom_breadcrumbsapi.info

75 custom_breadcrumbsapi/custom_breadcrumbsapi.install

195 custom_breadcrumbsapi/custom_breadcrumbsapi.module

209 custom_breadcrumbs_common.inc

wc: custom_breadcrumbs_identifiers: Is a directory

0 custom_breadcrumbs_identifiers

15 custom_breadcrumbs_identifiers/custom_breadcrumbs_identifiers.info

202 custom_breadcrumbs_identifiers/custom_breadcrumbs_identifiers.module

17 custom_breadcrumbs.info

219 custom_breadcrumbs.install

1245 custom_breadcrumbs.module

wc: custom_breadcrumbs_panels: Is a directory

0 custom_breadcrumbs_panels

19 custom_breadcrumbs_panels/custom_breadcrumbs_panels.info

83 custom_breadcrumbs_panels/custom_breadcrumbs_panels.install

262 custom_breadcrumbs_panels/custom_breadcrumbs_panels.module

wc: custom_breadcrumbs_paths: Is a directory

0 custom_breadcrumbs_paths

19 custom_breadcrumbs_paths/custom_breadcrumbs_paths.info

136 custom_breadcrumbs_paths/custom_breadcrumbs_paths.install

310 custom_breadcrumbs_paths/custom_breadcrumbs_paths.module

wc: custom_breadcrumbs_taxonomy: Is a directory

0 custom_breadcrumbs_taxonomy

146 custom_breadcrumbs_taxonomy/custom_breadcrumbs_taxonomy.admin.inc

419 custom_breadcrumbs_taxonomy/custom_breadcrumbs_taxonomy.inc

18 custom_breadcrumbs_taxonomy/custom_breadcrumbs_taxonomy.info

220 custom_breadcrumbs_taxonomy/custom_breadcrumbs_taxonomy.install

596 custom_breadcrumbs_taxonomy/custom_breadcrumbs_taxonomy.module

wc: custom_breadcrumbs_views: Is a directory

0 custom_breadcrumbs_views

17 custom_breadcrumbs_views/custom_breadcrumbs_views.info

118 custom_breadcrumbs_views/custom_breadcrumbs_views.install

174 custom_breadcrumbs_views/custom_breadcrumbs_views.module

339 LICENSE.txt

302 README.txt

6258 total

That's 6258 lines, counting a few text files and comments and blank lines. For Breadcrumbs. Debugging when things don't work as they should is obviously no picnic.


Crumbs is less than 4 years old so it's just a toddler compared to Custom Breadcrumbs. Let's take a look at a few of its admin pages.

Here's how you specify a breadcrumb pattern for content:

Content patterns

And here's a snippet of how you choose which plugins take priority over other plugins:

Plugin weights

Again, these aren't bad interfaces by any means. They're just symptoms of the problem, which is that breadcrumbs are just a hard thing to configure visually.

How about code?

0 admin

249 admin/crumbs.admin.inc

160 admin/crumbs.debug.inc

105 admin/crumbs.entity_parent.inc

55 admin/crumbs.expansible.inc

29 admin/crumbs.tabledrag.inc

14 admin/crumbs.textual.inc

144 crumbs.api.php

13 crumbs.info

67 crumbs.install

629 crumbs.module

0 css

217 css/crumbs.admin.expansible.css

0 example

13 example/crumbs_example.info

41 example/crumbs_example.module

0 example/lib

0 example/lib/CrumbsMonoPlugin

71 example/lib/CrumbsMonoPlugin/NewsByDate.php

0 example/lib/CrumbsMultiPlugin

42 example/lib/CrumbsMultiPlugin/ListOfNews.php

0 images

0 images/queue

8 images/queue/businessmen.png

6 images/queue/cartpusher.png

7 images/queue/dinocar.png

14 images/queue/donkeyman.png

6 images/queue/duckie.png

5 images/queue/elephant.png

20 images/queue-sprite-color.png

18 images/queue-sprite-grayscale.png

0 js

746 js/crumbs.admin.expansible.js

0 labs

12 labs/crumbs_labs.info

34 labs/crumbs_labs.module

0 lib

0 lib/Admin

0 lib/Admin/ElementObject

78 lib/Admin/ElementObject/Abstract.php

13 lib/Admin/ElementObject/WeightsAbstract.php

85 lib/Admin/ElementObject/WeightsExpansible.php

128 lib/Admin/ElementObject/WeightsTabledrag.php

165 lib/Admin/ElementObject/WeightsTextual.php

214 lib/Admin/WeightsTable.php

39 lib/BreadcrumbBuilder.php

75 lib/CallbackRestoration.php

0 lib/Container

176 lib/Container/CachedLazyPluginInfo.php

39 lib/Container/LazyDataByPath.php

47 lib/Container/LazyData.php

20 lib/Container/LazyPageData.php

16 lib/Container/LazyServices.php

25 lib/Container/MultiWildcardDataIterator.php

54 lib/Container/MultiWildcardDataOffset.php

80 lib/Container/MultiWildcardData.php

12 lib/Container/README.txt

172 lib/Container/WildcardData.php

40 lib/Container/WildcardDataSorted.php

0 lib/CrumbsEntityPlugin

38 lib/CrumbsEntityPlugin/TokenDisabled.php

36 lib/CrumbsEntityPlugin/TokenEnabled.php

274 lib/CurrentPageInfo.php

0 lib/Debug

149 lib/Debug/CandidateLogger.php

0 lib/Drupal

0 lib/Drupal/crumbs

0 lib/Drupal/crumbs/Tests

51 lib/Drupal/crumbs/Tests/MenuLinkPluginTest.php

31 lib/Drupal/crumbs/Tests/README.txt

0 lib/EntityPlugin

68 lib/EntityPlugin/Callback.php

0 lib/EntityPlugin/Field

68 lib/EntityPlugin/Field/Abstract.php

21 lib/EntityPlugin/Field/EntityReference.php

43 lib/EntityPlugin/Field/TermReference.php

12 lib/EntityPlugin/Field/Text.php

29 lib/EntityPlugin.php

0 lib/InjectedAPI

38 lib/InjectedAPI/describeMonoPlugin.php

68 lib/InjectedAPI/describeMultiPlugin.php

461 lib/InjectedAPI/hookCrumbsPlugins.php

0 lib/MonoPlugin

16 lib/MonoPlugin/FindParentInterface.php

16 lib/MonoPlugin/FindTitleInterface.php

29 lib/MonoPlugin/FixedParentPath.php

59 lib/MonoPlugin/ParentPathCallback.php

18 lib/MonoPlugin.php

17 lib/MonoPlugin/SkipItem.php

59 lib/MonoPlugin/TitleCallback.php

29 lib/MonoPlugin/TranslateTitle.php

0 lib/MultiPlugin

43 lib/MultiPlugin/EntityFindAbstract.php

128 lib/MultiPlugin/EntityFindSomething.php

11 lib/MultiPlugin/EntityParent.php

11 lib/MultiPlugin/EntityTitle.php

16 lib/MultiPlugin/FindParentInterface.php

16 lib/MultiPlugin/FindTitleInterface.php

22 lib/MultiPlugin.php

71 lib/ParentFinder.php

203 lib/PluginEngine.php

336 lib/PluginInfo.php

4 lib/PluginInterface.php

0 lib/PluginOperation

231 lib/PluginOperation/describe.php

112 lib/Router.php

108 lib/ServiceFactory.php

79 lib/TrailFinder.php

4 lib/UnserializeException.php

115 lib/Util.php

339 LICENSE.txt

0 plugins

58 plugins/crumbs.blog.inc

76 plugins/crumbs.comment.inc

66 plugins/crumbs.commerce_checkout.inc

46 plugins/crumbs.crumbs.inc

19 plugins/crumbs.entityreference.inc

102 plugins/crumbs.entityreference_prepopulate.inc

204 plugins/crumbs.forum.inc

204 plugins/crumbs.menu.inc

217 plugins/crumbs.og.2.inc

193 plugins/crumbs.og.inc

37 plugins/crumbs.path.inc

11 plugins/crumbs.search.inc

55 plugins/crumbs.taxonomy.inc

32 plugins/crumbs.text.inc

86 plugins/crumbs.views.inc

47 README.txt

9135 total

Crumbs currently ships with 9135 lines of code, again including text files and comments and blank lines.


Hansel is about as old as Crumbs and touts the slogan "Breadcrumbs done right!" It contains 7 modules (one each for Domain, OG, Taxonomy, Forum, Exporting, the UI, and core functionality) and weighs in at a lightweight 4421 lines currently.

wc -l **/*

wc: domain: Is a directory

0 domain

14 domain/hansel_domain.info

89 domain/hansel_domain.module

wc: export: Is a directory

0 export

12 export/hansel_export.info

343 export/hansel_export.module

wc: forum: Is a directory

0 forum

14 forum/hansel_forum.info

145 forum/hansel_forum.module

190 hansel.actions.inc

63 hansel.hooks.inc

11 hansel.info

114 hansel.install

735 hansel.module

221 hansel.switches.inc

wc: hansel_ui: Is a directory

0 hansel_ui

wc: hansel_ui/css: Is a directory

0 hansel_ui/css

61 hansel_ui/css/hansel_ui.css

11 hansel_ui/hansel_ui.info

883 hansel_ui/hansel_ui.module

62 hansel_ui/hansel_ui.registry.inc

88 hansel_ui/hansel_ui.test.inc

wc: hansel_ui/js: Is a directory

0 hansel_ui/js

34 hansel_ui/js/hansel_ui.js

6 hansel_ui/sprites.png

339 LICENSE.txt

wc: og: Is a directory

0 og

12 og/hansel_og.info

124 og/hansel_og.module

678 README.txt

wc: taxonomy: Is a directory

0 taxonomy

12 taxonomy/hansel_taxonomy.info

160 taxonomy/hansel_taxonomy.module

4421 total

Here's what it looks like:

Hansel UI

Would you know what to enter where on that screen? Would you know how to build out breadcrumbs for nodes tagged with a taxonomy using that? Yet again, this isn't a problem with the module, the module is fine. Breadcrumbs are just a hard thing to configure visually.


This list is by no means complete. Here are a few others that exist and are, in my perhaps grumpy opinion, either lacking in functionality or equally as bulky and confusing.

  • Path Breadcrumbs (here's a screenshot)

  • Breadcrumbs By Path (only works for items that follow a predictable nested URL aliasing convention)

  • Menu Breadcrumb (only works for items in menus)

  • Others? If you know of another breadcrumb module that you absolutely love, feel free to tell me all about it in the comments.

Why are we here?

Easy! Breadcrumbs are just a hard thing to configure visually!

They can depend on so many things and they need to satisfy so many different use cases, that it's just really hard to support all of that and do it in a way that isn't a GUI onslaught.

Let's take a specific example. Say we have just one single content type (just one!) called "Story". And let's pretend that there's a "Category" taxonomy attached to it. Here are some very common and completely valid ways one might want to set up those breadcrumbs:

  1. Make all news authored by a specific user named John Writer follow the "Editorials > John Doe > Title Of Post" pattern.

  2. Make all news under the "Press Release" taxonomy term (in the Categories vocabulary) follow the "Press Releases > Title Of Post" pattern

  3. Make all news posted before the current calendar year follow the "News Archive > Year > Month > Title Of Post" pattern

  4. Make all news posted in the "Blog" taxonomy term follow the "Blog > Author's Name > Year > Month > Title Of Post" pattern

So that's four completely different use cases all on the same content type with only one taxonomy attached to it. That doesn't even touch on multiple content types, multiple taxonomies, different entities (user profiles, and Drupal Commerce products are quite common) or even non-entity pages (Views pages, Panels pages, etc.).

Do you see what I mean? It's a losing game.

Blame "Invented Here" syndrome or Drupal's love of all things GUI, or both. Either way, most people are trying to make the best of a bad thing by working around the various failings of these contrib modules.

An alternative approach

You are a programmer. Do it in code. It's easy! Just use our frienddrupal_set_breadcrumb() like so:


// Build the breadcrumbs in the format Home > News > Title Of Post

$breadcrumb = array();

$breadcrumb[] = l(t('Home'), '<front>');

$breadcrumb[] = l(t('News'), 'news');

$breadcrumb[] = l(drupal_get_title(), base_path() . request_uri()); // Link to current URL

// Set the breadcrumbs


Here's a rundown of how you could satisfy the 4 use cases above in code, in a few minutes.

  1. Use hook_node_view($node), grab the author out of $node->uid, and if it's John Writer, set that custom beadcrumb usingdrupal_set_breadcrumb().

  2. Use hook_node_view($node), grab the category out of $node->field_news_categories (or whatever the field is called), and run taxonomy_term_load() to grab the whole term, and if the$term->name is "Press Release", then set that breadcrumb.

  3. Use hook_node_view($node), and if date('Y', $node->created) < date('Y') then set the breadcrumb by passingdate('Y', $node->created) and date('F', $node->created) into drupal_set_breadcrumb() for the year and month.

  4. Same basic idea as #2 above.

Or maybe you're adding breadcrumbs for a Views page? Throw it in a Views hook like hook_views_pre_render(&$view). Oh, you're trying to add breadcrumbs to a taxonomy term page? Throw adrupal_set_breadcrumb() intohook_taxonomy_term_view($term) and call it a day.

See what I mean? This is basic stuff for any Drupal developer, and it saves you many thousands of lines of code and potentially a lot of time debugging that code and trying to understand the interfaces.


This method won't work when you're dealing with either of the following scenarios:

  1. You need to accommodate new breadcrumb patterns as things are changed without being able to make code changes. For example, a new promotion is being run tomorrow, with no notice, and that's not enough time to push a code change through QA and find a decent launch window by then. Or maybe you're just an editor who doesn't have code access at all.

  2. You need to accommodate clients who want to add and configure their own breadcrumbs without relying on you to code it. There's still the difficulty in getting them a module with a UX they can wrap their non-technical brains around, but it's more doable than teaching them to code.

However, if you're not in one of those two situations, then I highly recommend you rid yourself of whatever breadcrumb GUI you've been using.

Or convince the client to get rid of breadcrumbs altogether!

Bạn thấy bài viết này như thế nào?: 
No votes yet
Ảnh của Tommy Tran

Tommy Tran owner Express Magazine

Drupal Developer having 9+ year experience, implementation and having strong knowledge of technical specifications, workflow development. Ability to perform effectively and efficiently in team and individually. Always enthusiastic and interseted to study new technologies

  • Skype ID: tthanhthuy
  • Phone/Zalo: (+84) 944 225 212
  • WhatsApp: (+84) 944 225 212
  • Line Messenger: (+84) 944 225 212
  • Email: asaleotestf@gmail.com
  • Telegram Messenger: https:/t.me/tommytran0401

Quảng cáo việc làm


Thích hợp các bạn nữ mảng thợ may làm việc tại nước NGA

Đơn hàng Tuyển dụng 100 Thợ may đi Nga(đợt 1 tháng 3.2021, đợt 2 tháng 5.2021). Lương thực lãnh 800 USD, bao ăn ở, vé máy bay và visa, phí xuất cảnh(1800 USD)trả khi đi làm có lương. Bạn có thể liên hệ CÔNG TY qua Phone/Zalo: (+84) 944 225 212. Công ty sẽ tư vấn cho bạn.

Xem chi tiết: >>> https://bit.ly/3o9NOfR

Tìm kiếm bất động sản





Dich vu khu trung tphcm

Dich vu diet chuot tphcm

Dich vu diet con trung

Quảng Cáo Bài Viết

Khái niệm mới Decoupling Drupal (decoupled CMS)

Khái niệm mới Decoupling Drupal (decoupled CMS)

Drupal 8 will make huge strides in this area, but alas it's not out yet. Fortunately the answer to the second problem is the first; it is entirely possible to build a solid, scalable, performant RESTful web service with Drupal 7

Tìm và xem video clip HD trên YouTube theo phong cách mới

Tìm và xem video clip HD trên YouTube theo phong cách mới

ShowMeNonStop sẽ lần lượt trình chiếu các video clip chất lượng cao trên YouTube về một chủ đề để bạn thưởng thức “đã” hơn.

Timeline Facebook thử nghiệm bố trí mới của ảnh cover

Timeline Facebook thử nghiệm bố trí mới của ảnh cover

Có vẻ như sắp tới giao diện Timeline của Facebook lại có chút thay đổi.