Номер объекта

Материал из Eludia
Перейти к: навигация, поиск

Номер объекта ($_REQUEST {id}) -- это значение первичного ключа в таблице, соответствующей заданному типу экрана.

Содержание

Общие соображения

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

Существует две разновидности уникальных ключей: натуральные и синтетические. Значения, составляющие натуральный первичный ключ, берутся из окружающей действительности, а синтетический – генерируются в самой базе данных. К примеру, натуральный первичный ключ гражданина РФ – его фамилия, имя, отчество и дата рождения, натуральный ключ юридического лица – код ОГРН. Синтетический первичный ключ и того, и другого – автоинкрементное поле в соответствующей таблице.

Одна и та же сущность может иметь произвольное число осмысленных естественных первичных ключей. Для гражданина помимо ФИО+ДР – это СНИЛС, номер медицинской страховки, серия+номер паспорта или его аналога, а для юридического лица – ИНН+КПП. Заводить много синтетических ключей на одну сущность, очевидно, бессмысленно.

Теперь – внимание. Натуральные первичные ключи НЕ РАБОТАЮТ. Использовать их нельзя. Никогда. Гражданин может поменять фамилию, потерять паспорт, пенсионный фонд редко, но выдаёт дублирующиеся номера. Оператор может набрать с ошибкой ОГРН (да, попав в контрольную сумму: вероятность 1/10 не так уж и мала). Данные и база – это как Вселенная и человек: разум использует стройные и непротиворечивые модели, но ни одна из них не охватывает всей природы именно в силу нестройности и противоречивости последней. Всё, что мы можем – это держаться за ближайший клочок мироздания, по возможности упорядочивая свои сведения о нём и минимизируя уровень естественных помех.

В общем, первичные ключи должны быть синтетическими. Каждая таблица пусть имеет поле-счётчик – это значение и будет единственным однозначным номером каждой записи. По другим полям не следует даже пытаться создавать уникальные индексы – обязательно откуда-нибудь возьмётся дубль, а вы будете отвечать за то, что "программа не работает". С дублями следует разбираться несколько тоньше, но об этом чуть ниже.

Правила именования

Повсеместное использование автоинкрементных индексов – практика довольно стандартная, особой новизны тут нет. Долгоживущие информационные системы, как правило, имеют определённые стандарты для именования полей. Часто поля-счётчики называются примерно так: NxMyTable или MyTableID. В Eludia.pm первичный ключ всегда называется id.

Итак, ссылка на запись в заданной таблице – это значение её поля id. Имя поля, ссылающегося на таблицу, должно образовываться из формы единственного числа имени целевой таблицы приписыванием префикса id_. Например, ссылки на таблицу users должны называться id_user. В этом случае некоторые API-функции (например, sql), автоматически распознают это поле как ссылку на users. Впрочем, после введения сокращённой формы для описания ссылок удобнее всегда указывать имя целевой таблицы: это ничего не стоит и к тому же не возникает вопросов при необходимости завести в одной таблице несколько ссылок на другую.

Другое, несколько устаревшее решение для того же случая: вместо физического имени целевой таблицы использовать один из её логических псевдонимов. Все такие псевдонимы должны быть приведены в разделе aliases описания таблицы. Например, если документ ссылается на автора и исполнителя, записи которых содержатся в таблице users, имеющей псевдонимы authors и executors, то соответствующие ссылки могут называться id_author и id_executor или id_author и id_executor.

Использование в обработке запроса

id – это имя и поля в БД, и одновременно параметра запроса, обозначающего номер записи, отображаемой на данном экране. id – вторая координата в нашей системе. Все экраны приложения делятся на две категории:

  • списки (с пустым значением id);
  • формы (с непустым значением id).

Например, экран с URL /?type=users должен изображать таблицу со списком пользователей системы, а /?type=users&id=15 – карточку пользователя №15. При этом экраны-формы могут содержать и таблицы (как правило, это списки дочерних объектов, например, список имущества, за которое отвечает данный сотрудник), но при непустом $_REQUEST{id} экран обязательно должен изображать некую "корневую" запись.

У справочников в подавляющем большинстве случаев типы экранов совпадают с именами таблиц. Возможны ситуации, когда одной таблице соответствует несколько типов экранов – они изображают записи в разных режимах. Имена типов таких экранов должны образовываться из имени таблицы путём приписывания постфиксов. Например, экран типа organisations может изображать карточку с основными реквизитами организации, а organisations_affiliates – название организации и список аффилированных структур. При этом экрана с типом organisations_affiliates и пустым $_REQUEST{id} может и не быть. В большом приложении форм всегда больше, чем списков. Но – повторимся – для подмножества справочников эти количества практически совпадают.

Полиморфные ссылки

Значение числового поля-ссылки всегда должно быть уникальным номером записи в единственной целевой таблице и ничем другим. Ни в коем случае нельзя использовать одно поле для хранения номеров записей в разных таблицах. Но что делать, если требуется привязывать записи заданной таблицы к объектам произвольного типа? Рассмотрим пример.

Допустим, вы реализуете в своём приложении сквозную систему аннотирования: заводите таблицу notes, в которой собираетесь хранить короткие заметки по поводу чего угодно (сотрудников, организаций и т. п.) Такая организация данных имеет смысл, если требуется просмотр и поиск в едином реестре заметок без разбиения по типам. Однако каждая запись должна помнить родительскую, а она может оказаться в любой таблице БД.

В этом случае удобно хранить упрощённые гиперссылки на объекты. Например, завести поле href строкового типа и писать туда значения вида "id=15&type=docs". Это удобно не только в смысле использования в WEB-интерфейсе.

Возможно, заметки добавляются на экранах нескольких разных типов (например, docs_new и docs_archive), которым соответствует одна и та же таблица (docs). Тогда (если, конечно, вы пишете значения в приведённом формате и построили необходимый индекс) весьма легко эффективно найти все заметки, относящиеся к одному документу, вне зависимости от его статуса:

href LIKE 'id=15&type=docs%'

При необходимости (которая случается нечасто, но всё же) по ссылкам такого вида можно построить вполне полноценный JOIN:

FROM
 docs
 LEFT JOIN notes ON notes.href LIKE CONCAT('id=', docs.id, '&type=docs%')
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Разработчику
Администратору
Инструменты