Pull to refresh

Вложенные запросы при помощи Zend_Db_Select

Reading time 2 min
Views 6K
    Относительно недавно при написании кода очередной модели, передо мной встала задача использования подзапроса (к примеру в join). При этом уже довольно давно я стараюсь как можно меньше писать запросов «в сыром» виде; использую для этого ООП обёртку Zend Framework. Однако, посмотрев в мануале, API, я, к своему удивлению, не нашёл необходимых средств. Но после обращения непосредственно к коду стало ясно, что вложенный запрос можно сделать очень просто!

    Присутствие в коде внутреннего метода _join (файл Zend/Db/Select.php) следующей строки, дало понять, что не всё так безнадёжно:
773.   } else if ($name instanceof Zend_Db_Expr || $name instanceof Zend_Db_Select) {

* This source code was highlighted with Source Code Highlighter.

    Банально исходя из того, что для $name instanceof Zend_Db_Select заложена какая-то своя логика, пробуем следующее:
$firstQuery = $db->select()
 ->from(array('u' => 'user'),
        array())
 ->join(array('s2u' => 'site2user'),
        's2u.userId = u.id',
        array('siteId'))
 ->columns(array('userCount' => 'count(*)'))
 ->group('s2u.siteId');

$secondQuery = $db->select()
 ->from(array('s' => 'site'),
        array('siteId' => 'id',
              'site'  => 'title'))
 ->join(array('n' => $firstQuery),
        'n.siteId = s.id',
        array('userCount'));

echo $secondQuery->assemble();


* This source code was highlighted with Source Code Highlighter.

    А в результате работы скрипта получаем:
SELECT `s`.`id` AS `siteId`, `s`.`title` AS `site`, `n`.`userCount` FROM `site` AS `s`
INNER JOIN (SELECT `su`.`siteId`, count(*) AS `userCount` FROM `user` AS `u`
INNER JOIN `site2user` AS `su` ON s2u.userId = u.id GROUP BY `s2u`.`siteId`) AS `n` ON n.siteId = s.id


* This source code was highlighted with Source Code Highlighter.

    Вуаля! Собрался абсолютно правильный запрос.

    Это очень важная особенность, т.к. развязывает руки при написании более абстрактных моделей. К примеру, создаём несколько методов, которые не просто возвращают какие-то данные, а запросы в виде объектов Zend_Db_Select. Тогда эти запросы можно будет модифицировать, встраивать в другие, т.е. избегать написания одного и того же SQL кода в разных местах, а это уже большой плюс при поддержке и модификации кода.

P.S. Данная фича работает уже достаточно давно и почему её до сих пор не внесли в мануал, PHPDoc, по которым получено API, я, честно говоря, не понимаю совсем.
Tags:
Hubs:
+16
Comments 45
Comments Comments 45

Articles