Database API Drupal 7, выборка данных и их удаление. db_select, db_query и db_delete. Часть 3

Сложность: 
3

В предыдущей статье мы создали форму для вставки наших данных, еще мы написали функционал для проверки введенных данных, то есть валидация и описали функцию отправки (сабмит) нашей формы, где записываются данные в таблицу, созданною модулем. В этой статье мы создадим таблицу с выводом данных из таблицы созданной модулем. Также сделаем функционал удаление записи из таблицы. Одним словом мы будем знакомится с функциями db_select и db_delete Database API Drupal 7.

Создание страницы с таблицей (theme_table)

В hook_menuдля страницы с таблицей необходимо написать следующие строчки:

$items['my_database'] = array(
  'title' => 'Table with data',
  'page callback' => 'my_database_table_data_page',
  'access arguments' => array('administer site configuration'),
);

Обратите внимание что в этом случаи мы не пишем page arguments, а просто указываем page callback. В page callback указывается функция, которая будет выводить страницу.

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

$header = array(t('ID'), t('Number'), t('Teaser'), t('Text'), t('Actions'));

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

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

$rows = array();
$rows[] = array(1, 2, 'Teaser text', 'Full text', 'Link for action');

Мы создаем простой массив в переменной rows, а во 2 строчке кода описываем строку данных в таблице.

Тонкости темизации в Drupal

Сейчас нам нужно выводить саму таблицу. Как говорилось выше, что мы будем использовать функцию темизации theme_table, но использовать ее напрямую в Друпал не есть правильно, хотя оно и будет работать. Правильней использовать так званную глобальную функцию theme, а первым аргументом передавать название хука темизации. То есть вместо theme_table($variables) необходимо использовать theme(‘table’, $variables), где в переменной variables будут данные, которые мы "скармливаем" для функции темизации. Использовать функцию theme необходимо для того, чтобы использовалась та темизация, которая есть в системе. Сам же стиль вывода можно "перетемить", то есть переписать. Делается это, как правило, в файле template.php который находится в папке с темой.
Вывод будет следующий:

return theme('table', array('header' => $header, 'rows' => $rows));

Сама функция по выводу нашей страницы будет выглядеть так:

function my_database_table_data_page() {
  $header = array(t('ID'), t('Number'), t('Teaser'), t('Text'), t('Actions'));
  $rows = array();
  $rows[] = array(1, 2, 'Teaser text', 'Full text', 'Link for action');
  return theme('table', array('header' => $header, 'rows' => $rows));
}

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

Результат следующий:

theme table drupal 7

Вывод данных из таблицы (db_select)

Для вывода данных из таблицы мы будем использовать функцию db_select. Сам запрос будет выглядеть так:

$query = db_select('my_table', 't')
  ->fields('t', array('id', 'number', 'teaser', 'text'))
  ->execute();

Здесь мы делаем запрос к таблице my_table, даем ей алиас t, дальше с помощью метода fields выбираем необходимые поля и потом выполняем запрос используя метод execute. Запрос сделан, сейчас необходимо вывести данные. Сделаем вывод данных и присвоим сразу в переменную rows.

while ($value = $query->fetchAssoc()) {
  $rows[] = array(
    $value['id'],
    $value['number'],
    $value['teaser'],
    $value['text'],
    'Link for action',
  );
}

При таком выводе данных в функции my_database_table_data_page мы должны увидеть таблицу.
Для примера, перед вами таблица с данными:

drupal 7 table with data db_select fetchAssoc

Вся функция по выводу страницы имеет такой вид:

function my_database_table_data_page() {
  $header = array(t('ID'), t('Number'), t('Teaser'), t('Text'), t('Actions'));
  $rows = array();
  $query = db_select('my_table', 't')
    ->fields('t', array('id', 'number', 'teaser', 'text'))
    ->execute();
  while ($value = $query->fetchAssoc()) {
    $rows[] = array(
      $value['id'],
      $value['number'],
      $value['teaser'],
      $value['text'],
      'Link for action',
    );
  }
  return theme('table', array('header' => $header, 'rows' => $rows));
}

Удаление записей (db_delete)

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

Само удаление будет производиться так:

db_delete(‘my_table’)
  ->condition(‘id’, $id)
  ->execute();

В db_delete мы указываем в какой таблице будем удалять. В методе condition (условие) первым аргументом указываем какое поле будем проверять, вторым аргументом задается значение, а если нет 3 аргумента, тогда он по умолчанию имеет значение ‘=’. То есть мы выбираем запись где поле ‘id’ равно значению переменно id. Конечно же каждая операция должна заканчиваться методом execute (выполнить).

Как говорилось выше, что нам необходимо сделать страницу подтверждение удаление. Сама страница, как обычно, будет определена в hook_menu, и выводить она будет форму.
Код страницы удаления:

  1. $items['my_database/%/delete'] = array(
  2.   'title callback' => 'my_database_delete_page_title',
  3.   'title arguments' => array(1),
  4.   'page callback' => 'drupal_get_form',
  5.   'page arguments' => array('my_database_delete_form', 1),
  6.   'access arguments' => array('administer site configuration'),
  7. );

Посмотрите внимательно на код. Возможно, для вас здесь будет много вещей, а именно это title callback и title arguments. Еще в ключе массива page arguments находится массив, 2 ключом которого есть 1. Разберем детально каждую строчку.

2 строка, title callback. Это не обязательный ключ массива. Даже из самого название ключа массива title callback можно сказать, что здесь находится функция, которая отвечает за вывод заголовка страницы.
3 строчка, title arguments. Здесь определяются аргументы функции, что указана в 2 строчке, то есть функции 'my_database_delete_page_title'. Единица означает что будет передано значение 1 аргумента нашего пути.

Что такое аргументы путей?

Давайте рассмотрим что такое аргументы путей.
К примеру, мы имеем следующею ссылку 'my_database/5/delete'. В этой ссылке находится 3 аргумента, а именно:
‘my_database’ - значение первого аргумента пути.
‘5’ - значение второго аргумента.
‘delete’ - третий аргумент.
В Друпал эти аргументы считаются с нуля, то есть аргумент, который выше мы посчитали вторым, будет первым, потому что ‘my_database’ это нулевой аргумент, ‘5’ первый, а ‘delete’, соответственно третий.
Еще, в Друпал есть функция arg, она выводит аргументы из указанного пути или заданого.
Например, если мы посмотрим, что нам вернет следующий код "arg(NULL, 'my_database/5/delete');", тогда мы увидим такую картину:

Array
(
    [0] => my_database
    [1] => 5
    [2] => delete
)

То есть функция arg разбила нашу строчку по аргументу.
А если мы напишем "arg(1, 'my_database/5/delete');", тогда в выводе мы увидим “5”. Именно “5” есть нашим первым аргументом.

Из этого можно взять то, что в значение ключа массива title arguments, что находится в hook_menu, передается значение именно первого аргумента. Он же, будет у нас подставлятся вместо значка ‘%’.

Аналогичная ситуация находится относительно page arguments и page callback. То есть в page callback указывается функция, которая будет выводить страницу, а в page arguments задаются в массиве аргументы функции (если есть в этом необходимость).

Приступим к заголовку

Мы создали title callback и title arguments для того, что бы динамически изменять заголовок, содержимое функции 'my_database_delete_page_title' (указана в title callback) будет следующее:

  1. function my_database_delete_page_title($id) {
  2.   $placeholders = array(':id' => $id);
  3.   $number = db_query("SELECT `number` FROM {my_table} WHERE `id` = :id", $placeholders)->fetchField();
  4.   return t('Are you sure you want to delete item with number "@num"?', array('@num' => $number));
  5. }

Посмотрите, что в нашей функции передается в аргументы переменная id, именно за это отвечает наш title arguments. В 2-3 строчке мы делаем запрос в БД в нашу таблицу, что бы получить значение клонки number записи с указаным id. Сам же запрос в БД выполняется с помощью db_query. Это еще один способ выполнять запросы, но здесь же, пишется прямой синтаксис SQL. Это перешло из Друпал 6, поскольку там еще не было db_inser, db_select и т.д.. В документации рекомендуют использовать именно db_query для небольших запросов.
В 4 строчке мы выводим сам заголовок. Обязательно необходимо использовать функцию t и брать наше число в “плейсхолдер” (специальная вставка динамических данных), потому что значение цифры у нас может меняться.

Теперь, перейдем к написанию формы подтверждения, выглядеть она будет так:

function my_database_delete_form($form, $form_state) {
  $form = array();
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  $form['cancel'] = array(
    '#markup' => l(t('Cancel'), 'my_database'),
  );
  return $form;
}

Сразу же опишем функцию сабмита формы:

  1. function my_database_delete_form_submit($form, &$form_state) {
  2.   $id = $form_state['build_info']['args'][0];
  3.   $result = db_delete('my_table')
  4.     ->condition('id', $id)
  5.     ->execute();
  6.   $placeholders = array('@id' => $id);
  7.   if ($result) {
  8.     drupal_set_message(t('Record @id successfully removed.', $placeholders));
  9.   }
  10.   else {
  11.     drupal_set_message(t('Record @id is undefined.', $placeholders), 'warning');
  12.   }
  13.   $form_state['redirect'] = 'my_database';
  14. }

Возможно для вас это все выглядит сильно сложно, но если разобраться, тогда проблем не будет.
В 2 строчке мы достаем наше id и присваиваем в переменную с таким же названием. Помните, мы писали в хук меню такую строчку:
'page arguments' => array('my_database_delete_form', 1),
так вот, именно единица отправляет значение с 1 аргумента пути в массив $form_state['build_info']['args'], где мы его и достаем.
В строчках 3-5 мы выполняем операцию удаления и результат этой операции присваиваем в переменную result.
В строке  6 мы строим плейсхолдер, который будет использоваться для подстановки значения в функцию t.
В строках 7-12 выполняется условие, где проверяется, действительно ли удалена у нас запись. Если да, тогда выводим сообщение про успешное удаление, иначе, выводим предупреждающий месседж (во 2 аргументе функции drupal_set_message установлено значение 'warning') про то, что запись неизвестна.
И в 13 строчке мы перенаправляем пользователя на страницу с записями.

Попробуйте самостоятельно проанализировать строчку. Помните, что каждую функцию можно найти на сайте http://api.drupal.org/api/drupal (смотреть для Друпал 7).

И еще, ранее мы создавали на странице 'my_database' столбец ‘actions’. Давайте выведем в этом столбце ссылку на удаление записи.
Сама ссылка будет выглядеть так:
l(t('Delete'), "my_database/{$value['id']}/delete")
Ее необходимо прописать в функции ’my_database_table_data_page’ вместо строки 'Link for action'.

Итог

В этой статье мы проделали большую работу, а именно: создали таблицу с выводом данных и их удалении. Мы работали с функциями db_delete, db_select и db_query Database API Drupal 7. Использовали дополнительные возможности hook_menu, это title callback и title argumets.
В следующей, финальной статье мы будем строить форму для обновление данных

Рассказать друзьям: