Pull to refresh

Comments 32

UFO landed and left these words here
Конечно можно, но… тогда Вы лишаете себя механизма placeholder`ов и вынуждены будете самостоятельно беспокоиться об экранировании переменных. А так же, raw-query сложнее расширить динамически (такое часто требуется, например, при написании фильтров или поиска по различным словиям).
ошибаетесь, у вас есть возможность писать так:

$query = «SELECT id FROM table WHERE id = :id»

$this->fetchAll($query, array(
'id' => 1
));
А в чем я ошибаюсь-то? Я же написал 2 условия. В Вашем коде выполняется только первое (про placeholder`ы), а второе (про удобное динамическое расширение) — нет. Так что так конечно писать можно, но для тех, кто не любит/хочет так делать — я и предложил свой вариант ;)
UFO landed and left these words here
Привет из django-world.

model.objects.all().filter(sex__eq=«male»).filter(Q(age__gt=18)|Q(hobby__eq=«sport»)

Если надло расширить запрос, то:
q0 = model.objetcs....blalbalba… # все по запросу из поста
q1= q0.exclude(name__contains=«John») # все из прошлого запроса кроме Джонов

Все эти запросы превратятся в sql при первом обращении к результатам.

Извините за оффтоп. Требуйте расширения ORM у производителя вашего фреймворка.
UFO landed and left these words here
Циклом прибавлять к переменной $select условия where — удобно.
Циклом конкатенировать к строке $select условия where — неудобно.

Такого примера достаточно или нужно кодом?
UFO landed and left these words here
Вот пример более наглядно показывающий приемущества:
$q->getPosts()->where( «status = ?», «ok» )->findAll();
В запрос в любой точке приложения можно добавлять условия, джойны. Так же можно смешивать 2 запроса. Убедительно?
UFO landed and left these words here
Согласен. В плюсы можно так же добавить абстракцию от синтаксиса конкретной RDBMS, автодополнение в IDE.
можно еще попробовать через quoteInto()
$this->select()
     ->where( "sex = ?", "male" )
     ->where( $this->quoteInto("age > ?", 18) . ' or ' . $this->quoteInto("hobby = ?", "sport"));
Можно, но это уже извращение, как мне кажется. Если условий хотя бы три — строчка уже настолько длинная, что код становится очень не удобно читать.
С другой стороны этот код более прозрачный.
Ваш код похож на хак.

В моем коде используются только стандартные методы ZF. Но, как говорится, на вкус и цвет… Поэтому Ваше решение, равно как и моё, имеет такое же право на существование. Может стоит ссылку на Ваш комментарий скинуть в топик, как альтернативное решение — может быть кому-то оно понравится больше?
Давайте разберемся.
Для создания сложного ИЛИ вы добавляете, забираете, конкатинируете, ресетите и вставляете заново.
В то время, как discourage сразу вставляет конкатинируемое условие без лишних (путанных) манипуляций.
То, что это сложное условие нельзя втсавить в Zend_Db_Select так же как и простое — недоработка Zend Framework'a.
ваш код не читабелен и не понятен
код discourage понятен и короче

вердикт — ваш код на свалку (ну или на говнокод запостить), код discourage внести в ман
Говнокод? Нда… Хорошо, пусть будет так.
В общем-то мне абсолютно все равно на многочисленные необоснованные минусы топика и кармы, топик добавило 4 человека в избранное, если им этот метод хотя бы 1 раз пригодится, значит я уже не зря старался. А Вы можете и дальше писать запросы в стиле raw-query и считать все иное говнокодом, дело Ваше.
У Вас была проблема
Вы ее решили
Но решили ее немного не через голову.
так делать нельзя по многим причинам. Самая главная причина — это то что потом этот код нужно будет сопровождать, либо Вам либо кому нибудь другому.
И уж поверьте через полгода Вы и сами вряд ли сходу поймете что там творится.
надо стараться всегда делать код простым и понятным.
ну а насчет говнокода — эт Вы зря обиделись. Все когда то писали/пишут говнокод.
отличительной чертой такого кода является то что он либо не читаем, не логичен, раздут, не оптимален или все сразу — но при этом всегда (внимание!) он работает
да Ваш код работоспособен. Да Вы разобрались с проблемой. За это вам плюс
но за то что вы показали плохой пример неокрепшим умам — за это минус.
Я б на вашем месте отредактировал статью, добавив те три строчки discourage
И кстати где это Вы в моих словах углядели призыв писать запросы в стиле raw-query?
Чувствую что бесполезно продолжать дискуссию. Вам тут подсказали элегантное решение, а Вы вместо того чтобы поблагодарить человека начали доказывать что Вы Д`артаньян
Я его поблагодарил, поставив плюс.

Я давно пишу только на ZF и я считаю такое решение удобным, поэтому его и рекомендовал.
Воспользуясь законами алгебры логики, что мешало написать так?
$this->select()
     ->where( "sex = ?", "male" )
     ->where( "age > ?", 18, "INTEGER" )
     ->orWhere( "hobby = ?", "sport" )
     ->where( "sex = ?", "male" );


Поскольку приоритет у AND'а больше следующий запрос выполнится так, как вам надо
SELECT * FROM `table` WHERE `sex`= "male" AND `age` > 18 OR `hobby` = "sport" AND `sex`= "male");
Ничего, кроме того, что:
а) дублирование условий
б) динамически такое сделать если и можно, то сложно.
Смотрю документацию Zend_Db_Select тут — framework.zend.com/manual/ru/zend.db.select.html, обратите внимание на Пример #19. Аналогичный запрос реализован иначе, наглядно, человекопонятно и универсально. Всё же не понимаю Ваше стремление добавить непрозрачный getPart с последующей обработкой, ресетом и опять же добавлением обратно в селект. Могли бы Вы привести пример бонуса, который получается в результате этих махинаций, той динамики, о которой речь, и которую никак не реализовать без Вашего метода? Если честно, пока видится только код, за который нужно отрывать руки, чтобы сократить время на чтение кода другими разработчиками.
Не аналогичный. Вопрос экранирования, в приведенном примере #19, не решается. В этом можно легко убедится, немного преобразим пример #19:
$maximumPrice = 500;
$prodGrade = 'A';
$prod = 'Apple';

$select = $db->select()
                      ->from('products',
                            array('product_id', 'product_name', 'price'))
                      ->where("product_grade = $prodGrade OR price > $maximumPrice")
                      ->where('product_name = ?', $prod);
echo $select;


На выходе мы получим

SELECT `products`.`product_id`, `products`.`product_name`, `products`.`price` 
FROM `products` 
WHERE (product_grade = A OR price > 500) AND (product_name = 'Apple')


Как можно заметить экранирование здесь не работает.
Ох, Вы копаете гряблями уважаемый. Для решения вопросов экранирования есть специальные методы.
Не знаю, как у вас там в Зенде, но буду сильно удивлен, получив отрицательный ответ:
неужели нельзя расширить класс и дополнить его методами (and_)where_open, (and_)where_close?

P.S.: привет от Kohana.
Согласен с высказавшимися выше, что пример похабный. Читабельность кода сильно страдает.
Справедливости ради надо отметить, что в ZF чрезвычайно дебильно реализован конструктор запросов. В том числе и расширять его неудобно.
Приведенный в статье пример скорее тянет на хак, нежели на образец кодирования. Мне кажется, более правильным было бы написание своего объекта, позволяющего конструировать сборку OR-условий, и подставлять его в where(). Там кода-то с гулькин нос будет, можно даже вот это всё порно из статьи инкапсулировать и сделать код читаемым.
$this->select()
->where( "sex = ?", "male" )
->where( "(age > ?", 18, "INTEGER" )
->orWhere( "hobby = ?)", "sport" );

Sign up to leave a comment.

Articles