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

312 lines
16 KiB
Markdown
Raw Normal View History

2010-08-21 04:43:03 +00:00
# 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');