K4:Работа с классом kDBItem
From In-Portal Developers Guide
Revision as of 14:37, 25 December 2008
| ||
---|---|---|
Статьи в этой категории | ||
|
Класс kDBItem
- один из базовых классов. Он предоставляет методы для работы с данными, относящимися к одной записи. Для связи объектов класса kDBItem
с прочими частями системы широко используются события. События происходящие во время выполнения методов класса kDBItem
можно перехватывать и выполнять необходимые действия. И наоборот - в системе имеются события, при наступлении которых выполняются методы класса kDBItem
.
Contents |
Загрузка из базы данных
Для загрузки из базы данных используется метод 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 |
---|---|---|
OnNew | OnPreCreate | setID(0)
|
OnCreate | OnPreSaveCreated | SetFieldsFromHash , Create , IsTempTable , setTempID , setID
|
OnUpdate | OnPreSave | Load , SetFieldsFromHash , Update , Load
|
Эти события как правило инициируются непосредственно с 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'); }