Урок - Schema API - работа со схемами в Drupal 6

Главная » Курсы » Курс Drupal 6, Разработка модулей. » Урок - Schema API - работа со схемами в Drupal 6

Обучающий онлайн курс
Drupal 6, Разработка модулей.

Лицензия: Копирование запрещено.

Обзор урока

В этом уроке мы познакомимся со схемами баз данных. Созданием таблиц при установке модуля. Удалением таблиц при удалении модуля.

Для начал познакомимся с таким понятием как Схема:

Схемой (схемой баз данных) в Drupal 6 называется структурированный массив хранящий в себе информацию о таблицах (поля, ключи, индексы), представляющий одну или более таблиц.

Также в уроке мы познакомимся со следующими программными единицами друпал:

  • хук hook_sсhema() – описывает структуры таблиц БД создаваемы текущем модулем.
  • функция drupal_install_schema($module) – cоздаёт таблицы в БД, определённые в реализации hook_schema() модуля $module.
  • функция drupal_uninstall_schema($module) – удаляет таблицы из БД, определённые в реализации hook_schema() модуля $module.

Структура схем.

Сначала познакомимся со структурой схем:

$schema = array(
	'<table_name1>' => array(
		'description' => 'Описание таблицы',
		'fields' => array(
			'<field1>' => array(
				...
			),
		),
	),
	...
	'<table_name2>' => array(
		...
	),
	...
);

Как мы уже говорили "схема" - это массив. Ключами в массиве схем явлются названия таблиц (<table_name1>, <table_name2>). Элементами в массиве схем являются массивы описывающие одну таблицу название которой указано в ключе.

Для описания таблиц определены следующие ключи:

  • description - cтрока, описывает назначение текущей таблицы. При использовании названий существующих таблиц - названия таблиц необходимо заключать в {} (фигурные скобки):
    $schema = array(
    	'<table_name1>' => array(
    		'description' => 'Дополнительня информация для таблицы {node} для типа материала "кактус".',
    		...
    	),
    	...
    );
  • fields - ассоциативный массив, для описания полей таблицы. Ключем массива fields будет название поля(<field1>), а значеним - ассоциативный массив со следующими ключами:
    $schema = array(
    	'<table_name1>' => array(
    		'fields' => array(
    			'<field1>' => array(
    				...
    			),
    			'<field2>' => array(
    				...
    			),
    			...
    		),
    		...
    	),
    	...
    );
    • description - cтрока, описывающая назначение текущего поля. При использовании названий существующих таблиц - названия таблиц необходимо заключать в {} (фигурные скобки):
      $schema = array(
      	'<table_name1>' => array(
      		'fields' => array(
      			'<field1>' => array(
      				'description' => 'Постфикc для ежика, дополняет поле {node}.title',
      				...
      			),
      			'<field2>' => array(
      				...
      			),
      			...
      		),
      		...
      	),
      	...
      );
    • type - основной тип поля. Может одно из следующих значений:
      • blob - поле для хранения двоичных данных
      • char - фиксированная строка
      • datetime - поле для хранения даты и времени
      • float - поле для вещественного числа
      • int - поле для целого числа
      • numeric - поле для хранения десятичного числа
      • serial - автоинкрементное поле, аналог 'int auto_increment' в MySQL.
      • text - текстовое поле
      • varchar - динамическая строка
    • size - размер данных. Возможные значения
      • tiny
      • small
      • medium
      • normal - значение, по умолчанию.
      • big

      Размер данных size для различных типов поля type отличается. Парные комбинации можно посмотреть в функции db_type_map(). Ниже приведены комбинации для БД MySQL:

      $map = array(
      	'varchar:normal'  => 'VARCHAR',
      	'char:normal'     => 'CHAR',
      
      	'text:tiny'       => 'TINYTEXT',
      	'text:small'      => 'TINYTEXT',
      	'text:medium'     => 'MEDIUMTEXT',
      	'text:big'        => 'LONGTEXT',
      	'text:normal'     => 'TEXT',
      
      	'serial:tiny'     => 'TINYINT',
      	'serial:small'    => 'SMALLINT',
      	'serial:medium'   => 'MEDIUMINT',
      	'serial:big'      => 'BIGINT',
      	'serial:normal'   => 'INT',
      
      	'int:tiny'        => 'TINYINT',
      	'int:small'       => 'SMALLINT',
      	'int:medium'      => 'MEDIUMINT',
      	'int:big'         => 'BIGINT',
      	'int:normal'      => 'INT',
      
      	'float:tiny'      => 'FLOAT',
      	'float:small'     => 'FLOAT',
      	'float:medium'    => 'FLOAT',
      	'float:big'       => 'DOUBLE',
      	'float:normal'    => 'FLOAT',
      
      	'numeric:normal'  => 'DECIMAL',
      
      	'blob:big'        => 'LONGBLOB',
      	'blob:normal'     => 'BLOB',
      
      	'datetime:normal' => 'DATETIME',
      );

      Как видите, для некоторых типов размер size не играет роли, а в некоторых случаях дает аналогичный результат.

    • not null - может быть TRUE или FALSE. Если TRUE - значения NULL в текущем столбце заперещены. Если FALSE (по умолчанию) - значения NULL разрешены.
    • default - значение поля по умолчанию. Для значения default важно различать нулевые значения: '' (пустая строка), '0' (нуль строкой) и 0 (нуль числом). Если для поля типа 'int' значением по умолчанию было задано '0' (нуль строкой), это не сработает, поскольку '0' есть строка, содержащая символ 0, а не целое число. Правльно указывать 0 (нуль числом).
    • length - максимальная длина поля типов 'varchar' или 'text'. Для других типов данных игнорируется.
    • unsigned - может быть TRUE или FALSE. Если TRUE - значения могут быть без знаковыми. Если FALSE (по умолчанию) - значения могут быть знаковыми. Используется с типами int, float, numeric.
    • precision - указывает точность (число значащих цифр) для полей типа numeric. Обязательно для numeric.
    • scale - указывает масштаб (десятичные цифры после запятой) для полей типа numeric. Обязательно для numeric.

  • primary key - массив из одного или более спецификаторов ключевых столбцов, которые формируют первичный ключ. Ключи задаются в двух вариантах:
    • строкой
    • массивом из двух элементов. Первый элемент - имя столбца, второй элемент длина префикса.
    Все поля описанные в первичном ключе должны иметь значение 'not null' => TRUE.
  • unique keys - ассоциативный массив уникальных ключей ('имяКлюча' => описание). Где имяКлюча - название ключа, а описание - список полей формирующие ключ таблицы.
  • indexes - ассоциативный массив индексов('имяКлюча' => описание), где имяКлюча - название ключа, а описание - список полей которые формируют индекс.
  • mysql_suffix - строка, суффикс для базы данных MySQL, указанная строка будет добавлена к запросу создания таблицы. Пример:
    ...			
    'mysql_suffix' => " DEFAULT CHARACTER SET UTF8 ENGINE = INNODB AUTO_INCREMENT=3844 ",
    ...

В качестве примера приведем схему из модуля book:

$schema['book'] = array(
  'description' => 'Stores book outline information. Uniquely connects each node in the outline to a link in {menu_links}',
  'fields' => array(
    'mlid' => array(
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
      'description' => "The book page's {menu_links}.mlid.",
    ),
    'nid' => array(
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
      'description' => "The book page's {node}.nid.",
    ),
    'bid' => array(
      'type' => 'int',
      'unsigned' => TRUE,
      'not null' => TRUE,
      'default' => 0,
      'description' => "The book ID is the {book}.nid of the top-level page.",
    ),
  ),
  'primary key' => array('mlid'),
  'unique keys' => array(
    'nid' => array('nid'),
  ),
  'indexes' => array(
    'bid' => array('bid'),
  ),
);

Хук hook_schema() - регистрация схем в Drupal 6

Для того, чтобы Drupal 6 знал какие дополнительные таблицы необходимы нашему модулю используется хук hook_schema().

Хук hook_schema() должен вернуть схему (описание таблиц) которые определены в нашем модуле. Это позволит легко создавать и удалять таблицы нашего модуля не заботясь и даже не зная о том какая СУБД используется в текущий момент.

hook_sсhema() должен быть создан в файле *.install (В нашем случае ramech.install).

hook_sсhema() должен вернуть ассоциативный массив, описывающий таблицы. Структур мы рассмотрели ранее.

function ramech_schema(){
	$schema = array(
		//	тут описываем схему таблиц
	);
	return $schema;
}

Целиком хук hook_sсhema() может выглядеть так:

function ramech_schema(){
  $schema = array(
    'ramech' => array(
    'ramech' => array(
      'description' => ('Ramech table',
      'fields' => array(
        'nid' => array(
          'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'default' => 0,
          'description' => "Reference to {node}.nid.",
        ),
        'weight' => array(
         'type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'default' => 0,
          'description' => "Weight for {book}.nid.",
        ),
      ),
    ),
  );
  return $schema;
}

drupal_install_schema($module) – cоздание таблиц

Функция drupal_install_schema($module) – cоздаёт таблицы в БД, определённые в реализации hook_schema() модуля $module.

Примечание: Эта функция не пропускает схему таблицы через hook_schema_alter(). Таблицы модуля создаются в точности, как были описаны.
В большинстве случаев drupal_install_schema($module) вызывается в хуке hook_install() - это значит, что drupal_install_schema($module) будет вызываться только при первичной установке модуля, не в повторном включении.
function ramech_install(){
	drupal_install_schema(basename(__FILE__));
}
Если вы отключили модуль (не удалили), изменили схему и включили модуль снова, то таблица не будет изменена. Пока мы не рассмотрели функцию drupal_uninstall_schema($module) (см. ниже), по этому план будет выхода из ситуации такой:
  • На странице модулей отключить модуль.
  • Если модуль остался на вкладке "удаление" - удалить модуль.
  • Важно: если вы изменяете схему (hook_schema()), то проверьте удалены ли таблицы вашего модуля в базе. если не удалены - делаем из бэкап и удаляем.
  • Установить модуль снова.

drupal_uninstall_schema($module) – удаление таблиц

drupal_uninstall_schema($module) – удаление таблиц определенных в схеме.

В основном вызывается в хуке hook_uninstall().

function ramech_uninstall() {
  drupal_uninstall_schema(basename(__FILE__);
}

Итог

В большинстве случаев код по работе со схемами сведется к шаблону:

<?php
function ramech_schema() {
  $schema = array();
  // перечисление схем
  return $schema;
}

function ramech_install() {
  // Создание таблиц при установке модуля
  drupal_install_schema(basename(__FILE__));
}

function ramech_uninstall() {
  // Удаление таблиц при удалении модуля, не при отключении
  drupal_uninstall_schema(basename(__FILE__));
}

Модуль Schema

Обратите внимание на модуль Schema.

  • Модуль Schema отображает информацию о таблицах, которые есть в БД, но не определены в хуке hook_schema() ни у одного из установленных модулей.
  • Модуль Schema может создавать схемы, для каждой таблицы из БД.
  • Модуль Schema позволяет сравнивать структуру БД со структурой таблиц, которые создаются новыми модулями, сообщает обо всех отсутствующих или неправильно объявленных таблицах.