# Zend_Db_Statement

Oprócz metod fetchAll() oraz insert() opisanych w Zend_Db_Adapter, możliwe jest bezpośrednie użycie obiektu polecenia Zend_Db_Statement w celu uzyskania większej ilości opcji tworzenia zapytań oraz zwracania ich rezultatów. Rozdział ten opisuje sposoby uzyskiwania dostępu do obiektu Zend_Db_Statement oraz użycia jego metod.

Klasa Zend_Db_Statement jest oparta na PDOStatement z rozszerzenia PHP Data Objects.

## Utworzenie obiektu polecenia

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

Tworzenie zapytania SQL za pomocą metody query()

    $stmt = $db->query(
                'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
                array('goofy', 'FIXED')
            );

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

Mniej rozpowszechnionym sposobem użycia Zend_Db_Statement 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 SQL jest drugim argumentem. Tak utworzona instrukcja jest preparowana ale nie wykonana.

Użycie konstruktora polecenia SQL

    $sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';

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

## Wykonanie polecenia

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

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

Wykonanie polecenia z parametrami pozycyjnymi

    $sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';

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

    $stmt->execute(array('goofy', 'FIXED'));

Przy użyciu parametrów nazywanych lub takich, które są określone za pomocą identyfikatora poprzedzonego dwukropkiem (':'), wartości parametrów wiązanych powinny zostać przekazane w tablicy asocjacyjnej. Klucze tablicy powinny odpowiadać nazwom parametrów.

Wykonanie polecenia z parametrami nazywanymi

    $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'));

Polecenia oparte na rozszerzeniu PDO wspierają zarówno pozycyjne jak i nazywane parametry. Nie można jednak używać ich równocześnie w jednym zapytaniu SQL. Część klas Zend_Db_Statement pozostałych rozszerzeń baz danych może oferować wsparcie jedynie dla jednego bądź drugiego typu parametrów wiązanych.

## Pobieranie rezultatów zapytania SELECT

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

### Pobranie pojedynczego wiersza ze zbioru wynikowego

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

- Styl pobierania jest pierwszym argumentem. Kontroluje format zwracanego wiersza. W tym rozdziale znajduje się opis możliwych wartości i odpowiadających im formatów.

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

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

Metoda fetch() zwraca `FALSE` jeśli wszystkie wiersze zbioru wynikowego zostały zwrócone.

Użycie fetch() w pętli

    $stmt = $db->query('SELECT * FROM bugs');

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

Zobacz również PDOStatement::fetch().

### Zwrócenie całego zbioru wynikowego

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

Użycie fetchAll()

    $stmt = $db->query('SELECT * FROM bugs');

    $rows = $stmt->fetchAll();

    echo $rows[0]['bug_description'];

Zobacz również PDOStatement::fetchAll().

### Zmiana trybu pobierania danych

Domyślnie obiekt Zend_Db_Statement 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 Zend_Db_Statement zwraca dane jest możliwa w podobny sposób jak w przypadku klasy adaptera. Za pomocą metody setFetchMode() można określić tryb pobierania danych. Możliwe wartości zawarte są w stałych klasy Zend_Db: `FETCH_ASSOC`, `FETCH_NUM`, `FETCH_BOTH`, `FETCH_COLUMN` oraz `FETCH_OBJ`. W tym rozdziale znajdują się szczegółowe informacje dotyczące poszczególnych trybów. Kolejne wywołania metod fetch() czy fetchAll() używają ustawionego wcześniej trybu.

Ustawianie trybu pobierania danych

    $stmt = $db->query('SELECT * FROM bugs');

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

    $rows = $stmt->fetchAll();

    echo $rows[0][0];

Zobacz również PDOStatement::setFetchMode().

### Pobranie pojedynczej kolumny ze zbioru wynikowego

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

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

Użycie fetchColumn()

    $stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

    $bug_status = $stmt->fetchColumn(2);

Zobacz również PDOStatement::fetchColumn().

### Pobranie wiersza jako obiektu

Aby pobrać wiersz zbioru wynikowego w postaci obiektu należy użyć metody fetchObject(). 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.

Użycie fetchObject()

    $stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');

    $obj = $stmt->fetchObject();

    echo $obj->bug_description;

Zobacz również PDOStatement::fetchObject().