---
title: 'Табы в Друпале'
url: 'https://graker.ru/news/2009/10/28/taby_v_drupale'
language: ru
type: post
author: 'Роман Грачев'
published: '2009-10-28T15:42:12+03:00'
updated: '2016-08-11T16:51:16+03:00'
categories:
  - Программирование
  - Друпальчики
---

# Табы в Друпале

При просмотре содержимого того или иного нода в [CMF Drupal](http://drupal.org) можно заметить наличие вкладок «Просмотр», «Изменить» и прочих:

![](https://graker.ru/sites/default/files/styles/max_1300x1300/public/legacy/drupal_local_tasks.png.webp?itok=eq6GX6qe)

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

Делается это через [систему меню](http://drupal.org/node/102338), а точнее — в [`hook_menu`](http://api.drupal.org/api/function/hook_menu/6). Предположим, нам нужно добавить к нодам локал таск tab1. Ноды доступны по внутреннему пути `node/$nid`, значит таб будет доступен по адресу `node/$nid/tab1`:

```
function mymodule_menu() {
  $items = array();
  $items['node/%/tab1'] = array(
    'title' => 'Tab1',
    'page callback' => '_view_tab1_page',
    'page arguments' => array(1),
    'access callback' => '_my_localtask_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
} //function mymodule_menu
```

где `_view_tab1_page` генерирует содержимое таба, а `_my_localtask_access` — управляет доступом к этому содержимому.

Знак % — это так называемый wildcard (он же шаблон, метасимвол, символ подстановки), использующийся для передачи элемента пути в аргумент функции. В данном случае нам нужно передать элемент пути, соответствующий `arg(1)`, в функции генерации страницы и контроля доступа. Предполагается, что элемент пути — это ID просматриваемого нода. Например для пути `node/64/tab1` функция `ag(1)` вернет 64. Однако поскольку путь может быть намеренно изменен пользователем в адресной строке браузера на что угодно, его следовало бы валидировать — проверить, что это число, убедиться, что нод с таким ID существует и т.д.

Для удобства разработчики Друпала предусмотрели [метасимвол с загрузкой](http://drupal.org/node/209056). Запись `%node` в примере ниже позволяет передать в функции вместо `arg(1)` сразу результат работы `node_load(arg(1))`. То есть и валидировать элемент пути, и сразу загрузить нужный нод. Это, кстати, избавляет нас от необходимости дважды вызывать `node_load()` — сначала в функции доступа, а затем в функции генерации страницы.

```
function mymodule_menu() {
  $items = array();</code></pre>
  $items['node/%node/tab1'] = array(
    'title' => 'Tab1',
    'page callback' => '_view_tab1_page',
    'page arguments' => array(1),
    'access callback' => '_my_localtask_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
} //function mymodule_menu
```

Возникает вопрос: а зачем вообще нужна функция доступа? Ведь мы можем просто передать `'access content'` или что-то еще в стандартный коллбэк `user_access()`. Функция доступа `_my_localtask_access` используется для того, чтобы ограничить появление вновь созданных табов за пределами нашего нового типа нода (как известно, если функция доступа возвращает FALSE, элемент меню не генерируется).

```
function _my_localtask_access($node) {
  if ($node->type != 'my_node_type') return FALSE;
  return user_access('access content');
} //function _my_localtask_access
```

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

Вот таким, немного странным, но коротким и аккуратным способом можно сделать табы для нодов.
