Breadcrumbs.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\widgets;
  8. use Yii;
  9. use yii\base\InvalidConfigException;
  10. use yii\base\Widget;
  11. use yii\helpers\ArrayHelper;
  12. use yii\helpers\Html;
  13. /**
  14. * Breadcrumbs displays a list of links indicating the position of the current page in the whole site hierarchy.
  15. *
  16. * For example, breadcrumbs like "Home / Sample Post / Edit" means the user is viewing an edit page
  17. * for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home"
  18. * to return to the homepage.
  19. *
  20. * To use Breadcrumbs, you need to configure its [[links]] property, which specifies the links to be displayed. For example,
  21. *
  22. * ```php
  23. * // $this is the view object currently being used
  24. * echo Breadcrumbs::widget([
  25. * 'itemTemplate' => "<li><i>{link}</i></li>\n", // template for all links
  26. * 'links' => [
  27. * [
  28. * 'label' => 'Post Category',
  29. * 'url' => ['post-category/view', 'id' => 10],
  30. * 'template' => "<li><b>{link}</b></li>\n", // template for this link only
  31. * ],
  32. * ['label' => 'Sample Post', 'url' => ['post/edit', 'id' => 1]],
  33. * 'Edit',
  34. * ],
  35. * ]);
  36. * ```
  37. *
  38. * Because breadcrumbs usually appears in nearly every page of a website, you may consider placing it in a layout view.
  39. * You can use a view parameter (e.g. `$this->params['breadcrumbs']`) to configure the links in different
  40. * views. In the layout view, you assign this view parameter to the [[links]] property like the following:
  41. *
  42. * ```php
  43. * // $this is the view object currently being used
  44. * echo Breadcrumbs::widget([
  45. * 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
  46. * ]);
  47. * ```
  48. *
  49. * @author Qiang Xue <qiang.xue@gmail.com>
  50. * @since 2.0
  51. */
  52. class Breadcrumbs extends Widget
  53. {
  54. /**
  55. * @var string the name of the breadcrumb container tag.
  56. */
  57. public $tag = 'ul';
  58. /**
  59. * @var array the HTML attributes for the breadcrumb container tag.
  60. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
  61. */
  62. public $options = ['class' => 'breadcrumb'];
  63. /**
  64. * @var bool whether to HTML-encode the link labels.
  65. */
  66. public $encodeLabels = true;
  67. /**
  68. * @var array the first hyperlink in the breadcrumbs (called home link).
  69. * Please refer to [[links]] on the format of the link.
  70. * If this property is not set, it will default to a link pointing to [[\yii\web\Application::homeUrl]]
  71. * with the label 'Home'. If this property is false, the home link will not be rendered.
  72. */
  73. public $homeLink;
  74. /**
  75. * @var array list of links to appear in the breadcrumbs. If this property is empty,
  76. * the widget will not render anything. Each array element represents a single link in the breadcrumbs
  77. * with the following structure:
  78. *
  79. * ```php
  80. * [
  81. * 'label' => 'label of the link', // required
  82. * 'url' => 'url of the link', // optional, will be processed by Url::to()
  83. * 'template' => 'own template of the item', // optional, if not set $this->itemTemplate will be used
  84. * ]
  85. * ```
  86. *
  87. * If a link is active, you only need to specify its "label", and instead of writing `['label' => $label]`,
  88. * you may simply use `$label`.
  89. *
  90. * Since version 2.0.1, any additional array elements for each link will be treated as the HTML attributes
  91. * for the hyperlink tag. For example, the following link specification will generate a hyperlink
  92. * with CSS class `external`:
  93. *
  94. * ```php
  95. * [
  96. * 'label' => 'demo',
  97. * 'url' => 'http://example.com',
  98. * 'class' => 'external',
  99. * ]
  100. * ```
  101. *
  102. * Since version 2.0.3 each individual link can override global [[encodeLabels]] param like the following:
  103. *
  104. * ```php
  105. * [
  106. * 'label' => '<strong>Hello!</strong>',
  107. * 'encode' => false,
  108. * ]
  109. * ```
  110. */
  111. public $links = [];
  112. /**
  113. * @var string the template used to render each inactive item in the breadcrumbs. The token `{link}`
  114. * will be replaced with the actual HTML link for each inactive item.
  115. */
  116. public $itemTemplate = "<li>{link}</li>\n";
  117. /**
  118. * @var string the template used to render each active item in the breadcrumbs. The token `{link}`
  119. * will be replaced with the actual HTML link for each active item.
  120. */
  121. public $activeItemTemplate = "<li class=\"active\">{link}</li>\n";
  122. /**
  123. * Renders the widget.
  124. */
  125. public function run()
  126. {
  127. if (empty($this->links)) {
  128. return;
  129. }
  130. $links = [];
  131. if ($this->homeLink === null) {
  132. $links[] = $this->renderItem([
  133. 'label' => Yii::t('yii', 'Home'),
  134. 'url' => Yii::$app->homeUrl,
  135. ], $this->itemTemplate);
  136. } elseif ($this->homeLink !== false) {
  137. $links[] = $this->renderItem($this->homeLink, $this->itemTemplate);
  138. }
  139. foreach ($this->links as $link) {
  140. if (!is_array($link)) {
  141. $link = ['label' => $link];
  142. }
  143. $links[] = $this->renderItem($link, isset($link['url']) ? $this->itemTemplate : $this->activeItemTemplate);
  144. }
  145. echo Html::tag($this->tag, implode('', $links), $this->options);
  146. }
  147. /**
  148. * Renders a single breadcrumb item.
  149. * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
  150. * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link.
  151. * @return string the rendering result
  152. * @throws InvalidConfigException if `$link` does not have "label" element.
  153. */
  154. protected function renderItem($link, $template)
  155. {
  156. $encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels);
  157. if (array_key_exists('label', $link)) {
  158. $label = $encodeLabel ? Html::encode($link['label']) : $link['label'];
  159. } else {
  160. throw new InvalidConfigException('The "label" element is required for each link.');
  161. }
  162. if (isset($link['template'])) {
  163. $template = $link['template'];
  164. }
  165. if (isset($link['url'])) {
  166. $options = $link;
  167. unset($options['template'], $options['label'], $options['url']);
  168. $link = Html::a($label, $link['url'], $options);
  169. } else {
  170. $link = $label;
  171. }
  172. return strtr($template, ['{link}' => $link]);
  173. }
  174. }