K4:Работа с классом kDBItem
From In-Portal Developers Guide
| ||
---|---|---|
Статьи в этой категории | ||
|
The kDBItem
class is one of the base classes. It provides methods for working with data. Events are widely used to connect between objects of the kDBItem
and other parts of the system. Events occurring during the execution of methods of the kDBItem
class can be перехватывать - hooked (is this correct?) to execute needed actions. The other way around is also possible - the system has events whose execution triggers execution of methods of the kDBItem
class.
Contents |
Loading from the Database
The method Load
is used to load data from the database. The method returns true
if data was loaded successfully and false
otherwise. If there is a need to check whether a single object was successfully loaded from the database, then the method isLoaded
can be used, which returns the status (true or false
) of loading the last object. Requirements for loading data are defined as the parameters of the method and can be simple or complex.
A simple requirement would be where the first parameter is the value of one of the fields of a record. Usually it's an Integer
value of the primary key, in which case a second parameter isn't needed. If the value of a different field is passed in the first parameter, then the second parameter must be the name of the corresponding field.
// Obtain a reference to the object. The third parameter prevents the automatic load of data to the object $user =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); /* @var $user kDBItem */ // Load the data of the object with ID = 23 $user->Load(23); // Here there may be actions with the object // Load user data to the object by his e-mail address $user->Load('erik@intechnic.com', 'Email');
A complex requirement for loading data from the database can be where the first parameter passes an array containing the field names as keys and, as values, the values that should be in the corresponding fields of the loaded record.
$load_keys = Array( 'FirstName' => 'Erik', 'LastName' => 'Snarski' ); $user->Load($load_keys);
As a result, to load this data, an SQL-query will be used with the following conditions:
WHERE FirstName = 'Erik' AND LastName = 'Snarski'
Changing Data
SetField
and SetDBField
are used to change the value of a field. SetDBField
enters the value of the $value
variable into the field exactly as it's passed. SetField
before entering the record checks whether a formatter is assigned for the field, and if one is assigned, transforms the value of the field using the formatter's Parse method.
// For example, with formatting a date $user->SetField('dob', '12/22/1971'); // The result will be the same as $user->SetDBField('dob', 62197200);
Often, it's convenient to change the data for several fields at once. For example, to overwrite the value of several fields, that were received as a result of a form submission. For that we have the SetFieldsFromHash
and SetDBFieldsFromHash
functions. They accept an array as a parameter, that contains the names of the fields and the values for them. SetFieldsFromHash
, just like the above SetField
, calls the formatter's Parse
method to transform a value.
$field_values = Array( 'Email' => 'erik@intechnic.com', 'FirstName' => 'Erik', 'LastName' => 'Snarski', 'dob' => '12/22/1971' ); // Usually, an array like this is received from a request constructed like this $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); list ($id, $field_values) = each($items_info); // and, finally,to record the values into the object $user->SetFieldsFromHash($field_values);
Sometimes, for example when importing data, we have to reuse the same object of the kDBItem
class with different sets of data. The Clear
method can be useful in such cases, which sets default values for all fields, thus guaranteeing that each data set will contain only its own data.
Discovering Changed Fields
Often, when changing an object's data, it's useful to check which fields were changed and which weren't. For example, if some actions only need to be performed if certain fields were changed. It's possible to get the value of a field before it was changed, right after loading the data from the database, with the help of the GetOriginalField
method.
Проверка - Testing?
Для проверки данных объекта применяется метод Validate
. Если в ходе выполнения метода обнаруживается несоответствие данных предъявляемым к ним требованиям, то в свойство FieldErrors
объекта, представляющее собой массив с именами полей в качестве ключей верхнего уровня, дописываются элементы второго уровня с ключами 'pseudo'
. Это коды ошибок, коротко описывающие сущность проблемы. Проверить есть ли в объекте такие коды можно методом HasErrors
.
The Validate
method is used to test an object's data. If, during the execution of a method, a discrepancy between data and requirements is revealed, then the object's FieldErrors
property represents the array with the names of the fields as key top-level elements appended to second-level elements with the keys 'pseudo'
. These are error codes that summarize the nature of the problem. It's possible to check whether a method has such error codes with the HasErrors
method.
Увидеть эти коды можно в отладчик, если открыть его после неудачной попытки сохранения записи.
[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'); }