<sect1 id="zend.db.statement">

    <title>Zend_Db_Statement</title>

    <para>
        В дополнение к удобным методам, таким, как <code>fetchAll()</code> и
        <code>insert()</code>, документированным в
        <xref linkend="zend.db.adapter" />, вы можете использовать объект
        оператора для того, чтобы восспользоваться
        бOльшим количеством опций запуска запросов и
        получения результатов запроса. Этот раздел описывает, как получить
        экземпляр объекта оператора и как использовать его методы.
    </para>

    <para>
        Zend_Db_Statement основан на объекте PDOStatement в расширении <ulink url="http://www.php.net/pdo">PDO</ulink>.
    </para>

    <sect2 id="zend.db.statement.creating">

        <title>Создание оператора</title>

        <para>
            Обычно объект оператора возвращается методом <code>query()</code>
            класса адаптера БД. Этот метод является основным средством
            подготовки любых операторов SQL. Первым аргументом является строка,
            содержащая оператор SQL. Опциональный второй аргумент - массив
            значений для подстановки вместо меток заполнения в строке SQL.
        </para>

        <example id="zend.db.statement.creating.example1">
            <title>Создание объекта оператора SQL с помощью query()</title>
            <programlisting role="php"><![CDATA[
$stmt = $db->query(
            'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
            array('goofy', 'FIXED')
        );
]]>
            </programlisting>
        </example>

        <para>
            Объект оператора соответствует оператору SQL, который был
            подготовлен и выполнен с заданными значениями для связки. Если
            оператор был запросом SELECT или любым другим типом оператора,
            который возвращает результат, то он уже готов для извлечения
            результатов.
        </para>

        <para>
            Вы можете создать оператор с помощью его конструктора, но это менее
            типичный вариант использования. Не существует метода-фабрики для
            создания этого объекта, поэтому нужно загружать определенный
            класс оператора и вызывать его конструктор. Передавайте объект
            адаптера в качестве первого аргумента и строку, содержащую оператор
            SQL в качестве второго. Теперь оператор подготовлен, но еще не
            выполнен.
        </para>

        <example id="zend.db.statement.creating.example2">
            <title>Using a SQL statement constructor</title>
            <programlisting role="php"><![CDATA[
$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';

$stmt = new Zend_Db_Statement_Mysqli($db, $sql);
]]>
            </programlisting>
        </example>

    </sect2>

    <sect2 id="zend.db.statement.executing">

        <title>Выполнение оператора</title>

        <para>
            Вам нужно выполнять оператор самостоятельно, если создали его объект
            с помощью его конструктора или хотите запустить один и тот же
            оператор несколько раз. Используйте метод <code>execute()</code>
            объекта оператора. Его единственным аргументом является массив
            значений для связки с метками заполнения в операторе.
        </para>

        <para>
            Если вы используете <emphasis>позиционные параметры</emphasis> - те,
            которые помечаются знаками вопроса (<code>?</code>), - то передавайте значения для связки в простом массиве.
        </para>

        <example id="zend.db.statement.executing.example1">
            <title>Выполнение оператора с позиционными параметрами</title>
            <programlisting role="php"><![CDATA[
$sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';

$stmt = new Zend_Db_Statement_Mysqli($db, $sql);

$stmt->execute(array('goofy', 'FIXED'));
]]>
            </programlisting>
        </example>

        <para>
            Если вы используете <emphasis>именованные параметры</emphasis> - те,
            что указываются через строковой идентификатор с двоеточием
            (<code>:</code>) в начале, - то передавайте значения для связки в
            ассоциативном массиве. Ключи этого массива должны соответствовать
            именам параметров.
        </para>

        <example id="zend.db.statement.executing.example2">
            <title>Выполнение оператора с именованными параметрами</title>
            <programlisting role="php"><![CDATA[
$sql = 'SELECT * FROM bugs WHERE ' .
       'reported_by = :reporter AND bug_status = :status';

$stmt = new Zend_Db_Statement_Mysqli($db, $sql);

$stmt->execute(array(':reporter' => 'goofy', ':status' => 'FIXED'));
]]>
            </programlisting>
        </example>

        <para>
            Операторы PDO поддерживают как позиционные, так именованные
            параметры по отдельности, но не вместе в одном операторе SQL.
            Некоторые классы Zend_Db_Statement для не-PDO расширений могут
            поддерживать только один тип параметров.
        </para>

    </sect2>

    <sect2 id="zend.db.statement.fetching">

        <title>Извлечение результатов выполнения оператора <code>SELECT</code></title>

        <para>
            Вы можете вызывать методы объекта оператора для получения строк из
            SQL-операторов, которые возвращают наборы результатов. SELECT, SHOW,
            DESCRIBE и EXPLAIN являются примерами операторов, которые генерируют
            наборы результатов, а INSERT, UPDATE и DELETE - примерами
            операторов, которые не возвращают наборы результатов. Вы можете
            выполнять последние операторы, используя Zend_Db_Statement, но не
            можете вызывать методы для получения строк из результатов их
            выполнения.
        </para>

        <sect3 id="zend.db.statement.fetching.fetch">

            <title>Извлечение одной строки из набора результатов</title>

            <para>
                Для извлечения одной строки из набора результатов используйте
                метод <code>fetch()</code> объекта оператора. Все три аргумента
                этого метода являются опциональными:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <emphasis role="strong">Формат извлечения</emphasis> -
                        первый аргумент. Он используется для управления
                        структурой, в которой возвращаются данные. Описания
                        допустимых значений и соответствующих им форматов данных
                        читайте в <xref linkend="zend.db.adapter.select.fetch-mode" />.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis role="strong">Ориентация курсора</emphasis> -
                        второй аргумент. Значением по умолчанию является
                        константа Zend_Db::FETCH_ORI_NEXT, которая просто
                        означает, что каждый вызов метода <code>fetch()</code>
                        возвращает следующую строку в наборе результатов, в той
                        же последовательности, в которой строки были возвращены
                        из БД.
                    </para>
                </listitem>
                <listitem>
                    <para>
                        <emphasis role="strong">Смещение</emphasis> - третий
                        аргумент.
                        Если ориентация курсора - Zend_Db::FETCH_ORI_ABS, то
                        число смещения - порядковый номер строки для
                        возвращения.
                        Если ориентация курсора - Zend_Db::FETCH_ORI_REL, то
                        число смещения является относительным по отношению к
                        положению курсора до того, как был вызван
                        <code>fetch()</code>.
                    </para>
                </listitem>
            </itemizedlist>

            <para>
                <code>fetch()</code> возвращает <code>false</code>, если все
                строки из набора результатов были извлечены.
            </para>

            <example id="zend.db.statement.fetching.fetch.example">
                <title>Использование fetch() в цикле</title>
                <programlisting role="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

while ($row = $stmt->fetch()) {
    echo $row['bug_description'];
}
]]>
                </programlisting>
            </example>

            <para>
                См. также <ulink url="http://www.php.net/PDOStatement-fetch">PDOStatement::fetch()</ulink>.
            </para>

        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchall">

            <title>Извлечение всего набора результатов</title>

            <para>
                Для единовременного получения всех строк из набора результатов
                используйте метод <code>fetchAll()</code>. Он является
                эквивалентным вызову метода <code>fetch()</code> в цикле и
                возвращению всех строк в массиве. Метод <code>fetchAll()</code>
                принимает два аргумента. Первый из них - формат извлечения,
                описанный выше, через второй аргумент указывается число
                возвращаемых столбцов, если формат извлечения
                Zend_Db::FETCH_COLUMN.
            </para>

            <example id="zend.db.statement.fetching.fetchall.example">
                <title>Использование fetchAll()</title>
                <programlisting role="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

$rows = $stmt->fetchAll();

echo $rows[0]['bug_description'];
]]>
                </programlisting>
            </example>

            <para>
                См. также <ulink url="http://www.php.net/PDOStatement-fetchAll">PDOStatement::fetchAll()</ulink>.
            </para>

        </sect3>

        <sect3 id="zend.db.statement.fetching.fetch-mode">

            <title>Изменение формата извлечения</title>

            <para>
                По умолчанию объект оператора возвращает строки из набора
                результатов в виде ассоциативного массива имен столбцов и их
                значений. Вы можете указать другой формат для класса оператора,
                так же, как это делается для класса адаптера. Вы можете
                использовать метод <code>setFetchMode()</code> объекта оператора
                для указания режима извлечения. Указывайте режим извлечения,
                используя константы FETCH_ASSOC, FETCH_NUM, FETCH_BOTH,
                FETCH_COLUMN и FETCH_OBJ класса Zend_Db. Более подробную
                информацию об этих режимах читайте в
                <xref linkend="zend.db.adapter.select.fetch-mode" />. В
                последующих вызовах методов <code>fetch()</code>
                и <code>fetchAll()</code> объекта оператора будет использоваться
                заданный вами режим извлечения.
            </para>

            <example id="zend.db.statement.fetching.fetch-mode.example">
                <title>Установка формата извлечения</title>
                <programlisting role="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

$stmt->setFetchMode(Zend_Db::FETCH_NUM);

$rows = $stmt->fetchAll();

echo $rows[0][0];
]]>
                </programlisting>
            </example>

            <para>
                См. также <ulink url="http://www.php.net/PDOStatement-setFetchMode">PDOStatement::setFetchMode()</ulink>.
            </para>

        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchcolumn">

            <title>Извлечение одного столбца из набора результатов</title>

            <para>
                Для извлечения одного столбца из следующей строки в наборе
                результатов используйте <code>fetchColumn()</code>. Опциональный
                аргумент - целочисленный индекс столбца, по умолчанию это 0.
                Этот метод возвращает скалярное значение или <code>false</code>,
                если все строки набора результатов были уже извлечены
            </para>

            <para>
                Обратите внимание, что этот метод работает иначе, чем метод
                <code>fetchCol()</code> класса адаптера. Метод
                <code>fetchColumn()</code> оператора возвращает единственное
                значение из одной строки. Метод <code>fetchCol()</code> адаптера
                возвращает массив значений, взятых из первого столбца всех строк
                набора результатов.
            </para>

            <example id="zend.db.statement.fetching.fetchcolumn.example">
                <title>Использование fetchColumn()</title>
                <programlisting role="php"><![CDATA[
$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

$bug_status = $stmt->fetchColumn(2);
]]>
                </programlisting>
            </example>

            <para>
                См. также <ulink url="http://www.php.net/PDOStatement-fetchColumn">PDOStatement::fetchColumn()</ulink>.
            </para>

        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchobject">

            <title>Извлечение строки в виде объекта</title>

            <para>
                Для извлечения строки из набора результатов в виде объекта
                используйте метод <code>fetchObject()</code>. Этот метод
                принимает два опциональных аргумента. Первый аргумент является
                именем класса для возвращаемого объекта, по умолчанию это
                'stdClass'. Второй аргумент является массивом значений, которые
                будут переданы конструктору этого класса.
            </para>

            <example id="zend.db.statement.fetching.fetchobject.example">
                <title>Использование fetchObject()</title>
                <programlisting role="php"><![CDATA[
$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

$obj = $stmt->fetchObject();

echo $obj->bug_description;
]]>
                </programlisting>
            </example>

            <para>
                См. также <ulink url="http://www.php.net/PDOStatement-fetchObject">PDOStatement::fetchObject()</ulink>.
            </para>

        </sect3>

    </sect2>

    <!--
      @todo: binding parameters is not working yet.

    <sect2 id="zend.db.statement.binding-param">

        <title>Binding PHP Variables to Parameters</title>

        <para>
        </para>

        <example id="zend.db.statement.binding-param.example">
            <title>Binding parameters from PHP variables</title>
            <programlisting role="php"><![CDATA[<?php
]]>
            </programlisting>
        </example>

        <para>
            See also <ulink url="http://www.php.net/PDOStatement-bindParam">PDOStatement::bindParam()</ulink>.
        </para>

    </sect2>
    -->

    <!--
      @todo: binding columns is not working yet.
    <sect2 id="zend.db.statement.binding-column">

        <title>Binding PHP Variables to Query Results</title>

        <para>
        </para>

        <example id="zend.db.statement.binding-column.example">
            <title>Binding results to PHP variables</title>
            <programlisting role="php"><![CDATA[<?php
]]>
            </programlisting>
        </example>

        <para>
            See also <ulink url="http://www.php.net/PDOStatement-bindColumn">PDOStatement::bindColumn()</ulink>.
        </para>

    </sect2>
    -->

</sect1>
