Пока мы с вами рассмотрели два способа работы с базами данных в Кохане: с помощью SQL-запросов и с помощью Query Builder-а. В этом и последующих уроках мы поговорим о еще одном способе — взаимодействие с базой данных с помощью ORM (Объектно-реляционное отображение). ORM очень любят новички, а вот продвинутые программисты не всегда рекомендуют его использовать. Вообще все это напоминает ситуацию с ООП. Перед тем как перейти к объектно-ориентированному подходу, рекомендуется сначала нормально изучить процедурный подход. Но речь сейчас не об этом. ORM любят не зря — он очень прост и удобен. При использовании SQL-запросов приходится фактически учить еще один язык — SQL (хотя это тоже надо!). Правда проблема даже не в составлении этих запросов. А в том, что сейчас нам понадобилось вытащить все записи из таблицы, потом только одну с определенным id, через какое-то время — запись с определенными условиями, а в конце вообще связать две таблицы через JOIN и получить записи из обеих. Это получается в модели нам нужно под каждый запрос писать свой метод ? И начинаются танцы с бубном. Создается модель CRUD для четырех базовых запросов SQL, создаются условия вроде «если мы передали id, то вытаскиваем запись с этим id, а иначе вытаскиваем все записи» и так далее. Сплошная головная боль и проблемы. Query Builder немножко упрощает все это дело, но не сильно.
А теперь представьте, что таблица — это объект и нужную запись мы можем получить просто написав:
echo $название_таблицы->название поля;
то есть что-то вроде
echo $article->name;
Хотим изменить имя текущей записи на другое, просто пишем
$article->name = 'Работа с сессиями в Kohana';
Вот примерно таким образом ORM и работает. Фактически мы манипулируем данными БД как обычными объектами PHP. То есть нас избавляют от необходимости писать все эти «лишние» методы по вставке, удалению, обновлению и выборке данных.
Что мне больше всего понравилось — организация связей между таблицами. Не нужно прописывать миллион JOIN с условиями ON table1.id = table2.category_id. Достаточно один раз указать в каждой таблице эту связь (имя связанной таблицы и названия ключей для связи) и все, можно получать значения сразу из нескольких таблиц.
Как и модуль database, который мы включали в файле bootstrap.php, ORM тоже является модулем и его тоже нужно раскомментировать для подключения:
'orm' => MODPATH.'orm', // Object Relationship Mapping
Необходимо помнить еще о том, что модуль ORM не может работать без включенного модуля database, так как использует его методы. По этой же причине для модуля ORM не требуется свой конфигурационный файл. И наши Модели теперь будут наследовать не класс Model, как раньше, а класс ORM, то есть выглядеть наша новая Модель будет примерно так:
<?php defined('SYSPATH') or die('No direct script access.'); class Model_Article extends ORM { }
Фактически то, что мы видим — это уже рабочая модель, которая работает с таблицей articles. При этом данная таблица обязательно должна содержать поле первичного ключа.
Вообще при работе с ORM нужно придерживаться нескольких правил:
— Название модели должно быть в единственном числе. Например: Model_Article, Model_Category, Model_User.
— Название таблицы должно быть во множественном числе. Например: articles, users, roles.
Но в английском языке бывают слова, в которых образование множественного числа происходит не по общим правилам: слова в единственном и множественном числе пишуться одинаково (news, clothes, chess), слова-исключения (man-men, foot-feet) и так далее. Даже в нашем случае category станет categories, а не categorys. Чтобы избежать проблем есть возможность указывать название таблицы вручную. Делается это так:
protected $_table_name = 'categories';
- Каждая таблица должна содержать первичный ключ с названием id. Но опять же, если такое название нас не устраивает, мы можем поменять его и указать новое внутри модели:
protected $_primary_key = 'my_id';
- Поля для связи с другими таблицами должны быть в единственном числе и заканчиваться на _id. Например: article_id, category_id, user_id. Я лично такие поля с самого начала изучения SQL так именую, поэтому у меня проблем с привыканием не возникло.
В случае, если для работы Модели нужно использовать не стандартную БД, а какую-то другую, достаточно указать ее название:
protected $_db_group = 'my_db';
В конечном итоге ваша модель может выглядеть вот так:
<?php defined('SYSPATH') or die('No direct script access.'); class Model_Category extends ORM { protected $_table_name = 'categories'; protected $_primary_key = 'cat_id'; protected $_db_group = 'my_db'; }
Если же вы пользуетесь дефолтной БД и правилами именования ORM для таблиц и полей, то все эти свойства можно опустить (что и происходит в 99% случаев).
В следующем уроке мы уже вплотную займемся практикой и будем получать записи из БД, причем вы увидите, что основная работа уже будет вестись внутри контроллера, а не модели.
<< Назад | Вперед >> |
Пожалуйста, зарегистрируйтесь для комментирования.
«…Даже в нашем случае category станет categories, а не categorys…» — тут не совсем так, это было в ko3.1.
У меня в ko3.2 работает как category => categories, country => countries и тд.
Но если, допустим, таблица «news», то модель должна быть «new».
И еще, если явно в ORM указывать имя таблицы через $_table_name, то не работает потом кеширование.
Так я не возражаю, вполне возможно оно и нормально преобразовывает. Насколько я знаю, для этого используется Хелпер Inflector, а он в общем-то нормально делает, да и настроить его можно для таких исключений, потому что new и news — это новый и новости, а это как-то не то :/
Вот с кешированием действительно интересно….Проблемка мда.
Все верно, хелпер Inflector использует uncountable из system\config\inflector.php — так что с news будет все нормально. Нужно по правилам английского делать) Накрайняк добавить чего нет.
Если с прямым указанием таблиц такие проблемы, как тут говорят, то действительно тогда определенно лучше ковырять Inflector
Денис, здраствуйте, очень хотелось бы примеров организации связей нескольких таблиц, например 3х, а как больше связывать уже понятно будет
Добрый день Денис!
Возникла проблема с созданием класса наследника ORM.
Объявляю в папке моделей классы:
class Model_Fun extends Model_BaseORM …
class Model_Category extends Model_BaseORM …
имена таблиц в базе данных соответственно
funs и categories
А контроллере классы моделей создаются без проблем
$categoryModel = Model::factory(‘Category’);
$funModel = Model::factory(‘Fun’);
А для таблицы imagecategories я создал файл imagecategory.php с обхявлением класса
class Model_Imagecategory extends Model_BaseORM …
Проблема состоит в том, что в контроллере при создании класса
$categoryModel = Model::factory(‘Imagecategory’);
возникает ошибка
Class ‘Model_Imagecategory’ not found
Как правильно всё назвать чтобы всё создавалось как надо?
Заранее спасибо
А у меня таблицу не находит. Создаю модель class Model_User extends ORM {
protected $_table_name = ‘sys_users’;
protected $_primary_key = ‘user_id’;
} в файле /application/classes/Model/Model_User.php
Создаю её экземпляр в контроллере $user = ORM::factory(‘User’);
и получаю ошибку Database_Exception [ 1146 ]: Table ‘ecollege.users’ doesn’t exist [ SHOW FULL COLUMNS FROM `users` ]. Хотя я явно указал с какой таблицей нужно работать protected $_table_name = ‘sys_users’; В чем неполадка, Денис?