# 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().