Query Builder vs конкатенация запроса ручками

На какой стороне ты?

  • QB / ORM / etc

    Голосов: 18 78,3%
  • Пилю все ручками, не обламываюсь.

    Голосов: 5 21,7%
  • ЭОС

    Голосов: 0 0,0%

  • Всего проголосовало
    23

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Возникли прения, суть в том, что сейчас у нас legacy, тонны говна и конкатенация запроса в виде строчек-массивов, что не всегда бывает удобно. Захотелось запилить простой QB от Illuminate (Laravel), с плюшками от Eloquent ORM. Началось швыряние говнами в команде и прочее. А вы как код пишите?

ЗЫ: Плейсхолдеры в наличии
 
Последнее редактирование:

Absinthe

жожо
Добавь плейсхолдеры, что бы Фанат мог за них проголосовать.
В любом случае сложный запрос будет склеен из кусков, часть которых опциональные.

Ответ очевиден: QueryBuilder обязателен, чтобы не опускаться до жуткого говнокода.
Использовать же его на уровне ORM или на уровне DBAL - другой вопрос.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Ну я как бы и выделил их все в одну группу потому. Просто устал в модели на 1600 строчек, пилить [censored] SQL.
 

AmdY

Пью пиво
Команда форума
QB обязателен. Кстати, в той же Doctrine 1 его не было и это основная проблема почему я забил на свой форк.
Вам возможно лучше взять sqlparser и скрестить его с qb, Sad Spirit вроде делал что-то такое для pg, раз уж есть легаси.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
AmdY, да я мечтаю о нормальном QB, доктрина у нас не взлетит, как и 101% остальных ORMок. Потому хочется гибкости, если надо - написал запрос ручками, а если надо - через QB. В том же Laravel, есть Raw, что радует.
 

AmdY

Пью пиво
Команда форума
c0dex, да, в laravel ничё такой, есть ещё отличный пакет, который join-ы во вложенный массив складывает, если не юзать ORM, самый сок, вот только с ходу не нашёл, нужно гуглить.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
keltanas, я когда смотрел на него, меня подубило это:
...->setParameter(1, $password), а когда увидел
PHP:
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('u.username', '?'),
$queryBuilder->expr()->eq('u.email', '?')
)
плюнул, не нравится мне так.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
PHP:
$sum        = ORM::factory('Account')->select(DB::expr('IFNULL(sum(balance), 0) as sum_balance'))
                    ->select(DB::expr('IFNULL(sum(cashout), 0) as sum_cashout'))
                    ->where('user_id', '=', $this->user->id)->where('status_id', '=', 1);
Пссст, посан, не хочешь немного коханы?)
 

keltanas

marty cats
c0dex, это крайний случай ))
Как правило, достаточно:
PHP:
$qb->where('u.username = ?');
if (true) {
    $qb->andWhere('u.email = ?');
}
Параметры можно непосредственно в Connection, PDO или любую другую обертку с плейсхолдерами передавать.
 
Последнее редактирование:

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
keltanas, меня напрягает сама передача параметров в плейсхолдер, то есть в ?.
 

hell0w0rd

Продвинутый новичок
c0dex, а в чем проблема делать именованные плейсхолдеры?
Ну и вообще http://nkt.github.io/flame/ )) У меня квери-билдер строку отдает, так что можно миксовать конкатенацию и квери-билдер) Как раз может руки дойдут додумать некоторые детали)
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
hell0w0rd, да проблемы нет, думал оного просто нет в доктрине. Просмотрел ссылку через строчку, не увидел.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
В общем примерное распределение голосов понятно, всем спасибо.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
ORM/QB, ручками в специальных местах вроде генерации sitemap размером сотни метров - так выгоднее
 

Активист

Активист
Команда форума
ИМХО, SQL Builder'ы как бы они не назывались - зло. Чем плох SQL? Он понятен и логичен, сразу видно что и как селектится. А стоит поменять SQL и сразу видно какие индексы перестроить, как оптимизировать, проще сделать explain.

Кроме того, ни разу не видел возможность создавать связанные объекты через JOIN'ы , типа того:
PHP:
/**
    * (non-PHPdoc)
    * @see app_db_interface::fetch_qualified_array()
    */
    function fetch_qualified_array()
    {
        if (!$this->_result instanceof mysqli_result)
        {
            return null;
        }
      
        $return = array();
      
        if ($row = $this->_result->fetch_row())
        {
          
            $fields = $this->_result->fetch_fields();
          
            foreach ($row as $_key => $_value)
            {
                $return[ $fields[$_key]->table ][ $fields[$_key]->name ] = $_value;
            }
          
            return $return;
        }
      
        return false;
    }
PHP:
public function searchTicketByStopsAndDate($dispatchStation, $arrivalStation, $date)
    {
        $db = new app_db();

        try
        {
            $datetime = new DateTime($date);
        }
        catch(Exception $e)
        {
            return array();
        }
       
        $db->query("
                select
                    *
                from
                    `root_bricks`               
                left join
                    `root_info` on `root_bricks`.`root_id` = `root_info`.`id`
                left join
                    `schedule`  on `root_bricks`.`root_id` = `schedule`.`root_id`
                right join
                    `carriers`  on `carriers`.`id` = `root_bricks`.`carrier_id`
                right join
                    `root_nodes` as `begin_node` on `root_bricks`.`root_id` = `begin_node`.`root_id` && `root_bricks`.`begin_point` = `begin_node`.`begin_point` -- @todo убрать из sql в будущем, разобравшись в коде
                right join
                    `root_nodes` as `end_node` on `root_bricks`.`root_id` = `end_node`.`root_id` && `root_bricks`.`end_point` = `end_node`.`end_point`               
                where
                    `schedule`.`dispatch_date` = '".$datetime->format("Y-m-d")."'
                    and `root_bricks`.`cost` > 0
                    and    `root_bricks`.`begin_point` = '".$db->escape($dispatchStation)."'
                    and    `root_bricks`.`end_point` = '".$db->escape($arrivalStation)."'
                    and `begin_node`.`order` <= `end_node`.`order`
                order by
                    `schedule`.`dispatch_datetime`
            ");
       
       
        $return = array();
       
        while ($row = $db->fetch_qualified_array())
        {
            $result =
            (new app_tickets_search_result())
            ->setDispatchStationId($dispatchStation)
            ->setArrivalStationId($arrivalStation)
            ->setBusRoot((new app_bus_root())->setAttributes($row['root_info']))
            ->setBusRootBrick((new app_bus_root_brick())->setAttributes($row['root_bricks']))
            ->setBusSchedule((new app_bus_schedule())->setAttributes($row['schedule']))
            ->setCarrier((new app_carriers_carrier())->setAttributes($row['carriers']))
            ;
           
            if ($result->getDispatchDatetime(null))
            {
                /* не продаем за три часа до отправки */
                $now = new DateTime("now");
                $now->add(new DateInterval("PT3H"));
               
                if ($result->getDispatchDatetime(null) > $now)
                {
                    $return[] = $result;
                }
            }
        }
       
        return $return;
    }
 
Сверху