<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24312 -->
<!-- Reviewed: no -->
<sect1 id="zend.db.statement">
    <title>Zend_Db_Statement</title>

    <para>
        Oprócz metod <methodname>fetchAll()</methodname> oraz <methodname>insert()</methodname>
        opisanych w <link linkend="zend.db.adapter">Zend_Db_Adapter</link>, możliwe jest 
        bezpośrednie użycie obiektu polecenia <classname>Zend_Db_Statement</classname> 
        w celu uzyskania większej ilości opcji tworzenia zapytań oraz zwracania ich rezultatów. 
        Rozdział ten opisuje 
        sposoby uzyskiwania dostępu do obiektu <classname>Zend_Db_Statement</classname> oraz 
        użycia jego metod.
    </para>

    <para>
        Klasa <classname>Zend_Db_Statement</classname> jest oparta na PDOStatement z rozszerzenia
        <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>.
    </para>

    <sect2 id="zend.db.statement.creating">
        <title>Utworzenie obiektu polecenia</title>

        <para>
            W typowej sytuacji obiekt <classname>Zend_Db_Statement</classname> zwracany jest 
            przez metodę <methodname>query()</methodname> klasy adaptera bazy danych. 
            Jest to standardowy sposób przygotowywania poleceń <acronym>SQL</acronym>. 
            Pierwszy argument to samo zapytanie <acronym>SQL</acronym>. 
            Drugi, opcjonalny, argument stanowi tablicę wartości
            służących do podstawienia jako parametry wiązane (bind parameters) w zapytaniu.
        </para>

        <example id="zend.db.statement.creating.example1">
            <title>Tworzenie zapytania SQL za pomocą metody query()</title>

            <programlisting language="php"><![CDATA[
$stmt = $db->query(
            'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
            array('goofy', 'FIXED')
        );
]]></programlisting>
        </example>

        <para>
            Taki obiekt <classname>Zend_Db_Statement</classname> odpowiada poleceniu 
            <acronym>SQL</acronym>, które zostało przygotowane i wykonane z określonymi 
            parametrami wiązanymi.
            Jeśli polecenie jest zapytaniem <acronym>SELECT</acronym> lub innym rodzajem instrukcji
            zwracającej zbiór danych to w tym momencie jest ono gotowe do pobrania rezultatu 
            zapytania.
        </para>

        <para>
            Mniej rozpowszechnionym sposobem użycia <classname>Zend_Db_Statement</classname>
            jest wykorzystanie jego konstruktora do utworzenia obiektu zapytania.
            Nie istnieje uniwersalna metoda fabryki tworząca taki obiekt więc niezbędne jest
            skorzystanie z konkretnej klasy zależnej od adaptera bazy danych.
            Obiekt adaptera stanowi pierwszy argument konstruktora natomiast łańcuch zawierający
            polecenie <acronym>SQL</acronym> jest drugim argumentem.
            Tak utworzona instrukcja jest preparowana ale nie wykonana.
        </para>

        <example id="zend.db.statement.creating.example2">
            <title>Użycie konstruktora polecenia SQL</title>

            <programlisting language="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>Wykonanie polecenia</title>

        <para>
            Jeśli obiekt <classname>Zend_Db_Statement</classname> został utworzony przy pomocy
            jego konstruktora to niezbędne jest wykonanie (jedno- bądź wielokrotne) polecenia 
            w nim zawartego. Służy temu metoda <methodname>execute()</methodname>.
            Jej argument stanowi tablica wartości przeznaczonych jako parametry wiązane
            do etykiet zastępczych umieszczonych w zapytaniu.
        </para>

        <para>
            Przy użyciu <emphasis>parametrów pozycyjnych</emphasis> lub znaków zapytania
            ('<emphasis>?</emphasis>') jako etykiet zastępczych, wartości parametrów wiązanych
            powinny zostać przekazane w zwykłej tablicy.
        </para>

        <example id="zend.db.statement.executing.example1">
            <title>Wykonanie polecenia z parametrami pozycyjnymi</title>

            <programlisting language="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>
            Przy użyciu <emphasis>parametrów nazywanych</emphasis> lub takich, które są 
            określone za pomocą identyfikatora poprzedzonego dwukropkiem ('<emphasis>:</emphasis>'),
            wartości parametrów wiązanych powinny zostać przekazane w tablicy asocjacyjnej.
            Klucze tablicy powinny odpowiadać nazwom parametrów.
        </para>

        <example id="zend.db.statement.executing.example2">
            <title>Wykonanie polecenia z parametrami nazywanymi</title>

            <programlisting language="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>
            Polecenia oparte na rozszerzeniu <acronym>PDO</acronym> wspierają zarówno pozycyjne 
            jak i nazywane parametry. Nie można jednak używać ich równocześnie w jednym 
            zapytaniu <acronym>SQL</acronym>.
            Część klas <classname>Zend_Db_Statement</classname> pozostałych rozszerzeń baz danych
            może oferować wsparcie jedynie dla jednego bądź drugiego typu parametrów wiązanych.
        </para>
    </sect2>

    <sect2 id="zend.db.statement.fetching">
        <title>Pobieranie rezultatów zapytania SELECT</title>

        <para>
            Aby pobrać wiersze rezultatu zapytania <acronym>SQL</acronym>, które zwraca dane
            można użyć odpowiednich metod obiektu <classname>Zend_Db_Statement</classname>.
            Zapytania <acronym>SELECT</acronym>, <acronym>SHOW</acronym>, 
            <acronym>DESCRIBE</acronym> oraz <acronym>EXPLAIN</acronym> to przykłady 
            poleceń zwracających dane.
            <acronym>INSERT</acronym>, <acronym>UPDATE</acronym> oraz <acronym>DELETE</acronym>
            są przykładami poleceń, które nie zwracają żadnych danych. Wywołać je można
            za pomocą <classname>Zend_Db_Statement</classname> ale w tym przypadku 
            nie jest możliwe użycie metod 
            pobierających wiersze rezultatu zapytania <acronym>SQL</acronym>.
        </para>

        <sect3 id="zend.db.statement.fetching.fetch">
            <title>Pobranie pojedynczego wiersza ze zbioru wynikowego</title>

            <para>
                Aby pobrać jeden wiersz ze zbioru wynikowego należy użyć metody
                <methodname>fetch()</methodname>. Wszystkie trzy jej argumenty są opcjonalne:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <emphasis>Styl pobierania</emphasis> jest pierwszym argumentem.
                        Kontroluje format zwracanego wiersza.
                        W <link linkend="zend.db.adapter.select.fetch-mode">tym rozdziale</link>
                        znajduje się opis możliwych wartości i odpowiadających im formatów.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>Położenie kursora</emphasis> jest drugim argumentem.
                        Domyślną wartością jest <constant>Zend_Db::FETCH_ORI_NEXT</constant>,
                        co oznacza, że każde odwołanie do metody <methodname>fetch()</methodname>
                        zwróci kolejny wiersz z wynikowego zbioru, w kolejności, w jakiej zostały
                        uporządkowane przez <acronym>RDBMS</acronym>.
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <emphasis>Numer wiersza</emphasis> jest trzecim argumentem.
                        Jeśli położenie kursora określone zostało jako
                        <constant>Zend_Db::FETCH_ORI_ABS</constant> to jest to absolutny
                        numer porządkowy wiersza, który zostanie zwrócony.
                        Jeśli położenie kursora określone zostało jako
                        <constant>Zend_Db::FETCH_ORI_REL</constant> to numer zwranacego wiersza
                        określany jest w relacji do położenia kursora bezpośrednio przed
                        wywołaniem metody <methodname>fetch()</methodname>.
                    </para>
                </listitem>
            </itemizedlist>

            <para>
                Metoda <methodname>fetch()</methodname> zwraca <constant>FALSE</constant>
                jeśli wszystkie wiersze zbioru wynikowego zostały zwrócone.
            </para>

            <example id="zend.db.statement.fetching.fetch.example">
                <title>Użycie fetch() w pętli</title>

                <programlisting language="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

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

            <para>
                Zobacz również <ulink
                   url="http://www.php.net/PDOStatement-fetch">PDOStatement::fetch()</ulink>.
            </para>
        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchall">
            <title>Zwrócenie całego zbioru wynikowego</title>

            <para>
            	Metoda <methodname>fetchAll()</methodname> służy zwróceniu wszystkich wierszy 
            	zbioru wynikowego w jednym kroku. Jest to jednoznaczne z wywołaniem
            	metody <methodname>fetch()</methodname> w pętli i zwróceniem wierszy w tablicy.
            	Metoda <methodname>fetchAll()</methodname> przyjmuje dwa argumenty. Pierwszy to,
            	opisany wyżej, tryb pobierania danych. Drugi wskazuje numer zwracanej kolumny 
            	w sytuacji, gdy trybem pobierania danych jest 
            	<constant>Zend_Db::FETCH_COLUMN</constant>.
            </para>

            <example id="zend.db.statement.fetching.fetchall.example">
                <title>Użycie fetchAll()</title>

                <programlisting language="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

$rows = $stmt->fetchAll();

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

            <para>
                Zobacz również <ulink
                    url="http://www.php.net/PDOStatement-fetchAll">PDOStatement::fetchAll()</ulink>.
            </para>
        </sect3>

        <sect3 id="zend.db.statement.fetching.fetch-mode">
            <title>Zmiana trybu pobierania danych</title>

            <para>
            	Domyślnie obiekt <classname>Zend_Db_Statement</classname> zwraca wiersze 
            	zbioru wynikowego w postaci zagnieżdżonych tablic asocjacyjnych mapujących nazwy
            	kolumn do odpowiadających im wartości. Zmiana formatu w którym 
            	<classname>Zend_Db_Statement</classname> zwraca dane jest możliwa w podobny sposób
            	jak w przypadku klasy adaptera. 
            	Za pomocą metody <methodname>setFetchMode()</methodname> można określić tryb 
            	pobierania danych. Możliwe wartości zawarte są w stałych klasy 
            	<classname>Zend_Db</classname>: <constant>FETCH_ASSOC</constant>,
                <constant>FETCH_NUM</constant>, <constant>FETCH_BOTH</constant>,
                <constant>FETCH_COLUMN</constant> oraz <constant>FETCH_OBJ</constant>.
                W <link linkend="zend.db.adapter.select.fetch-mode">tym rozdziale</link> 
                znajdują się szczegółowe informacje dotyczące poszczególnych trybów.
                Kolejne wywołania metod <methodname>fetch()</methodname> 
                czy <methodname>fetchAll()</methodname> używają ustawionego wcześniej trybu.
            </para>

            <example id="zend.db.statement.fetching.fetch-mode.example">
                <title>Ustawianie trybu pobierania danych</title>

                <programlisting language="php"><![CDATA[
$stmt = $db->query('SELECT * FROM bugs');

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

$rows = $stmt->fetchAll();

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

            <para>
                Zobacz również <ulink
                    url="http://www.php.net/PDOStatement-setFetchMode">PDOStatement::setFetchMode()</ulink>.
            </para>
        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchcolumn">
            <title>Pobranie pojedynczej kolumny ze zbioru wynikowego</title>

            <para>
            	Aby pobrać pojedynczą kolumnę kolejnego wiersza zbioru wynikowego
            	należy użyć metody <methodname>fetchColumn()</methodname>.
            	Jej opcjonalny argument to numer żądanej kolumny (domyślnie "0"). Na wyjściu
            	metoda zwraca wartość skalarną lub <constant>FALSE</constant> w przypadku gdy
            	wszystkie wiersze zostały już zwrócone.
            </para>

            <para>
            	Należy zaznaczyć, iż metoda ta działa inaczej niż 
            	<methodname>fetchCol()</methodname> klasy adaptera bazy danych.
            	Metoda <methodname>fetchColumn()</methodname> zwraca pojedynczą wartość z jednego
            	wiersza, <methodname>fetchCol()</methodname> adaptera zwraca tablicę wartości
            	branych z pierwszej kolumny wszystkich wierszy bieżącego zbioru wynikowego.
            </para>

            <example id="zend.db.statement.fetching.fetchcolumn.example">
                <title>Użycie fetchColumn()</title>

                <programlisting language="php"><![CDATA[
$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

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

            <para>
                Zobacz również <ulink
                    url="http://www.php.net/PDOStatement-fetchColumn">PDOStatement::fetchColumn()</ulink>.
            </para>
        </sect3>

        <sect3 id="zend.db.statement.fetching.fetchobject">
            <title>Pobranie wiersza jako obiektu</title>

            <para>
            	Aby pobrać wiersz zbioru wynikowego w postaci obiektu należy użyć metody
            	<methodname>fetchObject()</methodname>. Przyjmuje ona dwa opcjonalne argumenty.
            	Pierwszy to łańcuch znaków zawierający nazwę klasy, której obiekt ma być zwrócony,
            	domyślnie jest to 'stdClass'. Drugi argument to tablica wartości, które zostaną
            	przekazane do konstruktora tworzonej klasy.
            </para>

            <example id="zend.db.statement.fetching.fetchobject.example">
                <title>Użycie fetchObject()</title>

                <programlisting language="php"><![CDATA[
$stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

$obj = $stmt->fetchObject();

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

            <para>
                Zobacz również <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 language="php"><![CDATA[
]]></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 language="php"><![CDATA[
]]></programlisting>
        </example>

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

    </sect2>
    -->
</sect1>
