9.4. Zend_Db_Select

9.4.1. Обзор

Объект Zend_Db_Select представляет SQL-оператор SELECT. Класс имеет методы для добавления отдельных частей запроса. Вы можете определять некоторые части запроса, используя методы PHP и структуры данных, и класс формирует корректный синтаксис SQL. После того, как построен запрос, можно выполнять его так же, как если бы он был написан в виде строки.

В число достоинств Zend_Db_Select входит:

  • Объектно-ориентированные методы для построения SQL-запросов по частям;

  • Не зависящая от типа БД абстакция некоторых частей SQL-запроса;

  • Автоматическое заключение в кавычки идентификаторов метаданных в большинстве случаев для поддержки идентификаторов, содержащих зарезервированные SQL слова и спецсимволы;

  • Заключение в кавычки идентификаторов и значений для снижения угрозы атак с использованием SQL-инъекций.

9.4.2. Создание объекта Select

Вы можете создавать экземпляр объекта Zend_Db_Select, используя метод select() объекта Zend_Db_Adapter_Abstract.

Пример 9.10. Пример использования метода select() адаптера БД

<?php

$db = Zend_Db::factory( ...опции... );
$select = $db->select();

?>

Другой способ состоит в создании объекта Zend_Db_Select через конструктор, при этом в качестве аргумента указывается адаптер БД.

Пример 9.11. Пример создания нового объекта Select

<?php

$db = Zend_Db::factory( ...опции... );
$select = new Zend_Db_Select($db);

?>

9.4.3. Построение запросов Select

При построении запроса вы можете добавлять по одному его предложения. Предложение - это часть SQL-оператора, не представляющая собой законченный оператор; например, предложение WHERE. Для каждого предложения есть отдельный метод Zend_Db_Select.

Пример 9.12. Пример использования методов для добавления предложений

<?php

// Создание объекта Zend_Db_Select
$select = $db->select();

// Добавление предложения FROM
$select->from( ...определение таблицы и столбцов... )

// Добавление предложения WHERE
$select->where( ...определение критериев поиска... )

// Добавление предложения ORDER BY
$select->order( ...определение критериев сортировки... );

?>

Вы также можете использовать большинство методов объекта Zend_Db_Select в так называемом fluent interface. Fluent interface означает, что каждый метод возвращает ссылку на тот объект, в котором он был вызван, поэтому вы можете вызывать другой метод непосредственно за ним.

Пример 9.13. Пример использования fluent interface

<?php

$select = $db->select()
    ->from( ...определение таблицы и столбцов... )
    ->where( ...определение критериев поиска... )
    ->order( ...определение критериев сортировки... );

?>

Этот пример демонстрирует применение fluent interface, но во всех случаях вы можете использовать стандартный подход. Часто необходимо использовать стандартный подход - например, когда нужно выполнить некоторую логику до добавления предложения в запрос.

9.4.3.1. Добавление предложения FROM

Указывайте таблицу для запроса, используя метод from(). Вы можете задавать имя таблицы в виде обычной строки, Zend_Db_Select добавит идентификатор, заключив в кавычки имя таблицы, поэтому вы можете использовать спецсимволы.

Пример 9.14. Пример использования метода from()

<?php

// Строит запрос:
//   SELECT *
//   FROM "products" 

$select = $db->select()
    ->from( 'products' );

?>

Вы можете также задавать корреляционное (называемое также "псевдонимом") имя таблицы. В этом случае вместо простой строки используйте ассоциативный массив корреляционных имен и действительных имен таблиц. В других предложениях SQL-запроса используйте это корреляционное имя. Если в вашем запросе объединяется более одной таблицы, то Zend_Db_Select генерирует уникальные корреляционные имена, основанные на именах таблиц, для всех таблиц, для которых не были заданы корреляционные имена.

Пример 9.15. Пример задания корреляционного имени таблицы

<?php

// Строит запрос:
//   SELECT p.*
//   FROM "products" AS p

$select = $db->select()
    ->from( array('p' => 'products') );

?>

Некоторые СУРБД поддерживают спецификатор схемы для таблицы. Вы можете задавать имя таблицы в виде "имяСхемы.имяТаблицы". Zend_Db_Select заключит в кавычки все части по отдельности.

Пример 9.16. Пример задания имени схемы

<?php

// Строит запрос:
//   SELECT *
//   FROM "myschema"."products"

$select = $db->select()
    ->from( 'myschema.products' );

?>

9.4.3.2. Добавление колонок

Во втором аргументе метода from() вы можете задавать столбцы для выборки из соответствующей таблицы. Если вы не укажете столбцы для выборки, то по умолчанию будет подставлен метасимвол "*", означающий "все столбцы".

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

Вы можете указать имя столбца как "корреляционноеИмя.имяСтолбца". Zend_Db_Select заключит в кавычки все части по отдельности. Если вы не укажете корреляционное имя для столбца, то используется корреляционное имя таблицы, указанной в текущем вызове метода from().

Пример 9.17. Пример определения столбцов

<?php

// Строит запрос:
//   SELECT p."product_id", p."product_name"
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'product_name'));

// Строит тот же запрос с указанием корреляционных имен:
//   SELECT p."product_id", p."product_name"
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('p.product_id', 'p.product_name'));

// Строит тот же запрос с псевдонимом для одного столбца:
//   SELECT p."product_id" AS prodno, p."product_name"
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('prodno' => 'product_id', 'product_name'));

?>

9.4.3.3. Добавление столбцов выражений

Столбцы в SQL-запросах иногда представляют собой выражения, а не просто столбцы из таблицы. Выражения не должны иметь корреляционные имена и заключаться в кавычки. Если строка, обозначающая столбец запроса, содержит скобки, то Zend_Db_Select распознает ее как выражение.

Вы можете также явно создавать объект типа Zend_Db_Expr для того, чтобы предотвратить ошибочное распознавание строки как имени столбца. Zend_Db_Expr - минимальный класс, содержащий только строку. Zend_Db_Select распознает объекты типа Zend_Db_Expr и преобразует их обратно в строку, но без таких действий, как заключение в кавычки и добавление корелляционных имен.

[Замечание] Замечание

Использование Zend_Db_Expr не обязательно, если ваше выражение содержит скобки. Zend_Db_Select распознает выражение по скобкам и оперирует строкой как выражением, пропуская такие действия, как заключение в кавычки и добавление корреляционных имен.

Пример 9.18. Пример указания столбцов, содержащих выражения

<?php

// Строит запрос:
//   SELECT p."product_id", LOWER(product_name)
//   FROM "products" AS p
// Выражение со скобками неявно преобразуется в Zend_Db_Expr.

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'LOWER(product_name)'));

// Строит запрос:
//   SELECT p."product_id", (p.cost * 1.08) AS cost_plus_tax
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'cost_plus_tax' => '(p.cost * 1.08)'));

// Построение того же запроса с явным использованием Zend_Db_Expr:
//   SELECT p."product_id", p.cost * 1.08 AS cost_plus_tax
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'cost_plus_tax' => new Zend_Db_Expr('p.cost * 1.08')));

?>

В примерах выше Zend_Db_Select не модифицирует строку для добавления корреляционных имен или заключения идентификаторов в кавычки. Если эти изменения необходимы для исключения неоднозначности, то вы должны произвести их в строке вручную.

Если имена столбцов являются ключевыми словами SQL или содержат спецсимволы, то следует использовать метод адаптера quoteIdentifier() и включать результат в строку. Метод quoteIdentifier() использует заключение в кавычки для ограничения идентификатора, тем самым обозначается, что это идентификатор таблицы или столбца, а не другая часть синтаксиса SQL.

Ваш код будет более независимым от типа БД, если вы будете использовать метод quoteIdentifier() вместо непосредственного добавления кавычек в строке, поскольку некоторые БД используют нестандартные символы для заключения идентификаторов в кавычки. Метод quoteIdentifier() использует соответствующие символы кавычек, основываясь на типе адаптера. quoteIdentifier() также экранирует символы кавычек в самом идентификаторе.

Пример 9.19. Пример заключения в кавычки столбцов в выражении

<?php

// Строится следующий запрос, при этом имя столбца "from" в выражении
// заключается в кавычки:
//   SELECT p."from" + 10 AS origin
//   FROM "products" AS p

$select = $db->select()
    ->from(array('p' => 'products'),
        array('origin' => '(p.' . $db->quoteIdentifier('from') . ' + 10)'));

?>

9.4.3.4. Добавление в запрос другой таблицы через JOIN

Многие полезные запросы используют JOIN для объединения строк из разных таблиц. Вы можете добавлять таблицы в запрос, используя метод join() объекта Zend_Db_Select. Использование этого метода похоже на использование from() за тем исключением, что в большинстве случаев вам нужно будет также указать условие объединения.

Пример 9.20. Пример использования метода join()

<?php

// Строит запрос:
//   SELECT p."product_id", p."product_name", l.*
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'product_name'))
    ->join(array('l' => 'line_items'),
        'p.product_id = l.product_id');

?>

Второй аргумент метода join() является строкой, содержащей условие объединения. Это выражение объявляет условие, при выполнении которого строки в одной таблице объединяются со сроками в другой таблице. Вы можете использовать корреляционные имена в этом выражении.

[Замечание] Замечание

К выражению, указанному вами как условие объединения, не применяется автоматическое заключение в кавычки. Если нужно заключить в кавычки имена столбцов, то используйте quoteIdentifier() при формировании строки условия объединения.

Третий аргумент метода join() - массив имен столбцов, как и в методе from(). По умолчанию используется "*" вместо столбцов, поддерживаются корреляционные имена, выражения и Zend_Db_Expr - так же, как и в случае массива столбцов для метода from().

Если из таблицы не нужно выбирать столбцы, то используйте пустой массив вместо перечисления столбцов. Это работает и для метода from(), но обычно требуется извлечь часть столбцов из основной таблицы в запросе, при этом могут не требоваться столбцы из присоединяемой таблицы.

Пример 9.21. Пример извлечения без столбцов

<?php

// Строит запрос:
//   SELECT p."product_id", p."product_name"
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id', 'product_name'))
    ->join(array('l' => 'line_items'),
        'p.product_id = l.product_id',
        array() ); // пустой список столбцов

?>

Обратите внимание на пустой array() в примере выше вместо списка столбцов из присоединяемой таблицы.

SQL имеет несколько типов объединений. Ниже приведен список методов для поддержки различных типов объединений в Zend_Db_Select.

  • INNER JOIN, методы join(table, join, [columns]) и joinInner(table, join, [columns]).

    Возможно, наиболее часто используемый тип объединения. Строки из каждой таблицы сравниваются с использованием условия сравнения. Результат включает в себя только те строки, которые удовлетворяют условию объединения. Результат может быть пустым, если ни одна строка не удовлетворяет этому условию.

    Все СУРБД поддерживают этот тип объединения.

  • LEFT JOIN, метод joinLeft(table, condition, [columns]).

    В результат входят все строки из таблицы слева и все соответствующие строки из таблицы справа. Если нет соответствующих строк из таблицы справа, то соответствующие столбцы в результате заполняются NULL.

    Все СУРБД поддерживают этот тип объединения.

  • RIGHT JOIN, метод joinRight(table, condition, [columns]).

    Правое внешнее объединение дополняет левое внешнее объединение. В результат входят все строки из таблицы справа и все соответствующие строки из таблицы слева. Если нет соответствующих строк из таблицы слева, то соответствующие столбцы в результате заполняются NULL.

    Некоторые СУРБД не поддерживают этот тип объединения, но, как правило, любое правое объединение может быть заменено на левое посредством изменения порядка таблиц на обратный.

  • FULL JOIN, метод joinFull(table, condition, [columns]).

    Полное внешнее объединение является как бы комбинацией левого и правого объединений. Все строки из обоих таблиц входят в результат, при этом объединяются друг с другом в одну строку результата, если соответствуют условию объединения, иначе объединяются с NULL вместо значений столбцов из другой таблицы.

    Некоторые СУРБД не поддерживают этот тип объединения.

  • CROSS JOIN, метод joinCross(table, [columns]).

    Перекрестное объединение является декартовым произведением. Каждая строка в первой таблице объединяется с со всеми строками во второй таблице. Таким образом, количество строк в результате будет равно произведению числа строк в обоих таблицах. Вы можете фильтровать результат, используя условие в предложении WHERE, в этом случае перекрестное объединение подобно старому синтаксису объединений в SQL-89.

    Метод joinCross() не имеет параметров для определения условий объединения. Некоторые СУРБД не поддерживают этот тип объединения.

  • NATURAL JOIN, метод joinNatural(table, [columns]).

    Естетственное объединение сравнивает столбцы, имеющие одинаковые имена в обоих таблицах. Проверка производится на равенство; проверка на неравенство не является естетственным объединением. Этим API поддерживаются только внутренние естетственные объединения, даже если SQL поддерживает внешние естетственные объединения.

    Метод joinNatural() не имеет параметров для определения условий объединения.

9.4.3.5. Добавление предложения WHERE

Вы можете задавать условия для ограничения строк в результате выборки, используя метод where(). Первым аргументом этого метода является SQL-выражение, которое используется в предложении WHERE в данном запросе.

Пример 9.22. Пример использования метода where()

<?php

// Строится запрос:
//   SELECT product_id, product_name, price
//   FROM "products"
//   WHERE price > 100.00

$select = $db->select()
    ->from(
        'products',
        array('product_id', 'product_name', 'price'))
    ->where('price > 100.00');

?>
[Замечание] Замечание

К выражениям для методов where() или orWhere() не применяется автоматическое заключение в кавычки. Если необходимо, чтобы имена столбцов были заключены в кавычки, то используйте метод quoteIdentifier() при формировании строки условия.

Второй аргумент метода where() является опциональным. Это значение подставляется в выражение. Zend_Db_Select заключает это значение в кавычки и подставляет вместо знака вопроса ("?") в выражении.

Этот метод принимает только один параметр. Если в выражение подставляется несколько значений, то нужно сформировать строку вручную, вставляя переменные и заключая их в кавычки самостоятельно.

Пример 9.23. Пример параметра в методе where()

<?php

// Строит запрос:
//   SELECT product_id, product_name, price
//   FROM "products"
//   WHERE (price > 100.00)

$minimumPrice = 100;

$select = $db->select()
    ->from(
        'products',
        array('product_id', 'product_name', 'price'))
    ->where('price > ?', $minimumPrice);

?>

Вы можете вызывать метод where() несколько раз на одном и том же объекте Zend_Db_Select. Результрирующий запрос объединяет в себе все термы с добавлением AND между ними.

Пример 9.24. Пример нескольких вызовов метода where()

<?php

// Строит запрос:
//   SELECT product_id, product_name, price
//   FROM "products"
//   WHERE (price > 100.00)
//     AND (price < 500.00)

$minimumPrice = 100;
$maximumPrice = 500;

$select = $db->select()
    ->from('products',
        array('product_id', 'product_name', 'price'))
    ->where('price > ?', $minimumPrice)
    ->where('price < ?', $maximumPrice);

?>

Если вам нужно объединить термы с использованием OR, то используйте метод orWhere(). Этот метод используется так же, как и метод where(), за тем исключением, что определенный в этом вызове терм добавляется вместе с OR вместо AND.

Пример 9.25. Пример использования метода orWhere()

<?php

// Строит запрос:
//   SELECT product_id, product_name, price
//   FROM "products"
//   WHERE (price < 100.00)
//     OR (price > 500.00)

$minimumPrice = 100;
$maximumPrice = 500;

$select = $db->select()
    ->from('products',
        array('product_id', 'product_name', 'price'))
    ->where('price < ?', $minimumPrice)
    ->orWhere('price > ?', $maximumPrice);

?>

Zend_Db_Select автоматически заключает в скобки все выражения, которые вы добавляете через методы where() или orWhere(). Это позволяет быть уверенным в том, что приоритет булевых операторов не вызовет другой результат вместо ожидаемого.

Пример 9.26. Пример заключения булевых выражений в скобки

<?php

// Строит запрос:
//   SELECT product_id, product_name, price
//   FROM "products"
//   WHERE (price < 100.00 OR price > 500.00)
//     AND (product_name = 'Apple')

$minimumPrice = 100;
$maximumPrice = 500;
$prod = 'Apple';

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

?>

В примере выше результаты могут отличаться от тех, что получаются без скобок, потому что AND имеет больший приоритет, чем OR. Zend_Db_Select добавляет скобки, Таким образом, результатом является то, что каждое выражение, добавленное в успешных вызовах where() более связанно, чем AND, объединяющее эти выражения.

9.4.3.6. Добавление предложения GROUP BY

В SQL выражение GROUP BY позволяет ограничить количество строк в результатах запроса до одной стоки на каждое уникальное значение в столбцах, перечисленных в предложении GROUP BY.

В Zend_Db_Select вы можете задавать столбцы, используемые для определения групп строк, через метод group(). Аргументом этого метода является столбец или массив столбцов для подстановки в предложение GROUP BY.

Пример 9.27. Пример использования метода group()

<?php

// Строит запрос:
//   SELECT p."product_id", COUNT(*) AS line_items_per_product
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id
//   GROUP BY p.product_id

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id'))
    ->join(array('l' => 'line_items'),
        'p.product_id = l.product_id',
        array('line_items_per_product' => 'COUNT(*)'))
    ->group('p.product_id');

?>

Как и для массива столбцов в методе from(), вы можете использовать корреляционные имена в именах столбцов, столбцы заключаются в кавычки в качестве идентификаторов, если строка не содержит скобок или является объектом типа Zend_Db_Expr.

9.4.3.7. Добавление предложения HAVING

В SQL предложение HAVING применяет условие ограничения к группам строк. Это подобно тому, как предложение WHERE применяет условие ограничения к строкам. Но эти предложения не являются идентичными, поскольку условия WHERE применяются до группировки, в то время как условия HAVING применяется после группировки.

В Zend_Db_Select вы можете определять условия ограничения групп через метод having(). Его использование аналогично использованию метода where(). Первый аргумент является строкой, содержащей SQL-выражение. Опциональный второй аргумент - значение, которое используется для подстановки вместо метки заполнения в SQL-выражении. Выражения, переданные в нескольких вызовах метода having(), объединяются через булевый оператор AND или через булевый оператор OR, если вы используете метод orHaving().

Пример 9.28. Пример использования метода having()

<?php

// Строит запрос:
//   SELECT p."product_id", COUNT(*) AS line_items_per_product
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id
//   GROUP BY p.product_id
//   HAVING line_items_per_product > 10

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id'))
    ->join(array('l' => 'line_items'),
        'p.product_id = l.product_id',
        array('line_items_per_product' => 'COUNT(*)'))
    ->group('p.product_id')
    ->having('line_items_per_product > 10');

?>
[Замечание] Замечание

К выражениям, переданным через методы having() или orHaving(), не применяется автоматическое заключение в кавычки. Если у вас есть имена столбцов, которые требуется заключить в кавычки, то используйте quoteIdentifier() при формировании строки условия.

9.4.3.8. Добавление предложения ORDER BY

В SQL предложение ORDER BY задает один или более столбцов (или выражения) по которым сортируется результат запроса. Если перечислено несколько столбцов, то вторичные столбцы используются для принятия решения в ситуации "ничьи": если первичные столбцы содержат идентичные значения, то порядок сортировки определяется через вторичные столбцы. По умолчанию сортировка производится от меньших значений к большим. Вы можете также производить для данного столбца сортировку от больших значений к меньшим, указав ключевое слово DESC после этого столбца.

В Zend_Db_Select вы можете использовать метод order() для определения столбца или массива столбцов, по которым производится стортировка. Каждый элемент массива является строкой с именем столбца, опционально строка может содержать ключевое слово ASC или DESC после имени столбца и отделенное от него пробелом.

Как и в случае методов from() и group(), имена столбцов заключаются в кавычки в качестве идентификаторов, если они не содержат скобки и не являются объектами Zend_Db_Expr.

Пример 9.29. Пример использования метода order()

<?php

// Строит запрос:
//   SELECT p."product_id", COUNT(*) AS line_items_per_product
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id
//   GROUP BY p.product_id
//   ORDER BY "line_items_per_product" DESC, "product_id"

$select = $db->select()
    ->from(array('p' => 'products'),
        array('product_id'))
    ->join(array('l' => 'line_items'),
        'p.product_id = l.product_id',
        array('line_items_per_product' => 'COUNT(*)'))
    ->group('p.product_id')
    ->order(array('line_items_per_product DESC', 'product_id'));

?>

9.4.3.9. Добавление предложения LIMIT

Некоторые СУРБД расширяют язык SQL предложением, известным как LIMIT. Это предложение ограничивает количество строк в результате запроса до заданного вами количества. Вы можете также задать количество пропускаемых до начала вывода строк. Эта возможность облегчает выборку подмножества строк результата - например, для постраничного вывода результатов запроса.

В Zend_Db_Select вы можете использовать метод limit() для задания количества строк в выборке и количества пропускаемых строк. Первым аргументом этого метода является желаемое количество строк в результате запроса. Вторым аргументом - количество пропускаемых строк

Пример 9.30. Пример использования метода limit()

<?php

// Строит запрос:
//   SELECT p."product_id", p."product_name"
//   FROM "products" AS p 
//   LIMIT 10, 20

$select = $db->select()
    ->from(array('p' => 'products'), array('product_id', 'product_name'))
    ->limit(10, 20);

?>
[Замечание] Замечание

Ситаксис LIMIT поддерживается не всеми СУРБД. Некоторые СУРБД используют другой синтаксис для поддержки аналогичной функциональности. Каждый класс Zend_Db_Adapter_Abstract включает в себя метод для генерации SQL, присущего данной СУРБД.

9.4.3.10. Добавление модификатора DISTINCT

Метод distinct() дает возможность добавлять ключевое слово DISTINCT в ваш запрос.

Пример 9.31. Пример использования метода distinct()

<?php

// Строит запрос:
//   SELECT DISTINCT p."product_name"
//   FROM "products" AS p

$select = $db->select()
    ->distinct()
    ->from(array('p' => 'products'), 'product_name');

?>

9.4.3.11. Добавление модификатора FOR UPDATE

Метод forUpdate() дает возможность добавлять модификатор FOR UPDATE в ваш запрос.

Пример 9.32. Пример использования метода forUpdate()

<?php

// Строит запрос:
//   SELECT FOR UPDATE p.*
//   FROM "products" AS p

$select = $db->select()
    ->forUpdate()
    ->from(array('p' => 'products'));

?>

9.4.4. Выполнение запросов Select

Этот раздел объясняет, как выполнять запрос, представленный объектом Zend_Db_Select.

9.4.4.1. Выполнение запросов из адаптера БД

Вы можете выполнять запрос, представленный объектом Zend_Db_Select, посредством передачи его в качестве первого аргумента методу query() объекта Zend_Db_Adapter_Abstract. Используйте объекты Zend_Db_Select вместо строк запроса.

Метод query() возвращает объект Zend_Db_Statement или PDOStatement, в зависимости от типа адаптера.

Пример 9.33. Пример использования метода query() адаптера БД

<?php

$select = $db->select()
  ->from('products');

$stmt = $db->query($select);
$result = $stmt->fetchAll();

?>

9.4.4.2. Выполнение запросов через объект

Вместо метода query() объекта адаптера вы можете использовать метод query() объекта Zend_Db_Select. Оба метода возвращают объект типа Zend_Db_Statement или PDOStatement, в зависимости от типа адаптера.

Пример 9.34. Пример использования метода query() объекта Select

<?php

$select = $db->select()
    ->from('products');

$stmt = $select->query();
$result = $stmt->fetchAll();

?>

9.4.4.3. Преобразование объекта Select в SQL-строку

Если нужно получить доступ к представлению SQL-запроса в виде строки, то используйте метод __toString().

Пример 9.35. Пример использования метода __toString()

<?php

$select = $db->select()
    ->from('products');

$sql = $select->__toString();
echo "$sql\n";

// Выводом будет строка:
//   SELECT * FROM "products"

?>

9.4.5. Другие методы

Этот раздел описывает другие методы класса Zend_Db_Select, которые не были охвачены ранее: getPart() и reset().

9.4.5.1. Получение частей объекта Select

Метод getPart() возвращает представление определенной части вашего запроса. Например, вы можете использовать этот метод для получения строки выражения для предложения WHERE, массива столбцов, перечисленных для получения выборки по ним, значений количества и смещения для предложения LIMIT.

Возвращаемое значение не является строкой, содержащей фрагмент запроса SQL. Возвращаемое значение является внутренним представлением в объекте, обычно это массив, содержащий значения и выражения. Каждая часть запроса имеет различную структуру.

Единственным аргументом метода getPart() является строка, идентифицирующая часть запроса, которую требуется вернуть. Например, строка 'from' соответствует той части запроса, которая хранит информацию о таблицах в предложении FROM, включая присоединяемые таблицы.

Zend_Db_Select определяет константы, которые вы можете использовать для частей SQL-запроса. Вы можете использовать эти константы или литеральные строки.

Таблица 9.1. Константы, используемые методами getPart() и reset()

Константа Строковое значение
Zend_Db_Select::DISTINCT 'distinct'
Zend_Db_Select::FOR_UPDATE 'forupdate'
Zend_Db_Select::COLUMNS 'columns'
Zend_Db_Select::FROM 'from'
Zend_Db_Select::WHERE 'where'
Zend_Db_Select::GROUP 'group'
Zend_Db_Select::HAVING 'having'
Zend_Db_Select::ORDER 'order'
Zend_Db_Select::LIMIT_COUNT 'limitcount'
Zend_Db_Select::LIMIT_OFFSET 'limitoffset'

Пример 9.36. Пример использования метода getPart()

<?php

$select = $db->select()
    ->from('products')
    ->order('product_id');

// Вы можете использовать строковой литерал для указания части запроса
$orderData = $select->getPart( 'order' );

// Можно использовать константу для указания той же части
$orderData = $select->getPart( Zend_Db_Select::ORDER );

// Возвращаемое значение может быть массивом, а не строкой
// Каждая часть имет свою структуру
print_r( $orderData );

?>

9.4.5.2. Сброс частей запроса в объекте Select

Через метод reset() вы можете очистить определенную часть SQL-запроса или все части запроса, если опустить аргумент.

Единственный аргумент метода является опциональным. Вы можете указать часть запроса для очистки, используя те же строки, которые используются для метода getPart(). Та часть запроса, которую вы указали, сбрасывается в состояние по умолчанию.

Если вы опустите этот параметр, то reset() сбрасывает все части запроса в состояние по умолчанию. Это делает объект Zend_Db_Select эквивалентным новому объекту - так же, как если бы вы его только что инстанцировали его.

Пример 9.37. Пример использования метода reset()

<?php

// Строит запрос:
//   SELECT p.*
//   FROM "products" AS p
//   ORDER BY "product_name"

$select = $db->select()
    ->from(array('p' => 'products')
    ->order('product_name');

// Changed requirement, instead order by a different columns:
// Теперь нужна сортировка по другому столбцу:
//   SELECT p.*
//   FROM "products" AS p
//   ORDER BY "product_id"

// Очищаем соответствующую часть, теперь можно переопределить ее
$select->reset( Zend_Db_Select::ORDER );

// Задаем другой столбец
$select->order('product_id');

// Очищаем все части запроса
$select->reset();

?>