This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/kohana/modules/userguide/guide/ru-ru/tutorials.orm.md
2011-05-03 09:49:01 +10:00

312 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ORM {#top}
Kohana 3.0 включает мощный модуль ORM, который использует паттерн Active Record и автоопределение информации о списке полей БД модели.
Модуль ORM включен в дистрибутив Kohana 3.0, но нуждается в подключении перед его использованием. В файле `application/bootstrap.php` отредактируйте вызов [Kohana::modules] и добавьте модуль ORM:
Kohana::modules(array(
...
'orm' => MODPATH.'orm',
...
));
## Настройка {#configuration}
ORM требует небольшую настройку перед использованием. Наследуйте Вашу модуль от ORM:
class Model_User extends ORM
{
...
}
В примере выше, модель будет искать таблицу `users` в БД по умолчанию.
### Свойства модели, отвечающие за конфигурацию
Следующие свойства используются для настройки каждой модели:
Тип | Название | Описание | Значение по умолчанию
----------|---------------------|-------------------------------------|---------------------------------
`string` | _table_name | Используемая таблица БД | `имя модели в единственном числе`
`string` | _db | Название БД | `default`
`string` | _primary_key | Поле - первичный ключ | `id`
`string` | _primary_val | Титульное поле | `name`
`bool` | _table_names_plural | Имя таблицы во множественном числе | `TRUE`
`array` | _sorting | Сортировка (столбец => направление) | `primary key => ASC`
`string` | _foreign_key_suffix | Суффикс внешнего ключа | `_id`
## Использование ORM
### Загрузка записи
Для создания экземпляра модели используйте метод [ORM::factory] или конструктор [ORM::__construct]:
$user = ORM::factory('user');
// или
$user = new Model_User();
Конструктор и фабричный метод также поддерживают значение первичного ключа для загрузки конкретной записи:
// Загружаем пользователя с ID 5
$user = ORM::factory('user', 5);
// Проверяем успешность загрузки объекта пользователя
if ($user->loaded()) { ... }
Опционально, Вы можете передать массив с парами ключ => значение для загрузки данных объекта по совпадающим критериям, указанным в массиве:
// Загрузка пользователя с email joe@example.com
$user = ORM::factory('user', array('email' => 'joe@example.com'));
### Поиск записи
ORM поддерживает большинство методов класса [Database] для полноценного поиска данных модели. В свойстве `_db_methods` перечислен полный список поддерживаемых методов. Записи извлекаются после вызовов [ORM::find] или [ORM::find_all].
// Извлекаем первого активного пользователя по имени Bob
$user = ORM::factory('user')
->where('active', '=', TRUE)
->where('name', '=', 'Bob')
->find();
// Ищем всех активных пользователей по имени Bob
$users = ORM::factory('user')
...
->find_all();
Когда Вы запрашиваете список моделей через [ORM::find_all], перебирать его можно аналогично обычным выборкам из БД:
foreach ($users as $user)
{
...
}
Мощным инструментом ORM является метод [ORM::as_array], который возвращает полученные записи в виде массива. При использовании совместно с [ORM::find_all], будет возвращён массив всех записей. Хороший пример использование этого метода - когда необходимо передать значения для выпадающего списка:
// Отображается выпадающий список пользователей
// (используется id в качестве значения select option)
form::select('user', ORM::factory('user')->find_all()->as_array('id', 'username') ...
### Подсчёт записей
Для получения количества записей для данного запроса, используйте [ORM::count_all].
// Число активных пользователей
$count = ORM::factory('user')->where('active', '=', TRUE)->count_all();
Если требуется подсчитать общее количество пользователей для данного запроса при лимитировании количества возвращаемых записей, используйте метод [ORM::reset] с параметром `FALSE` перед использованием `count_all`:
$user = ORM::factory('user');
// Общее число пользователей (reset FALSE предотвращает объект от очистки перез запросом)
$count = $user->where('active', '=', TRUE)->reset(FALSE)->count_all();
// Получаем только первые 10 результатов
$users = $user->limit(10)->find_all();
### Доступ к свойствам модели
Все свойства модели доступны через "магические" методы `__get` и `__set`.
$user = ORM::factory('user', 5);
// Выводит имя пользователя
echo $user->name;
// Изменяет имя пользователя
$user->name = 'Bob';
Для хранения данных/свойств, которые отсутствуют в таблице модели, надо использовать атрибут `_ignored_columns`.
class Model_User extends ORM
{
...
protected $_ignored_columns = array('field1', 'field2', ...)
...
}
Множественные пары ключ => значение могут быть заданы с использованием метода [ORM::values]:
$user->values(array('username' => 'Joe', 'password' => 'bob'));
### Создаем и сохраняем записи
Метод [ORM::save] используется как для создания новых записей, так и для обновления существующих.
// Создаем запись
$user = ORM::factory('user');
$user->name = 'New user';
$user->save();
// Редактируем запись
$user = ORM::factory('user', 5);
$user->name = 'User 2';
$user->save();
// Проверяем, сохранена ли запись
if ($user->saved()) { ... }
Вы можете обновить множество записей с помощью метода [ORM::save_all]:
$user = ORM::factory('user');
$user->name = 'Bob';
// Все активные пользователи получат имя 'Bob'
$user->where('active', '=', TRUE)->save_all();
#### Использование `Updated` и `Created` для столбцов БД
Свойства `_updated_column` и `_created_column` позволяют производить автоматическое обновление модели при её обновлении и сохранении. Это используется не по-умолчанию. Чтобы использовать эти свойства, следует их указать:
// date_created является столбцом таблицы, в котором хранится дата создания.
// Для сохранения метки времени, используем TRUE
protected $_created_column = array('date_created' => TRUE);
// date_modified является столбцом таблицы, в котором хранится дата изменения.
// В этом случае используется строка, определяющая формат для функции date()
protected $_updated_column = array('date_modified' => 'm/d/Y');
### Удаление записей
Записи удаляются методами [ORM::delete] и [ORM::delete_all]. Эти методы работают аналогично описанному выше сохранению, за исключением того, что [ORM::delete] принимает необязательный параметр `id` для удаляемой записи.
### Отношения
ORM предоставляет мощную поддержку отношений таблиц. Прочитать про отношения можно в [справочнике по Ruby](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html)
#### Belongs-To и Has-Many
Допустим, мы работаем со школой, которая имеет много учеников (has many). Каждый студент приписан к одной школе (принадлежит - belongs to). Необходимо определить отношения моделей следующим образом:
// В модели school
protected $_has_many = array('students' => array());
// В модели student
protected $_belongs_to = array('school' => array());
Получаем информацию о школе студента:
$school = $student->school;
Ищем всех студентов школы:
// Учтите, что после students следует вызвать метод find_all
$students = $school->students->find_all();
// Чтобы сузить результаты поиска:
$students = $school->students->where('active', '=', TRUE)->find_all();
По-умолчанию, ORM будет искать поле `school_id` в таблице модели student. Это можно изменить, используя аттрибут `foreign_key`:
protected $_belongs_to = array('school' => array('foreign_key' => 'schoolID'));
Внешний ключ будет перегружен как в модели student, так и в school.
#### Has-One
Has-One - это частный случай Has-Many, единственным отличаем которого является то, что в отношении участвует только одна запись. В дополнении к приведённому выше примеру школы, каждая школа будет иметь (has-one) только одного директора, который принадлежит (belongs-to) школе.
// Inside the school model
protected $_has_one = array('principal' => array());
Как и для Belongs-To, Вам не нужно использовать метод `find` для получение объекта, ссылающегося на Has-One объект - это будет сделано автоматически.
#### Has-Many "через" (through)
Отношение Has-Many "through" (так же известное как Has-And-Belongs-To-Many) оспользуется в случае если объект связан с несколькими объектами другого типа и наоборот. Например, студент записан на многие занятия и на занятие ходит много студентов. В этом случаеи используется `промежуточная` таблица. Используем для нашего примера промежуточную таблицу и модель - журнал (`enrollment`).
// В модели student
protected $_has_many = array('classes' => array('through' => 'enrollment'));
// В модели class
protected $_has_many = array('students' => array('through' => 'enrollment'));
Таблица enrollment должна содержать 2 внешних ключа: для занятий `class_id` и для студентов `student_id`. Наименование внешних и дальних ключей (`foreign_key` и `far_key`) могут быть переопределены при определении отношений. Например:
// В модели student (внешний ключ ссылается на модель student,
// в то время, как дальний ключ - на class)
protected $_has_many = array(
'classes' => array(
'through' => 'enrollment',
'foreign_key' => 'studentID',
'far_key' => 'classID'
));
// В модели class
protected $_has_many = array(
'students' => array(
'through' => 'enrollment',
'foreign_key' => 'classID',
'far_key' => 'studentID'
));
Определяем в модели enrollment:
// Журнал принадлежит как студенту, так и занятию
protected $_belongs_to = array('student' => array(), 'class' => array());
Для доступа к связанным объектам:
// Для получение занятий студента
$student->classes->find_all();
// Для получения студентов, записанных на занятие
$class->students->find_all();
### Валидация
ORM тесно взимодействует с [Validate] библиотекой, позволяя использовать возможности этого класса в следующих свойствах:
* _rules
* _callbacks
* _filters
* _labels
#### `_rules`
protected $_rules = array
(
'username' => array('not_empty' => array()),
'email' => array('not_empty' => array(), 'email' => array()),
);
`username` будет проверяться на то, что значение этого поля не является пустым. `email` поле будет проверено на соответствие значения валидному email адресу. Ввиду возможности передачи дополнительных опций для правил, значения правил задаются как пустые массивы.
#### `_callbacks`
protected $_callbacks = array
(
'username' => array('username_unique'),
);
Значение поля `username` будет передано методы `username_unique`. Если метод не существует в текущей модели, то будет вызвана глобальная функция. Вот пример описания этого метода:
public function username_unique(Validate $data, $field)
{
// Логика, проверяющая уникальность имени пользователя
...
}
#### `_filters`
protected $_filters = array
(
TRUE => array('trim' => array()),
'username' => array('stripslashes' => array()),
);
`TRUE` Указывает на то, что фильтр `trim` будет применён ко всем полям. Значение поля `username` будет отфильтровано с помощью функции `stripslashes` перед процессом валидации. Ввиду возможности передачи дополнительных опций для фильтров, значения фильтра задаются как пустые массивы.
#### Проверка объекта
Для проверки объекта, используйте [ORM::check]:
// Задание значений объекта и дальнейшая их валидация
if ($user->values($_POST)->check())
{
$user->save();
}
Для доступа к объекту валидации данной модели, можно использовать метод `validate()`:
// Ручное добавление дополнительного фильтра
$user->validate()->filter('username', 'trim');