Что до конкретного примера, мне лично не нравится, что скрывая реализацию SQL имена таблиц указываются явно. Хотя, наверно, это уже уровень датамапера...
Случалось. Конкретный пример из различия двух популярных субд - мускуля и постгреса. Справедливости ради, мускуль умеет и offset, но мало кто так пишет, хех. А вообще, часто вы переписываете свой код? Зачем вам все эти классы, функции... а? Ну придется мож один проект из десятка поправить - ну ничего, потрудитесь, лучше чем городить все эти ООПы
MiksIr Лол, ну если не хватает воображения сделать реплейс непосредственно в момент вызова запроса, тогда конечно Цитата к месту - ибо поверьте мне, люди не глупее вас и подходили к проблеме комплексно, а не только с точки зрения проектирования таблиц.
Угу, этакий класс db обвешанный регэкспами Да и потом, не в совместимости все дело. Это был так, самый простой пример, что в голову пришел. А посмотрите синтаксис, например, работы с массивами и хешами в постргресе... ну а потом уж скажите - так ли просто "запомнить SQL". К тому же, такой абстрактный класс может помогать и в других вещах. Нам, например, помогает сохранять объекты беря на себя роль фильтрации служебных полей объекта. В общем, много чего можно сделать - надо лишь желание двигаться. У Сергея оно есть, по крайней мере. А уж какая там конкретная реализация конструктора SQL будет - объектная или еще какая не так важно.
MiksIr Да на здоровье, двигайтесь. Просто я уже, наверное, сотый вариант такого подхода вижу, словно их кто-то клонирует, а идея почему-то везде одна и та же - любыми правдами и неправдами крыть исходный синтаксис запроса, создать иллюзию абстрактности, а потом тот же самый запрос и собрать обратно (с учетом конкретного диалекта SQL, ога). Все это уже давным-давно реализовано например в MZZ и LIMB. Поработайте с этими фреймворками и поймете, что вы получили, а чего лишились. А под другим подходом я имел в виду нечто действительно новое и сулящее хоть какую-то свежесть - например, обдумать вариант, при котором у программиста вообще нет никаких запросов к СУБД, нигде. Он просто связывает сущности отношениями и обращается к тем или иным полям, даже не задумываясь, где у него хранятся данные. Вот это был бы "объектный SQL", да.
Это уже следующий уровень абстракции - уровень датамапера. Мы его делали взяв именно лимб как основу. Уровень конструктора SQL он совершенно не исключает. А получив такой конструктор, который принимает в себя, к примеру, массив с данными (а не строчку INSERT ... ) и фильтрует его, мы можем не заботится о том, что бы модели знали как их свойства отражаются в поля конкретной таблицы.
Так и делаю, без всяких ООПов и почих. Проект (если он хорошо спланирован и реализован) переписывать не нужно, поставил и забыл на годы. (исключение когда хомяк "васи пупкина" раскручивается до уровня яндекса и надо полностью переписывать его под HighLoad) это по любому дешевле чем изначально писать хомяки "васи пупкина" под HighLoad вкладывая десятки тысяч мёртвых зелёных президентов, а затем ежемесячно вкладывать столько-же на его поддержку, в надежде что когда нибудь один из них вырастет и станет вторым гуглом, точнее первым, а гугл станет вторым...
Хех, давай посмотрим с точки зрения хайлоада на это? Как ты с этим классом БД ты будешь затачивать SQL как ты сам говорил, что это не является деградацией кода? )) И вообще, почему ты тогда ратуешь за натив-ПХП в шаблонах? Это тоже тот случай. Введение нового синтаксиса для сущности ради самого синтаксиса. Я понимаю желание привести SQL к обьектному виду. Я сам это пытался сделать. Да, т.к. я работаю с 2 СУБД одновременно, некоторые вещи у меня абстрагираваны от SQL - например методы Limit() и Prepare() — но я согласен с Dagdamor (хотя я не часто с ним согласен) — генерацию SQL из обьекта считаю идеей ущербной по сути, особенно в скриптовых языках.
плюсов, кроме как независимость от СУБД, не вижу... а минусы уже перечислили... полностью согласен.. Возможно и нужна некая абстрактная модель для удобства, но не такая жесткая как здесь ИМХО
Затачивание SQL? Ты про что? Конструктор SQL вообще никак не мешает создавать нужные запросы. Про датамапер отдельный разговор - у нас он умеет и джоны строить и объекты/выборки кешировать. Деградации тут не вижу. Я? Я всегда был против нативных шаблонов в виду их отвратительной читаемости. Как реализован конструктор - объектом ли, статикой или функцией - особо роли не играет. Если кому-то нравится объект - ради бога. Вероятно объект даже будет удобнее при наличии чего-то, что само создает SQL запросы (тот же датамапер). А скриптовый язык или нет - тут тоже вообще никакой роли не играет... или уж говорите нет объектам в принципе, присоединяйтесь в Vladson-у и вперед... нада еще обсудить, не ущербна ли идея функций в _скриптовых_ языках =)
У меня есть цель, и есть средства, там где одни оправдывают других я использую их, когда не оправдывают то шлю нафик. А делать ООП-ы только потому что это "круто" и уж тем более придумывать свой SQL для упрощения запросов (но на разработку которого уйдёт уйма времени, и на обучение которому уйдёт ещё больше) когда старый ничем не хуже это не для меня.
Поймите, что подобный код, как правило, скрыт за DAO. И запрос почти целиком генерируется автоматически, со всеми джоинами и т.п. Вам лишь остаётся задать какие-то ограничения на выборку при помощи критерии. Это уже, как сказали, уровень Data Mapper. Бизнес объект полностью отделяется от источника данных. И ему уже всё равно откуда берутся данные. Но даже в этом случае квери билдер очень полезен. Где-то нам надо выбрать 10 объектов, где-то 20, где-то объекты отсортировать в одном порядке, где-то в другом. PHP: <?php $user = new UserMapper(); $ten_users_sorted_by_login = $user->createCriteria()->orderBy(SQLOrder::create('login'))->limit(10)->all();
Sergey89 Даже для такого примера, сверхпримитивного и сверхудобного для демонстрации возможностей объектного подхода, запись получается гораздо длиннее аналогичного SQL-запроса... PHP: <?php $ten_users=db_query("SELECT * FROM users ORDER BY login LIMIT 10"); или же подхода, реализованного в PHPC... PHP: <?php $ten_users=$db->getOrderedLinesRange("users","login",0,10);
А что если мне нужно добавить ещё пару JOIN'ов и заполнить релевантные объекты данными? PHP: <?php $user = $um->findById(10); $user->getDataFromRelateTable(); Ну это тоже в своём роде qwery builder, только с заранее урезанным функционалом.
Sergey89 ...то уже для этого примера существует риск забабахать такую конструкцию в цикле, не зная о ее реализации, и получить кучу излишних запросов.
А я могу сказать DataMapper'у, чтобы он сразу выбрал все нужные объекты. А риск забабахать запрос в цикле есть всегда, даже когда пишешь на сыром SQL.
О чём спор? Абстракция всегда может повлеч за собой недостатки, такие как избыточность кода, падение производительности и т. п. Но она же в свою очередь имеет и достоинства абстракции. Тут надо выбирать, что тебе нужно.
с одной стороны Дагдамор во многом прав, а с другой PHP: <? function SqlSearchByPostsText($q,$category=array(),$page=0){ $sql='';$sqlnumrows=''; $q=Replacer::Escape($q); if(!empty($category)) $category=Replacer::Escape($category); $page=Replacer::Escape($page); $cnf=locator::LoadData('config'); $tsql=" FROM ?p_posts as P WHERE P.posts_text LIKE('%$q%') "; if(is_array($category) && !empty($category)) $tsql.=" AND ".$this->SFormateIN(array("P.posts_cats_id"=>$category)); $sql=" SELECT P.* ".$tsql." ORDER BY {$cnf['page_global_sorter']} LIMIT {$page},{$cnf['search_page_num']} "; $sqlnumrows=" SELECT COUNT(P.posts_id) ".$tsql." "; return array("result"=>$this->query($sql),"numrows"=>$this->resultquery($sqlnumrows)); } ?>
Отойдём от привычных СУБД К примеру есть самописная база данных [которая работает с текстовыми файлами] У неё есть интерфейс: select(), delete() и т.д. Без ОРМ придётся писать парсер SQL-запросов для получения данных.
вот ОРМ, как я его понимаю: возьму самый простой пример. Например, мне в базе, в папке "Организации" надо программно создать новую организацию РАО ЕЭС, при этом, естественно приходится делать сопутствующие вещи: - записать в логах время создания и пользователя от имени которого она создается - еще до этого проверить, а есть ли у пользователя права создавать в этой папке новые объекты? - заполнить незаполненные поля значениями по умолчанию - проверить корректность заполнения полей и в случае некорректности исправить ошибки или выплюнуть исключения ну и еще куча всяких мелочей, которые зависят от типа создаваемого объекта и реализуются в OnCreate() и OnStore() для того чтобы сделать все это при помощи ОРМ нужно написать ровно 4 строчки: PHP: $dep= new Department(); $dep->name= "РАО ЕЭС"; //имя $dep->path= Object::path2(26957); //26957- это айдишник папки "Оргинизации" $dep->store(); //тут заполнятся поля значениями по умолчанию, ссылочные поля проверятся на корректность, проверятся права на создание внутри 26957, объект сохранится и запишется вго первый лог. а сколько тысяч строк мне пришлось бы писать для того же без ОРМ? или вот задачка: возьми папку Организации и скопируй ее в корневую папку. Опять надо проверять права сначала на саму папку, а потом на каждый объект внутри нее, и для всех объектов опять же писать логи. Все это выполнится автоматически если написать PHP: $org= new Object(26957); $org->move(new Object(1)); //1- это айдишник корневой папки. просто же? так что те кто говорит, что ОРМ ничем не помогает, тот по- моему сильно ошибается. мне было проще один раз написать ОРМ, чем каждый раз писать эти эскуэли и тонны проверок. А второе преимущество ОРМ, это как уже говорили относительная независимость от СУБД и от структуры БД. Вот непридуманный случай. Сначала база работала на МуСКЛ. Потом его стало нехватать и я ушел на ПГ. Теперь самое интересное. Все что пришлось переписать- это Object::create(), Object::store(), Object::copy(), Object::move(), Object::delete() и undelete(). Все это методы одного класса и все в одном месте. вот так. Если бы я не пользовался ОРМ, а писал непосредственно СКуЛь, мне пришлось бы перепроверить все места проекта, где работа с базой. Представляете сколько на это ушло бы времени? А так что раньше там стояло create(), что теперь стоит create(), я в одном месте поменял реализацию create() и все заработало. Так что ОРМ рулит
Sergey89 +1 onphp забавная штука, а использование критериев в своих sql-запросах - просто песня Я за разделение Бизнес-объектов и Sql-конструкций, т.к. это обычно совершенно разные задачи.
а с этой объектной эскуэлиной можно делать вот так: PHP: $sql = "select * from table"; $builder= new Builder($sql); //тут чуть по чуть модифицирали его объектно и потом обратно в текст $sql= $builder->asText(); интересует в основном постгрксовский диалект скуэля. Вот как по моему опыту, проще написать запрос ручками без всяких объектных извращений. Это будет даже быстрее. Если только для этого, то тут всякие билдеры только нагружают. А вот если его потом надо параметризировать, то делать это в строковом виде очень не удобно. тут в ход идут фор-ичи, имплоды, ерег_реплейсы и пр.