ertttert
Books-CMS.clan.su

API-интерфейс схемы

С помощью уровня абстракции баз данных Drupal поддерживает различные СУБД — MySQL, PostreSQL, SQLite и т.д. Каждый модуль, которому для работы нужна таблица базы данных, описывает эту таблицу для Drupal с помощью определения схемы. Затем Drupal транслирует такое определение в синтаксис, понятный для конкретной СУБД.

drupal

Использование файлов .install

Как было сказано в главе 2, при написании модуля, в котором нужно создавать и сохранять одну или несколько таблиц баз данных, инструкции по созданию и обслуживанию табличной структуры заносятся в файл .install, который распространяется вместе с модулем.

Создание таблиц

Во время инсталляции нового модуля Drupal автоматически проверяет, имеется ли в файле .install определение схемы (рис. 5.3). Если имеется, то Drupal создает таблицу (или таблицы) базы данных в этой схеме. Ниже приведен пример общей структуры определения схемы:

$schema['tablename'] = array(
 // Описание таблицы.
 'description' => t('Description of what the table is used for.'),
 // Описание, для чего предназначена таблица.

 'fields' => array(
 // Определение поля.

 'field1' => array(
 'type' => 'int',
 'unsigned' => TRUE,
 'not null' => TRUE,
 'default' => 0,
 'description' => t('Description of what this field is used for.'),
 // Описание, для чего предназначено поле.

 ),

),

// Объявления индексов.
'primary key' => array('field1'),
);

Рассмотрим определение схемы для таблицы книг по Drupal, которая находится по адресу modules/book/book.install:

/**
* Реализация hook_schema().
*/

function book_schema() {

$schema['book'] = array(

 'description' => 'Stores book outline information. Uniquely connects each node
in the outline to a link in {menu_links}',
 // Хранит краткие описания книг. Уникально сочетает каждую ноду
 // в кратких описаниях со ссылкой в {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'),
),

);

return $schema;
}

Это определение схемы описывает таблицу book с тремя полями типа int. В нем также указаны первичный ключ, уникальный индекс (т.е. все значения в данном поле уникальны) и обычный индекс. Обратите внимание, что когда описание поля ссылается на поле из другой таблицы, используются фигурные скобки. Это позволяет модулю схемы (см. следующий раздел) создать удобные гиперссылки на описания таблиц.

Использование модуля схемы

Вот тут вы можете подумать: “Ничего себе! Создание таких больших массивов для описания в Drupal всех моих таблиц — это жуткая рутина!” Не пугайтесь. Просто загрузите модуль схемы из http://drupal.org/project/schema и активируйте его для своего сайта. Выберите пункт меню StructureSchema (Структура→Схема) и перейдите на вкладку Inspect (Просмотр) — это позволит увидеть определение схемы для любой таблицы базы данных. Так что если вы создали таблицу с помощью SQL, вы сможете, воспользовавшись модулем схемы, получить для нее определение схемы, а затем скопировать и вставить его в файл .install.

Совет. Написание схемы с нуля почти никогда не требуется. Вместо этого используйте существующую таблицу (таблицы) и вкладку Inspect модуля схемы, чтобы автоматически построить схему. Можно воспользоваться и другими средствами, такими как модуль мастера таблиц (Table Wizard), чтобы просматривать всю информацию о любой таблице в Drupal с помощью модуля Views.
drupal

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

Отображение типов полей из схемы в базу данных

Тип поля, объявленный в определении схемы, отображается на внутренний тип поля в СУБД. Например, целочисленное поле с объявленным размером tiny становится полем TINYINT в MySQL или полем small int в PostgreSQL. Действительное отображение можно просмотреть, отобразив результаты функции getFieldTypeMap(), или обратившись к табл. 5.1 далее в главе.

Текстовые типы

Текстовые поля содержат текст.

Тип varchar

Поля символов переменной длины — наиболее часто применяемый тип поля для хранения текста длиной до 256 символов. Максимальное количество символов задается в ключе length. Длина поля varchar может быть 0–255 символов в MySQL 5.0.2 и более старых версиях, и 0–65535 в MySQL 5.0.3 и более новых версиях. Длины полей varchar в PostgreSQL могут быть еще больше.

$field['fieldname'] = array(
 'type' => 'varchar', // Обязательно.
 'length' => 255, // Обязательно.
 'not null' => TRUE, // По умолчанию FALSE.
 'default' => 'chocolate', // См. ниже.
 'description' => t('Always state the purpose of your field.'),
 // Всегда описывайте назначение поля.
);

Если ключ default не задан, а ключ not null установлен в FALSE, то в качестве значения по умолчанию принимается NULL.

Тип сhar

Поля типа char являются символьными полями фиксированной длины. Количество символов определяется ключом length. Длины полей char в MySQL могут быть от 0 до 255 символов.

$field['fieldname'] = array(
 'type' => 'char', // Обязательно.
 'length' => 64, // Обязательно.
 'not null' => TRUE, // По умолчанию FALSE.
 'default' => 'strawberry', // См. ниже.
 'description' => t('Always state the purpose of your field.'),
);

Если ключ default не задан, а ключ not null установлен в FALSE, то в качестве значения по умолчанию принимается NULL.

Тип text

Поля типа text используются для текстовых данных, которые могут иметь большой размер. Например, поле body из таблицы node_revisions (где хранится текст тела ноды) — как раз такого типа. Для полей типа text значения по умолчанию не могут использоваться.

$field['fieldname'] = array(
 'type' => 'text', // Обязательно.
 'size' => 'small', // tiny | small | normal | medium | big
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Числовые типы

Числовые типы данных используются для хранения чисел и могут быть integer, serial, float и numeric.

Тип int

Этот тип поля используется для хранения целых чисел, таки как идентификаторы нод. Если ключ unsigned установлен в TRUE, то отрицательные значения не допускаются.

$field['fieldname'] = array(
 'type' => 'int', // Обязательно.
 'unsigned' => TRUE, // По умолчанию FALSE.
 'size' => 'small', // tiny | small | medium | normal | big
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Тип serial

Поле типа serial хранит автоинкрементные числа. Например, при добавлении ноды значение поля nid в таблице node увеличивается на 1. Для этого нужно вставить строку и вызвать функцию db_last_insert_id(). Если строка добавлена в другом потоке между вставкой строки и выборкой последнего идентификатора, то все равно возвращается корректный идентификатор, поскольку он отслеживается для каждого подключения отдельно. Автоинкрементные поля должны быть индексированными; обычно они служат первичными ключами.

$field['fieldname'] = array(
 'type' => 'serial', // Обязательно.
 'unsigned' => TRUE, // По умолчанию FALSE. Серийные числа обычно положительны.
 'size' => 'small', // tiny | small | medium | normal | big
 'not null' => TRUE, // По умолчанию FALSE. Обычно TRUE
 // для автоинкрементных полей.
 'description' => t('Always state the purpose of your field.'),
);

Тип float

Числа с плавающей точкой хранятся в типе данных float. Обычно нет особой разницы между числами размеров tiny, small, medium и normal; размер big означает поле с двойной точностью.

$field['fieldname'] = array(
 'type' => 'float', // Обязательно.
 'unsigned' => TRUE, // По умолчанию FALSE.
 'size' => 'normal', // tiny | small | medium | normal | big
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Тип numeric

Тип numeric позволяет задавать точность и масштаб чисел. Точность — это общее количество значащих цифр в числе, а масштаб — общее количество цифр справа от десятичной точки. Например, у числа 123.45 точность 5 и масштаб 2. Ключ size не используется. На момент написания этих строк поля numeric в схеме ядра Drupal не использовались.

$field['fieldname'] = array(
 'type' => 'numeric', // Обязательно.
 'unsigned' => TRUE, // По умолчанию FALSE.
 'precision' => 5, // Значащие цифры.
 'scale' => 2, // Цифры справа от десятичной точки.
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Дата и время: тип datetime

Этот тип данных не используется в ядре Drupal, вместо него применяются метки времени Unix в целочисленных полях. Формат datetime является составным: он содержит одновременно дату и время.

$field['fieldname'] = array(
 'type' => 'datetime', // Обязательно.
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Двоичный: тип blob

Тип данных больших двоичных объектов (binary large object data — blob) применяется для хранения двоичных данных (например, таблица кэша Drupal используется для хранения кэшированных данных). Двоичные данные могут содержать музыку, изображения или видео. Доступны два размера: normal (нормальный) и big (большой).

$field['fieldname'] = array(
 'type' => 'blob', // Обязательно.
 'size' => 'normal' // normal | big
 'not null' => TRUE, // По умолчанию FALSE.
 'description' => t('Always state the purpose of your field.'),
);

Объявление конкретного типа столбца с помощью mysql_type

Если тип столбца в используемой СУБД в точности известен, то в определении схемы можно установить ключ mysql_type (или pgsql_type). Он переопределяет ключи типа и размера для этой СУБД. Например, в MySQL имеется тип поля TINYBLOB для небольших двоичных объектов. Чтобы указать, что среда Drupal должна использовать TINYBLOB при работе с MySQL, но вернуться к обычному типу BLOB в случае другой СУБД, поле понадобится определить следующим образом:

$field['fieldname'] = array(
 'mysql_type' => 'TINYBLOB', // Для использования с MySQL.
 'type' => 'blob', // Для других СУБД.
 'size' => 'normal', // Для других СУБД.
 'not null' => TRUE,
 'description' => t('Wee little blobs.')
);

Встроенные типы MySQL и PostgreSQL приведены в табл. 5.1.

Таблица 5.1. Отображение ключей type и size в определениях схемы на типы конкретных СУБД

Определение схемы Встроенный тип поля в СУБД
Тип (type) Размер (size) MySQL PostgreSQL SQLite
varchar normal VARCHAR varchar VARCHAR
char normal CHAR character VARCHAR
text tiny TINYTEXT text TEXT
text small TINYTEXT text TEXT
text medium MEDIUMTEXT text TEXT
text big LONGTEXT text TEXT
text normal TEXT text TEXT
serial tiny TINYINT serial INTEGER
serial small SMALLINT serial INTEGER
serial medium MEDIUMINT serial INTEGER
serial big BIGINT bigserial INTEGER
serial normal INT serial INTEGER
int tiny TINYINT smallint INTEGER
int small SMALLINT smallint INTEGER
int medium MEDIUMINT int INTEGER
int big BIGINT bigint INTEGER
int normal INT int INTEGER
float tiny FLOAT real FLOAT
float small FLOAT real FLOAT
float medium FLOAT real FLOAT
float big DOUBLE double precision FLOAT
float normal FLOAT real FLOAT
numeric normal DECIMAL numeric NUMERIC
blob big LONGBLOB bytea BLOB
blob normal BLOB bytea BLOB
datetime normal DATETIME timestamp TIMESTAMP

Обслуживание таблиц

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

  1. Измените реализацию hook_schema() в файле .install, чтобы у новых пользователей, которые будут инсталлировать модуль, устанавливалась новая схема. Определение схемы в файле .install всегда будет самой свежей схемой для таблиц и полей модуля.
  2. Предоставьте существующим пользователям путь обновления, написав для этого функцию обновления. Функции обновления должны иметь последовательные имена, начиная с номера версии Drupal. Например, первая функция обновления для Drupal 7 должна называться modulename_update_7000(), а вторая — modulename_update_7001(). Ниже приведен пример из файла modules/comment/comment.install, где таблица, используемая для хранения комментариев, переименована с comments в comment:
    /**
    * Переименование таблицы {comments} в {comment}.
    */
    function comment_update_7002() {
     db_rename_table('comments', 'comment');
    }
    
  3. Эта функция будет выполняться, когда пользователь запустит сценарий http://example.com/update.php после обновления модуля.
Внимание! Поскольку определение схемы в реализации hook_schema() изменяется при каждом добавлении таблицы, поля или индекса, функции обновления не должны использовать это определение схемы. Реализацию hook_schema() следует считать как находящуюся в настоящем, а функции обновления — в прошлом. См. http://drupal.org/node/150220.

Полный список функций для работы со схемами приведен на странице http://api.drupal.org/api/group/schemaapi/7.

Совет. Среда Drupal следит за тем, какую версию схемы использует модуль в данный момент. Эта информация находится в таблице system. После выполнения обновления, приведенного в данном разделе, в строке для модуля комментария будет содержаться значение schema_ version, равное 7002. Чтобы Drupal отбросила это значение, используйте параметр Reinstall Modules в модуле Devel или удалите строку модуля из таблицы system.

Удаление таблиц при деинсталляции

При отключении модуля все данные, сохраненные этим модулем в базе данных, остаются без изменений, на случай, если администратор передумает и снова активирует модуль. На странице Modules (Модули) имеется вкладка Uninstall (Деинсталляция), которая автоматически удаляет данные из базы. Может понадобиться удалить все переменные, определенные в то же время. Вот пример для модуля аннотирования, который был написан в главе 2:

/**
* Реализация hook_uninstall().
*/
function annotate_uninstall() {
 // Очистка записи в таблице переменных.
 variable_del('annotate_nodetypes');
}

Изменения существующих схем с помощью hook_schema_alter()

Обычно модули сами создают и используют свои таблицы. Но что если модулю надо изменить существующую таблицу? Допустим, модулю абсолютно необходимо добавить столбец в таблицу node. Конечно, проще всего взять базу данных и добавить нужный столбец. Но тогда перестанут быть актуальными определения схемы Drupal, которые должны соответствовать реальной таблице базы данных. Существует лучший способ: hook_schema_alter(). Предположим, что имеется модуль, который каким-нибудь образом помечает ноды, и по соображениям производительности нужно обязательно использовать существующую таблицу node, а не собственную таблицу, соединенную с идентификаторами нод. Модуль должен сделать две вещи: изменить таблицу node при инсталляции модуля и изменить схему, чтобы она соответствовала структуре базы данных. Первый пункт выполняется с помощью функции hook_install(), а второй — с помощью hook_schema_ alter(). Если модуль называется markednode.module, то файл markednode.install будет содержать следующие инструкции:

/**
* Реализация hook_install().
*/
function markednode_install() {
$field = array(
 'type' => 'int',
 'unsigned' => TRUE,
 'not null' => TRUE,
 'default' => 0,
 'initial' => 0, // Задает начальное значение для существовавших ранее нод.
 'description' => t('Whether the node has been marked by the markednode module.'),
 // Помечена ли нода модулем markednode
);

// Создание обычного индекса 'marked' по полю 'marked'.
$keys['indexes'] = array(
 'marked' => array('marked')
);
db_add_field('node', 'marked', $field, $keys);
}

/**
* Реализация hook_schema_alter(). Содержимое $schema изменяется по ссылке.
*
* @param $schema
* Схема для всей системы, собранная drupal_get_schema().
*/

function markednode_schema_alter(&$schema) {
 // Добавление поля в существующую схему.
 $schema['node']['fields']['marked'] = array(
 'type' => 'int',
 'unsigned' => TRUE,
 'not null' => TRUE,
 'default' => 0,
 'description' => t('Whether the node has been marked by the markednode module.'),
 // Помечена ли нода модулем markednode
);
}
Всего комментариев: 0
Имя *:
Email *:
Код *:


Бесплатный конструктор сайтов - uCoz