2.5.1. Работа с классом kDBItem
Класс kDBItem - один из базовых классов. Он предоставляет методы для работы с данными, относящимися к одной записи.
Для связи объектов класса kDBItem с прочими частями системы широко используются события. События происходящие во
время выполнения методов класса kDBItem можно перехватывать и выполнять
необходимые действия. И наоборот - в системе имеются события, при наступлении которых выполняются методы
класса kDBItem.
Загрузка из базы данных
Для загрузки из базы данных используется метод Load. Метод возвращает значение true в случае успешной загрузки
данных и false в прочих случаях. Если требуется проверить факт успешной загрузки из базы данных у отдельно взятого
объекта, то можно использовать метод isLoaded, который возвращает статус последней загрузки объекта. Условия
загрузки данных задаются параметрами метода. Они могут быть простыми и сложными.
Простое условие загрузки получается если первым параметром передаётся значение одного из полей записи. Обычно это
Integer значение первичного ключа и тогда второй параметр не нужен. Если первым параметром передают значение
другого поля, то вторым параметром должно быть название соответствующего поля.
// получаем ссылку на объект. Третий параметр предотвращает автоматическую загрузку данных в объект
$user =& $this->Application->recallObject('u', null, Array('skip_autoload' => true));
/* @var $user kDBItem */
// загружаем данные объекта с ID = 23
$user->Load(23);
// Тут могут быть всякие действия с объектом
// Загружаем в объект данные пользователя по его адресу электронной почты
$user->Load('erik@intechnic.com', 'Email');
Сложное условие загрузки получается если первым параметром передать массив, содержащий в качестве ключей имена полей а в качестве значений - значения, которые должны быть в соответствующих полях у загруженной записи.
$load_keys = Array(
'FirstName' => 'Erik',
'LastName' => 'Snarski'
);
$user->Load($load_keys);
В итоге для загрузки данных будет использоваться SQL-запрос с условием следующего вида:
WHERE FirstName = 'Erik' AND LastName = 'Snarski'
Изменение данных
Для изменения данных одного поля используются методы SetField и SetDBField. SetDBField записывает в поле
значение параметра $value в точности таким как оно передано. SetField перед тем как записать значение,
проверяет не назначен ли для поля форматер, и если назначен, то
трансформирует значение поля методом Parse форматера.
// например в случае с форматированием даты
$user->SetField('dob', '12/22/1971');
// результат операции будет эквивалентен
$user->SetDBField('dob', 62197200);
Часто бывает удобно поменять данные сразу в нескольких полях. Например, переписать значения полей, которые пришли в
результате submit-а формы. Для этого имеются функции SetFieldsFromHash и SetDBFieldsFromHash. Они принимают в
качестве параметра массив, содержащий имена полей и значения для них. SetFieldsFromHash, как вышеупомянутый
SetField, вызывает метод Parse форматера для трансформации
значений.
$field_values = Array(
'Email' => 'erik@intechnic.com',
'FirstName' => 'Erik',
'LastName' => 'Snarski',
'dob' => '12/22/1971'
);
// обычно подобный массив получают из запроса конструкцией вида
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list ($id, $field_values) = each($items_info);
// и, наконец - запись данных в объект
$user->SetFieldsFromHash($field_values);
Иногда, например при импорте данных, приходится один и тот же объект класса kDBItem использовать многократно с
разными наборами данных. В таких случаях может оказаться полезным метод Clear, выставляющий всем полям значения
по умолчанию и таким образом гарантирующий, что в каждом наборе будут только его собственные данные.
Определение изменившихся полей
Часто бывает полезно при изменении данных объекта также проверить какие именно поля менялись а какие - нет. Например,
если какие-то действия есть смысл производить только при изменениях в определённых полях. Получить значение поля,
которое было до изменения данных, сразу после загрузки данных из базы можно с помощью метода GetOriginalField.
Проверка
Для проверки данных объекта применяется метод Validate. Если в ходе выполнения метода обнаруживается несоответствие
данных предъявляемым к ним требованиям, то в свойство FieldErrors объекта, представляющее собой массив с именами
полей в качестве ключей верхнего уровня, дописываются элементы второго уровня с ключами 'pseudo'. Это коды ошибок,
коротко описывающие сущность проблемы. Проверить есть ли в объекте такие коды можно методом HasErrors.
Увидеть эти коды можно в отладчик, если открыть его после неудачной попытки сохранения записи.
[Name] = Array
(
[pseudo] = required
)
Иногда бывает необходимо не только считывать информацию об ошибках в полях, но и записывать её. Например, при написании
функций проверки данных, специфических для конкретной задачи. Тогда, для обозначения ошибок в поле следует использовать
предоставляемый классом kDBItem метод SetError.
Например, при редактировании данных в форме можно выбрать из списка категорию, к которой относиться объект. Однако, перед сохранением в базу данных хорошо бы убедиться что категория с таким номером действительно существует:
/**
*
* @param kEvent $event
*/
function OnBeforeItemUpdate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$category_id = $object->getDBField('CategoryId');
if (!$category_id) {
// значение не задано - проверка не нужна
return;
}
if ($category_id == $object->GetOriginalField('CategoryId')) {
// значение не изменялось - проверка не нужна
return;
}
$sql = 'SELECT COUNT(*)
FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('c', 'IDField') . ' = ' . $this->Conn->qstr($category_id);
if (!$this->Conn->GetOne($sql)) {
$object->SetError('CategoryId', 'invalid_category', 'la_error_InvalidCategory');
}
}
Сохранение в базу данных
Для сохранения в базу данных используются методы Create и Update. Метод Create предназначен для создания
новой записи. Метод Update - для изменения существующей записи. Оба эти метода по умолчанию, перед тем как
записывать данные в базу, делают проверку методом Validate, и производят запись только в случае если проверка
пройдена успешно. В приведённом ниже примере делается импорт данных, правда, если данные создаваемого пользователя не
пройдут проверку, то запись просто не будет создана.
// считываем данные из внешнего источника данных в массив
$sql = 'SELECT username, password, email
FROM user';
$users = $application->Conn->Query($sql);
// создаём объект класса kDBItem
$user =& $application->recallObject('u.-item', null, Array('skip-autoload' => true));
/* @var $user kDBItem*/
foreach ($users AS $user_data) {
// выставляем значения по умолчанию вызовом метода Clear
$user->Clear();
// выставляем значения полей импортируемой записи
$user->SetDBField('Login', $user_data['username']);
$user->SetDBField('Email', $user_data['email']);
$user->SetDBField('Password', $user_data['password']);
$user->SetDBField('VerifyPassword', $user_data['password']);
// вызываем метод Create для создания записи в нашей системе
$user->Create();
}
Использование событий
Четыре основных метода класса kDBItem, способные непосредственно обращаться к базе данных - это методы:
Create;Load;Update;Delete.
Каждый из них в определённых ситуациях вызывает события, которые можно использовать для связи объекта класса
kDBItem с остальными частями системы. Все эти четыре метода могут в ходе своего выполнения вызывать события
OnBeforeItem**** и OnAfterItem****, где **** - имя метода. Событие OnBeforeItem**** вызывается до
обращения к базе данных. Событие OnAfterItem**** вызывается только после успешного обращения к базе данных.
Методы Create и Update могут вызывать ещё и событие OnAfterItemValidate. Это происходит в случае, если
производилась проверка данных объекта и эта проверка прошла успешно. Событие OnAfterItemValidate вызывается до
того как произойдёт обращение к базе данных. Ниже приведён пример того, как можно использовать событие
OnAfterItemDelete для выполнения дополнительных действий после успешного удаления записи.
function OnAfterItemDelete(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
// несмотря на то что запись в базе данных уже удалена, в памяти хранятся все её данные и
// в зависимости от значения полей удалённой записи можно выполнять разные действия
$topic_id = $object->GetDBField('TopicId');
if (!$topic_id) {
// deleting non-existing post
return ;
}
$post_helper =& $this->Application->recallObject('PostHelper');
/* @var $post_helper PostHelper */
// update posts count in topic
$post_helper->updatePostCount($topic_id, -1);
}
Основные события, использующие этот класс
Основные события, которые используют класс kDBItem находятся в классе kDBEventHandler.
Основные События |
Аналоги, используемые при работе с временными таблицами |
Используемые методы kDBItem |
|---|---|---|
|
|
|
|
|
|
|
|
|
Эти события как правило инициируются непосредственно с web-страницы, то есть, их имена передаются в запросе к серверу.
Событие OnNew происходит при открытии формы ввода данных для создания новой записи.
OnCreate- при отсылке данных на сервер для создания новой записи.OnUpdate- при отсылке данных на сервер для модификации существующей записи.
function OnUpdate(&$event)
{
// Получаем ссылку на объект класса kDBItem.
$object =& $event->getObject( Array('skip_autoload' => true) );
// Получаем данные из запроса.
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
foreach ($items_info as $id => $field_values) {
// Загружаем данные из базы по идентификатору записи
$object->Load($id);
// Вставляем данные из запроса в объект.
$object->SetFieldsFromHash($field_values);
$this->customProcessing($event, 'before');
// Вызываем метод класса kDBItem.
if ( $object->Update($id) ) {
$this->customProcessing($event, 'after');
$event->status=erSUCCESS;
}
else {
$event->status=erFAIL;
$event->redirect=false;
break;
}
}
}
$event->setRedirectParam('opener', 'u');
}
См. также