Духовность™
Продвинутый новичок
ORM - миф. Когда остановиться?
Написал ORM систему для одной записи таблицы, совместив её с партерном DataMapper. Ну или типа того..
Итого я имею:
всё это работает черезвычайно здорово, красиво, оопшно, классно, рульно и т.д. Особенно это всё удобно использовать тогда, когда нужно делать какие-то простые выборки, например, для админ-части, при работе с записью и списком строк из таблицы.
Но ценность и практичность всего этого убывает, когда нужно делать сложные выборки. Например, вывести список пользователей в колонки, и рядом города/страны/регионы, в которых они проживают. Т.е. сделать JOIN таблиц - user, country, region, city.
При возникновении такой задачи есть несколько основных способов решения:
1. Использовать "полноценный" готовый ORM
Я не хочу использовать стороннюю наработку, т.к. это фактически движок, очень важная вещь в проекте и если что-то пойдет не так, то все накроется медным тазом. Т.е. я за полный контроль над своим кодом. В конце-концов, существующие ORM меня просто пугают своим огромным "клиентским" кодом (объекты Criteria и т.д).
2. Писать свой ORM дальше, до попытки создать систему, которая будет делать что-то из разряда танца с бубном и выдавать нужный результат.
Очень нетривиальная идея. А судя по многим мнениям, полноценного решения все равно не получится, или получится глючный монстр.
3. Совмещение Object-модели и plain SQL в ORM
Это то, что я вижу гораздо чаще в решениях. Суть такова, что ORM/Mapper поддерживает базовый объектный функционал, такой как я привел выше, а все сложные запросы оформляются в виде методов в ORM/Mapper-классах в виде SQL:
В данном случае метод getUsersListWithResidence вернет уже НЕ объекты, а простой массив записей, результат mysql_fetch_assoc().
Собственно вот - задача, которая является, на мой взгляд, одной из основных в программировании. Как её решать, в какую сторону двигаться?
С одной стороны, хочется универсальности.
С другой стороны, смешение plain SQL и ОО-моделей приводит к какой-то неуклюжей архитектуре. Ну как так - один метод объект возвращает, другой массив строк. WTF?
А стремление угнаться за ОО-моделью приводит к появлению сложных решений, один только вид их запросов приводит в ужас.
Как быть?
Написал ORM систему для одной записи таблицы, совместив её с партерном DataMapper. Ну или типа того..
Итого я имею:
PHP:
$user_mapper = new User_Mapper();
$object = $user_mapper->creteFromPost($_POST); // создали из POST-a
$object = $user_mapper->createNew(); // создали пустой объект
$user_mapper->save($object); // сохранили объект
$user_mapper->delete($object); // удалили объект
$user_mapper->findById(5); // нашли объект по ID
// теперь распечатаем
echo 'Привет, '.$object->getName().',
последний раз ты заходил '.
$object->getDaleLastVisit()->format('H:i:s');
$user_mapper->findByParams(5); // нашли объект по массиву $params
// нашли список объектов по массиву $params
$objects_list = $user_mapper->findObjectsList($params);
foreach ($objects_list as $object)
{
echo $object=>getName().'<br />';
}
Но ценность и практичность всего этого убывает, когда нужно делать сложные выборки. Например, вывести список пользователей в колонки, и рядом города/страны/регионы, в которых они проживают. Т.е. сделать JOIN таблиц - user, country, region, city.
При возникновении такой задачи есть несколько основных способов решения:
1. Использовать "полноценный" готовый ORM
Я не хочу использовать стороннюю наработку, т.к. это фактически движок, очень важная вещь в проекте и если что-то пойдет не так, то все накроется медным тазом. Т.е. я за полный контроль над своим кодом. В конце-концов, существующие ORM меня просто пугают своим огромным "клиентским" кодом (объекты Criteria и т.д).
2. Писать свой ORM дальше, до попытки создать систему, которая будет делать что-то из разряда танца с бубном и выдавать нужный результат.
Очень нетривиальная идея. А судя по многим мнениям, полноценного решения все равно не получится, или получится глючный монстр.
3. Совмещение Object-модели и plain SQL в ORM
Это то, что я вижу гораздо чаще в решениях. Суть такова, что ORM/Mapper поддерживает базовый объектный функционал, такой как я привел выше, а все сложные запросы оформляются в виде методов в ORM/Mapper-классах в виде SQL:
PHP:
class my_super_orm {
// методы для работы с объектами
object public function save($object) {...}
object public function findById($object) {...}
object public function delete($object) {...}
// методы оперирующие "сложными" SQL-запросами
// возвратить список пользователей и города/регионы/страны
// в которых они проживают (реальный SQL)
array public function getUsersListWithResidence()
{
$sql = 'SELECT SQL_CALC_FOUND_ROWS
user.id,
user.user_active,
IFNULL(user.user_first_name, user.user_login) AS user_first_name,
user.user_last_name,
user.user_regdate,
user.user_visitdate,
user.user_mail,
user.user_url,
user_icq,
user.user_city,
user.user_region,
user.user_country,
country.country_name,
region.region_name,
city.city_name
FROM
user, country, region, city .... ';
// .....
}
Собственно вот - задача, которая является, на мой взгляд, одной из основных в программировании. Как её решать, в какую сторону двигаться?
С одной стороны, хочется универсальности.
С другой стороны, смешение plain SQL и ОО-моделей приводит к какой-то неуклюжей архитектуре. Ну как так - один метод объект возвращает, другой массив строк. WTF?
А стремление угнаться за ОО-моделью приводит к появлению сложных решений, один только вид их запросов приводит в ужас.
Как быть?