1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 21740 -->
4 <sect1 id="zend.db.adapter">
5 <title>Zend_Db_Adapter</title>
8 <classname>Zend_Db</classname> i powiązane z nim klasy udostępniają prosty interfejs
9 dla baz danych <acronym>SQL</acronym> z poziomu Zend Framework. Klasa
10 <classname>Zend_Db_Adapter</classname> jest podstawowym komponentem potrzebnym by
11 połączyć aplikację PHP z systemem zarządzania bazą danych (<acronym>RDBMS</acronym>).
12 Dla każdego rodzaju bazy danych istnieje oddzielna klasa adaptera
13 <classname>Zend_Db</classname>.
17 Adaptery <classname>Zend_Db</classname> tworzą połączenie pomiędzy rozszerzeniami
18 <acronym>PHP</acronym> dla konkretnych rodzajów baz danych a wspólnym interfejsem,
19 dzięki czemu można napisać aplikację raz i w nieskomplikowany sposób uruchamiać
20 ją z wieloma rodzajami <acronym>RDBMS</acronym>
24 Interfejs klasy adaptera jest podobny do interfejsu rozszerzenia
25 <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>. <classname>Zend_Db</classname>
26 zawiera klasy adapterów dla sterowników <acronym>PDO</acronym> następujących rodzajów
33 IBM DB2 oraz Informix Dynamic Server (IDS), poprzez rozszerzenie
34 <acronym>PHP</acronym>
35 <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>.
41 MySQL, poprzez rozszerzenie <acronym>PHP</acronym>
42 <ulink url="http://www.php.net/pdo-mysql">pdo_mysql</ulink>
48 Microsoft <acronym>SQL</acronym> Server, używając rozszerzenia
49 <acronym>PHP</acronym>
50 <ulink url="http://www.php.net/pdo-dblib">pdo_dblib</ulink>
56 Oracle, poprzez rozszerzenie <acronym>PHP</acronym>
57 <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink>
63 PostgreSQL, poprzez rozszerzenie <acronym>PHP</acronym>
64 <ulink url="http://www.php.net/pdo-pgsql">pdo_pgsql</ulink>
70 SQLite, używając rozszerzenia <acronym>PHP</acronym>
71 <ulink url="http://www.php.net/pdo-sqlite">pdo_sqlite</ulink>
77 Dodatkowo <classname>Zend_Db</classname> dostarcza klas adapterów korzystających
78 z rozszerzeń <acronym>PHP</acronym> dla następujących rodzajów
85 MySQL, poprzez rozszerzenie <acronym>PHP</acronym>
86 <ulink url="http://www.php.net/mysqli">mysqli</ulink>
92 Oracle, poprzez rozszerzenie <acronym>PHP</acronym>
93 <ulink url="http://www.php.net/oci8">oci8</ulink>
99 IBM DB2 oraz DB2/i5, poprzez rozszerzenie <acronym>PHP</acronym>
100 <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
106 Firebird/Interbase, poprzez rozszerzenie <acronym>PHP</acronym>
107 <ulink url="http://www.php.net/ibase">php_interbase</ulink>
114 Każdy adapter <classname>Zend_Db</classname> używa określonego rozszerzenia
115 <acronym>PHP</acronym>. Aby użyć adaptera należy mieć zainstalowane i włączone
116 odpowiadające mu rozszerzenie <acronym>PHP</acronym>. Np. aby użyć dowolnego
117 adaptera <acronym>PDO</acronym> <classname>Zend_Db</classname>, wymagane jest
118 posiadanie włączonego rozszerzenia <acronym>PDO</acronym> oraz sterownika dla
119 danego rodzaju <acronym>RDBMS</acronym>.
123 <sect2 id="zend.db.adapter.connecting">
124 <title>Połączenie z bazą danych za pomocą adaptera</title>
127 Ta część opisuje jak tworzy się instancję adaptera bazy danych. Jest to odpowiednik
128 połączenia z bazą danych w aplikacji <acronym>PHP</acronym>.
131 <sect3 id="zend.db.adapter.connecting.constructor">
132 <title>Użycie konstruktora adaptera Zend_Db</title>
135 Można utworzyć instancję adaptera za pomocą konstruktora. Przyjmuje on
136 pojedynczy argument - tablicę parametrów używanych do deklaracji połączenia.
139 <example id="zend.db.adapter.connecting.constructor.example">
140 <title>Użycie konstruktora adaptera</title>
142 <programlisting language="php"><![CDATA[
143 $db = new Zend_Db_Adapter_Pdo_Mysql(array(
144 'host' => '127.0.0.1',
145 'username' => 'webuser',
146 'password' => 'xxxxxxxx',
153 <sect3 id="zend.db.adapter.connecting.factory">
154 <title>Użycie fabryki Zend_Db</title>
157 Alternatywą w stosunku do bezpośredniego używania konstruktora jest utworzenie
158 instancji adaptera za pomocą statycznej metody
159 <methodname>Zend_Db::factory()</methodname>. Ta metoda dynamicznie ładuje plik
160 klasy adaptera używając
161 <link linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>.
165 Pierwszy argument metody to łańcuch znaków, który wyznacza nazwę bazową klasy
166 adaptera. Np. string '<classname>Pdo_Mysql</classname>' odpowiada klasie
167 <classname>Zend_Db_Adapter_Pdo_Mysql</classname>. Drugi argument to ta sama
168 tablica parametrów, którą należało podać adapterowi konstruktora.
171 <example id="zend.db.adapter.connecting.factory.example">
172 <title>Użycie metody fabryki adaptera</title>
174 <programlisting language="php"><![CDATA[
175 // Poniższa instrukcja jest zbędna ponieważ plik z klasą
176 // Zend_Db_Adapter_Pdo_Mysql zostanie załadowany przez fabrykę
179 // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
181 // Załaduj klasę Zend_Db_Adapter_Pdo_Mysql automatycznie
182 // i utwórz jej instancję
183 $db = Zend_Db::factory('Pdo_Mysql', array(
184 'host' => '127.0.0.1',
185 'username' => 'webuser',
186 'password' => 'xxxxxxxx',
193 Jeśli jest zdefiniowana własna klasa dziedzicząca po
194 <classname>Zend_Db_Adapter_Abstract</classname> ale jej nazwa nie zawiera
195 "<classname>Zend_Db_Adapter</classname>", można użyć metody
196 <methodname>factory()</methodname> do załadowania adaptera jedynie jeśli
197 poda się swój prefiks nazwy adaptera z kluczem 'adapterNamespace' do
198 argumentu zawierającego parametry połączenia.
201 <example id="zend.db.adapter.connecting.factory.example2">
202 <title>Użycie metody fabryki dla własnej klasy adaptera</title>
203 <programlisting language="php"><![CDATA[
204 // Nie trzeba ładować pliku klasy adaptera
205 // bo robi to metoda fabryki Zend_Db
207 // Załadowanie klasy MyProject_Db_Adapter_Pdo_Mysql automatycznie
208 // i utworzenie jej instancji
209 $db = Zend_Db::factory('Pdo_Mysql', array(
210 'host' => '127.0.0.1',
211 'username' => 'webuser',
212 'password' => 'xxxxxxxx',
214 'adapterNamespace' => 'MyProject_Db_Adapter'
220 <sect3 id="zend.db.adapter.connecting.factory-config">
221 <title>Użycie Zend_Config z fabryką Zend_Db</title>
224 Każdy z argumentów metody <methodname>factory()</methodname> może również zostać
225 podany w formie obiektu klasy <link linkend="zend.config">Zend_Config</link>.
229 Jeśli pierwszy argument jest obiektem <classname>Zend_Config</classname>
230 to wymagane jest aby posiadał właściwość o nazwie
231 <property>adapter</property>, w której będzie zapisany łańcuch znaków
232 określający nazwę bazową klasy adaptera. Opcjonalnie, obiekt ten może zawierać
233 właściwość '<property>params</property>' z właściwościami potomnymi
234 odpowiadającymi nazwom parametrów adaptera. Będą one użyte jedynie w
235 przypadku braku drugiego argumentu metody
236 <methodname>factory()</methodname>.
239 <example id="zend.db.adapter.connecting.factory.example1">
240 <title>Użycie metody fabryki adaptera z obiektem Zend_Config</title>
243 W poniższym przykładzie, obiekt <classname>Zend_Config</classname>
244 jest utworzony z tablicy.
245 Można również załadować dane z pliku zewnętrznego poprzez klasy
246 <link linkend="zend.config.adapters.ini">Zend_Config_Ini</link> oraz
247 <link linkend="zend.config.adapters.xml">Zend_Config_Xml</link>.
250 <programlisting language="php"><![CDATA[
251 $config = new Zend_Config(
254 'adapter' => 'Mysqli',
256 'host' => '127.0.0.1',
258 'username' => 'webuser',
259 'password' => 'secret',
265 $db = Zend_Db::factory($config->database);
270 Drugi argument metody <methodname>factory()</methodname> może stanowić tablicę
271 asocjacyjną zawierającą wartości odpowiadające parametrom adaptera. Ten argument
272 jest opcjonalny. Jeśli pierwszy argument jest obiektem klasy
273 <classname>Zend_Config</classname> to powinien zawierać wszystkie parametry a
274 drugi argument jest ignorowany.
278 <sect3 id="zend.db.adapter.connecting.parameters">
279 <title>Parametry adaptera</title>
282 Poniższa lista opisuje parametry wspólne dla klas adapterów
283 <classname>Zend_Db</classname>.
289 <emphasis>host</emphasis>:
290 łańcuch znaków zawierający nazwę hosta lub adres IP serwera bazy danych.
291 Jeśli baza danych jest uruchomiona na tej samej maszynie co aplikacja to
292 można tu umieścić 'localhost' lub '127.0.0.1'.
298 <emphasis>username</emphasis>:
299 identyfikator użytkownika używany do autoryzacji połączenia z serwerem
306 <emphasis>password</emphasis>:
307 hasło użytkownika używane do autoryzacji połączenia z serwerem
314 <emphasis>dbname</emphasis>:
315 nazwa instancji bazy danych na serwerze.
321 <emphasis>port</emphasis>:
322 niektóre serwery bazy danych używają do komunikacji numeru portu określonego
323 przez administratora. Ten parametr pozwala na ustawienie numeru portu przez
324 który aplikacja <acronym>PHP</acronym> się łączy tak aby zgadzał się z tym
325 ustawionym na serwerze bazy danych.
331 <emphasis>charset</emphasis>:
332 określenie zestawu znaków używanego podczas połączenia.
338 <emphasis>options</emphasis>:
339 ten parametr to tablica asocjacyjna opcji obsługiwanych przez wszystkie
340 klasy <classname>Zend_Db_Adapter</classname>.
346 <emphasis>driver_options</emphasis>:
347 ten parametr to tablica asocjacyjna zawierająca dodatkowe opcje
348 specyficzne dla każdego rozszerzenia bazy danych. Typowym przykładem
349 użycia tego parametru jest zbiór atrybutów sterownika
350 <acronym>PDO</acronym>.
356 <emphasis>adapterNamespace</emphasis>:
357 początkowa część nazwy klasy używanego adaptera, używana zamiast
358 '<classname>Zend_Db_Adapter</classname>'. Przydatna w przypadku użycia
359 metody <methodname>factory()</methodname> do załadowana własnej klasy
365 <example id="zend.db.adapter.connecting.parameters.example1">
366 <title>Przekazanie do fabryki opcji zmiany wielkości znaków</title>
369 Opcję tą można podać za pomocą stałej
370 <constant>Zend_Db::CASE_FOLDING</constant>.
371 Odpowiada ona atrybutowi <constant>ATTR_CASE</constant> w <acronym>PDO</acronym>
372 oraz rozszerzeniu IBM DB2, który zmienia wielkość znaków w nazwach kolumn
373 zwracanych w rezultacie zapytania. Opcja przybiera wartości
374 <constant>Zend_Db::CASE_NATURAL</constant> (bez zmiany - domyślnie),
375 <constant>Zend_Db::CASE_UPPER</constant> (zmiana na wielkie znaki) oraz
376 <constant>Zend_Db::CASE_LOWER</constant> (zmiana na małe znaki).
379 <programlisting language="php"><![CDATA[
381 Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
385 'host' => '127.0.0.1',
386 'username' => 'webuser',
387 'password' => 'xxxxxxxx',
389 'options' => $options
392 $db = Zend_Db::factory('Db2', $params);
396 <example id="zend.db.adapter.connecting.parameters.example2">
397 <title>Przekazanie do fabryki opcji automatycznego umieszczania
398 w cudzysłowie</title>
401 Tą opcję można podać za pomocą stałej
402 <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant>.
403 Jeśli jej wartość wynosi <constant>TRUE</constant> (domyślnie) to identyfikatory
404 takie jak nazwy tabel, kolumn oraz aliasy w składni każdego polecenia
405 <acronym>SQL</acronym> generowanego za pomocą danego adaptera będą
406 umieszczane w cudzysłowie. Takie podejście upraszcza używanie identyfikatorów
407 zawierających słowa kluczowe <acronym>SQL</acronym> lub znaki specjalne. Jeśli
408 wartość opcji wynosi <constant>FALSE</constant> to identyfikatory nie są
409 umieszczane w cudzysłowie. Jeśli zachodzi potrzeba owinięcia identyfikatorów
410 cudzysłowami należy to zrobić samodzielnie za pomocą metody
411 <methodname>quoteIdentifier()</methodname>.
414 <programlisting language="php"><![CDATA[
416 Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
420 'host' => '127.0.0.1',
421 'username' => 'webuser',
422 'password' => 'xxxxxxxx',
424 'options' => $options
427 $db = Zend_Db::factory('Pdo_Mysql', $params);
431 <example id="zend.db.adapter.connecting.parameters.example3">
432 <title>Przekazanie do fabryki opcji sterownika PDO</title>
434 <programlisting language="php"><![CDATA[
436 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
440 'host' => '127.0.0.1',
441 'username' => 'webuser',
442 'password' => 'xxxxxxxx',
444 'driver_options' => $pdoParams
447 $db = Zend_Db::factory('Pdo_Mysql', $params);
449 echo $db->getConnection()
450 ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
454 <example id="zend.db.adapter.connecting.parameters.example4">
455 <title>Przekazanie do fabryki opcji serializacji</title>
457 <programlisting language="php"><![CDATA[
459 Zend_Db::ALLOW_SERIALIZATION => false
463 'host' => '127.0.0.1',
464 'username' => 'webuser',
465 'password' => 'xxxxxxxx',
467 'options' => $options
470 $db = Zend_Db::factory('Pdo_Mysql', $params);
475 <sect3 id="zend.db.adapter.connecting.getconnection">
476 <title>Zarządzanie leniwymi połączeniami</title>
479 Utworzenie instancji klasy adaptera nie powoduje natychmiastowego połączenia
480 z serwerem bazy danych. Adapter zachowuje parametry połączenia ale łączy się
481 na żądanie - w momencie pierwszego wywołania zapytania. Dzięki temu zainicjowanie
482 adaptera jest szybkie i tanie. Można utworzyć adapter nawet jeśli nie jest
483 się pewnym czy wykonanie jakiegokolwiek zapytania przy danym połączeniu będzie
488 Jeśli zajdzie potrzeba zmuszenia adaptera do połączenia z bazą danych,
489 należy wówczas wywołać metodę <methodname>getConnection()</methodname>.
490 Zwraca ona obiekt połączenia odpowiednio do rozszerzenia
491 <acronym>PHP</acronym> używanego do połączenia. Jeśli
492 używa się adaptera korzystającego z <acronym>PDO</acronym>, to metoda
493 <methodname>getConnection()</methodname>, po zainicjowaniu połączenia
494 z serwerem bazy danych, zwróci obiekt <acronym>PDO</acronym>.
498 Możliwość wymuszenia połączenia z bazą danych może być przydatna gdy chce się
499 złapać wyjątki rzucane przez adapter powstałe w rezultacie podania złych danych
500 uwierzytelniających lub innych błędów połączenia. Te wyjątki nie są rzucane dopóki
501 nie jest ustanowiona próba połączenia, więc można uprościć kod aplikacji i obsłużyć
502 je w jednym miejscu. W przeciwnym razie należałoby je przechwycać w momencie
503 wywołania pierwszego zapytania do bazy danych.
507 Dodatkowo adapter może zostać poddany serializacji i przechowany
508 np. w zmiennej sesyjnej.
509 Może to być pomocne nie tylko dla adaptera ale również z punktu widzenia obiektów,
510 które z niego korzystają, takich jak <classname>Zend_Db_Select</classname>.
511 Domyślnie serializacja adapterów jest dozwolona ale jeśli jest taka
512 potrzeba - można ją wyłączyć poprzez podanie opcji
513 <constant>Zend_Db::ALLOW_SERIALIZATION</constant> z wartością
514 <constant>FALSE</constant> (przykład niżej).
515 Aby pozostać w zgodzie z zasadą leniwego połączenia, adapter nie połączy się
516 automatycznie po odserializowaniu. Należy zatem
517 wywołać metodę <methodname>getConnection()</methodname>.
518 Można również zmusić adapter aby po odserializowaniu łączył się z bazą
519 danych automatycznie poprzez podanie opcji
520 <constant>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE</constant>
521 z wartością <constant>TRUE</constant>.
524 <example id="zend.db.adapter.connecting.getconnection.example">
525 <title>Obsługa wyjątków połączenia</title>
527 <programlisting language="php"><![CDATA[
529 $db = Zend_Db::factory('Pdo_Mysql', $parameters);
530 $db->getConnection();
531 } catch (Zend_Db_Adapter_Exception $e) {
532 // przyczyną problemów mogą być złe dane uwierzytelniające lub np. baza danych
533 // nie jest uruchomiona
534 } catch (Zend_Exception $e) {
535 // przyczyną może być np. problem z załadowaniem odpowiedniej klasy adaptera
544 <sect2 id="zend.db.adapter.example-database">
546 <title>Przykładowa baza danych</title>
549 W dokumentacji klas <classname>Zend_Db</classname> używany jest prosty zestaw tabel w
550 celu zilustrowania użycia klas i metod. Te tabele mogą przechowywać dane związane z
551 przechowywaniem błędów (bugs) powstałych podczas rozwijania projektu informatycznego.
552 Baza danych zawiera cztery tabele:
558 <emphasis>accounts</emphasis> przechowuje informacje o każdym użytkowniku
564 <emphasis>products</emphasis> przechowuje informacje o każdym produkcie,
565 dla którego można zapisać wystąpienie usterki.
570 <emphasis>bugs</emphasis> przechowuje informacje o błędach, włączając
571 jego obecny stan, osobę zgłaszającą, osobę przypisaną do rozwiązania
572 problemu oraz osobę przeznaczoną do zweryfikowania poprawności
573 zastosowanego rozwiązania.
578 <emphasis>bugs_products</emphasis> przechowuje relację pomiędzy usterkami
579 a produktami. To odzwierciedla połączenie wiele-do-wielu, ponieważ dany błąd
580 może się odnosić do wielu produktów a jeden produkt może posiadać wiele usterek.
586 Poniższy pseudokod definicji danych <acronym>SQL</acronym> opisuje tabele z tego
587 przykładu. Te tabele są bardzo często używane w testach jednostkowych
588 <classname>Zend_Db</classname>.
591 <programlisting language="sql"><![CDATA[
592 CREATE TABLE accounts (
593 account_name VARCHAR(100) NOT NULL PRIMARY KEY
596 CREATE TABLE products (
597 product_id INTEGER NOT NULL PRIMARY KEY,
598 product_name VARCHAR(100)
602 bug_id INTEGER NOT NULL PRIMARY KEY,
603 bug_description VARCHAR(100),
604 bug_status VARCHAR(20),
605 reported_by VARCHAR(100) REFERENCES accounts(account_name),
606 assigned_to VARCHAR(100) REFERENCES accounts(account_name),
607 verified_by VARCHAR(100) REFERENCES accounts(account_name)
610 CREATE TABLE bugs_products (
611 bug_id INTEGER NOT NULL REFERENCES bugs,
612 product_id INTEGER NOT NULL REFERENCES products,
613 PRIMARY KEY (bug_id, product_id)
618 Należy zwrócić uwagę, iż tabela 'bugs' zawiera wiele kluczy obcych
619 odnoszących się do tabeli 'accounts'. Każdy z nich może prowadzić do
620 innego wiersza tabeli 'accounts' w ramach jednego bugu.
624 Poniższy diagram ilustruje fizyczny model danych przykładowej bazy danych
628 <inlinegraphic width="387" scale="100" align="center" valign="middle"
629 fileref="figures/zend.db.adapter.example-database.png" format="PNG" />
634 <sect2 id="zend.db.adapter.select">
636 <title>Pobranie rezultatów zapytania</title>
639 Ta część opisuje metody klasy adaptera za pomocą których można wywołać
640 zapytania <acronym>SELECT</acronym> oraz pobrać ich rezultaty.
643 <sect3 id="zend.db.adapter.select.fetchall">
645 <title>Pobranie całego zbioru rezultatów</title>
648 Za pomocą metody <methodname>fetchAll()</methodname> można wywołać zapytanie
649 <acronym>SQL</acronym> <acronym>SELECT</acronym> oraz pobrać jego rezultaty
654 Pierwszym argumentem metody jest łańcuch znaków zawierający polecenie
655 <acronym>SELECT</acronym>. Alternatywnie, w pierwszym argumencie można umieścić
656 obiekt klasy <link linkend="zend.db.select">Zend_Db_Select</link>. Adapter
657 automatycznie dokonuje konwersji tego obiektu do łańcucha znaków zawierającego
658 zapytanie <acronym>SELECT</acronym>.
662 Drugi argument metody <methodname>fetchAll()</methodname> to tablica wartości
663 używanych do zastąpienia parametrów wiązanych w zapytaniu <acronym>SQL</acronym>.
666 <example id="zend.db.adapter.select.fetchall.example">
667 <title>Użycie metody fetchAll()</title>
668 <programlisting language="php"><![CDATA[
669 $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
671 $result = $db->fetchAll($sql, 2);
677 <sect3 id="zend.db.adapter.select.fetch-mode">
679 <title>Zmiana trybu zwracania danych</title>
682 Domyślnie <methodname>fetchAll()</methodname> zwraca tablicę wierszy, z których
683 każdy jest tablicą asocjacyjną. Kluczami tablicy asocjacyjnej są kolumny lub ich
684 aliasy podane w zapytaniu <acronym>SELECT</acronym>.
688 Można ustawić inny tryb zwracania rezultatów poprzez metodę
689 <methodname>setFetchMode()</methodname>. Dopuszczalne tryby są identyfikowane
696 <emphasis>Zend_Db::FETCH_ASSOC</emphasis>:
697 zwraca dane w postaci tablicy tablic asocjacyjnych.
698 Klucze tablicy asocjacyjnej
699 to nazwy kolumn. To jest domyślny tryb zwrotu danych w klasach
700 <classname>Zend_Db_Adapter</classname>.
703 Należy zwrócić uwagę na fakt iż jeśli lista kolumn do zwrotu
704 zawiera więcej niż jedną kolumnę o określonej nazwie,
705 np. jeśli pochodzą one z różnych tabel
706 połączonych klauzulą <acronym>JOIN</acronym>, to w asocjacyjnej
707 tablicy wynikowej może być tylko jeden klucz o podanej nazwie.
708 Jeśli używany jest tryb <acronym>FETCH_ASSOC</acronym>,
709 należy upewnić się, że kolumny w zapytaniu
710 <acronym>SELECT</acronym> posiadają aliasy, dzięki czemu rezultat zapytania
711 będzie zawierał unikatowe nazwy kolumn.
714 Domyślnie, łańcuchy znaków z nazwami kolumn są zwracane w taki sposób w jaki
715 zostały otrzymane przez sterownik bazy danych. Przeważnie jest odpowiada to
716 stylowi nazw kolumn używanego rodzaju bazy danych. Dzięki opcji
717 <constant>Zend_Db::CASE_FOLDING</constant> można określić wielkość
719 Opcji tej można użyć podczas inicjowania adaptera.
720 Przykład: <xref linkend="zend.db.adapter.connecting.parameters.example1" />.
725 <emphasis>Zend_Db::FETCH_NUM</emphasis>:
726 zwraca dane jako tablicę tablic. Indeksami tablicy są liczby całkowite
727 odpowiadające pozycji danej kolumny w liście <acronym>SELECT</acronym>
733 <emphasis>Zend_Db::FETCH_BOTH</emphasis>:
734 zwraca dane jako tablicę tablic. Kluczami tablicy są zarówno łańcuchy znaków
735 (tak jak w trybie FETCH_ASSOC) oraz liczby całkowite (tak jak w trybie
736 FETCH_NUM). Należy zwrócić uwagę na fakt iż liczba elementów
737 tablicy wynikowej będzie dwukrotnie większa niż w przypadku
738 użycia trybów FETCH_ASSOC lub FETCH_NUM.
743 <emphasis>Zend_Db::FETCH_COLUMN</emphasis>:
744 zwraca dane jako tablicę wartości. Wartości odpowiadają rezultatom
745 zapytania przypisanym jednej kolumnie zbioru wynikowego.
746 Domyślnie, jest to pierwsza kolumna,
747 indeksy rozpoczynają się od 0.
752 <emphasis>Zend_Db::FETCH_OBJ</emphasis>:
753 zwraca dane jako tablicę obiektów. Domyślną klasą jest wbudowana
754 w <acronym>PHP</acronym> klasa stdClass.
755 Kolumny rezultatu zapytania stają się właściwościami powstałego obiektu.
760 <example id="zend.db.adapter.select.fetch-mode.example">
761 <title>Użycie metody setFetchMode()</title>
762 <programlisting language="php"><![CDATA[
763 $db->setFetchMode(Zend_Db::FETCH_OBJ);
765 $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
767 // $result jest tablicą obiektów
768 echo $result[0]->bug_description;
774 <sect3 id="zend.db.adapter.select.fetchassoc">
776 <title>Pobranie rezultatów jako tablicy asocjacyjnej</title>
779 Metoda <methodname>fetchAssoc()</methodname> zwraca dane w formie tablicy tablic
780 asocjacyjnych, niezależnie od wartości ustalonej jako tryb
781 zwracania rezultatów zapytania.
784 <example id="zend.db.adapter.select.fetchassoc.example">
785 <title>Użycie fetchAssoc()</title>
786 <programlisting language="php"><![CDATA[
787 $db->setFetchMode(Zend_Db::FETCH_OBJ);
789 $result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
791 // $result staje się tablicą tablic asocjacyjnych, mimo ustawionego
792 // trybu zwracania rezultatów zapytania
793 echo $result[0]['bug_description'];
799 <sect3 id="zend.db.adapter.select.fetchcol">
801 <title>Zwrócenie pojedynczej kolumny ze zbioru wynikowego</title>
804 Metoda <methodname>fetchCol()</methodname> zwraca dane w postaci tablicy wartości
805 niezależnie od wartości ustalonej jako tryb zwrcania rezultatów zapytania. Ta
806 metoda zwraca pierwszą kolumnę ze zbioru powstałego na skutek wywołania zapytania.
807 Inne kolumny znajdujące się w tym zbiorze są ignorowane. Aby zwrócić inną niż
808 pierwsza kolumnę należy skorzystać z przykładu
809 <xref linkend="zend.db.statement.fetching.fetchcolumn" />.
812 <example id="zend.db.adapter.select.fetchcol.example">
813 <title>Użycie fetchCol()</title>
814 <programlisting language="php"><![CDATA[
815 $db->setFetchMode(Zend_Db::FETCH_OBJ);
817 $result = $db->fetchCol(
818 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
820 // zawiera bug_description; bug_id nie zostanie zwrócona
827 <sect3 id="zend.db.adapter.select.fetchpairs">
829 <title>Zwrócenie ze zbioru wynikowego par klucz-wartość</title>
832 Metoda <methodname>fetchPairs()</methodname> zwraca dane w postaci tablicy
833 par klucz-wartość. Zwracana jest to tablica asocjacyjna z pojedynczą wartością
834 w każdym polu. Wartości z pierwszej kolumny zapytania <acronym>SELECT</acronym>
835 stają się kluczami tablicy wynikowej zaś wartości drugiej zostają umieszczone
836 jako wartości tablicy. Pozostałe kolumny zwracane przez zapytanie są ignorowane.
840 Należy konstruować zapytanie <acronym>SELECT</acronym> w taki sposób aby pierwsza
841 kolumna posiadała unikalne wartości. W przeciwnym wypadku wartości
842 tablicy asocjacyjnej zostaną nadpisane.
845 <example id="zend.db.adapter.select.fetchpairs.example">
846 <title>Użycie fetchPairs()</title>
847 <programlisting language="php"><![CDATA[
848 $db->setFetchMode(Zend_Db::FETCH_OBJ);
850 $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
857 <sect3 id="zend.db.adapter.select.fetchrow">
859 <title>Zwrócenie pojedynczego wiersza ze zbioru wynikowego</title>
862 Metoda <methodname>fetchRow()</methodname> pobiera dane używając bieżącego
863 trybu zwracania rezultatów ale zwraca jedynie pierwszy wiersz ze zbioru
867 <example id="zend.db.adapter.select.fetchrow.example">
868 <title>Using fetchRow()</title>
869 <programlisting language="php"><![CDATA[
870 $db->setFetchMode(Zend_Db::FETCH_OBJ);
872 $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
874 // $result to pojedynczy obiekt a nie tablica obiektów
875 echo $result->bug_description;
880 <sect3 id="zend.db.adapter.select.fetchone">
882 <title>Zwrócenie pojedynczej wartości ze zbioru wynikowego</title>
885 Metoda <methodname>fetchOne()</methodname> można opisać jako kombinacja
886 <methodname>fetchRow()</methodname> oraz <methodname>fetchCol()</methodname>
887 bo zwraca dane pochodzące z pierwszego wiersza zbioru wynikowego ograniczając
888 kolumny do pierwszej w wierszu. Ostatecznie zostaje zwrócona pojedyncza
889 wartość skalarna a nie tablica czy obiekt
892 <example id="zend.db.adapter.select.fetchone.example">
893 <title>Using fetchOne()</title>
894 <programlisting language="php"><![CDATA[
895 $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
897 // pojedyncza wartość string
905 <sect2 id="zend.db.adapter.write">
907 <title>Zapisywanie zmian do bazy danych</title>
910 Adaptera klasy można użyć również do zapisania nowych, bądź do zmiany
911 istniejących danych w bazie. Ta część opisuje metody włąściwe dla tych operacji.
914 <sect3 id="zend.db.adapter.write.insert">
916 <title>Dodawanie danych</title>
919 Za pomocą metody <methodname>insert()</methodname> można dodać nowe wiersze
920 do tabeli bazy danych. Jej pierwszym argumentem jest łańcuch znaków oznaczający
921 nazwę tabeli. Drugim - tablica asocjacyjna z odwzorowaniem nazw kolumn i wartości
922 jakie mają zostać w nich zapisane.
925 <example id="zend.db.adapter.write.insert.example">
926 <title>Dodawanie danych do tabeli</title>
927 <programlisting language="php"><![CDATA[
929 'created_on' => '2007-03-22',
930 'bug_description' => 'Something wrong',
931 'bug_status' => 'NEW'
934 $db->insert('bugs', $data);
939 Kolumny, które nie zostały podane w tablicy z danymi nie będą umieszczone
940 w zapytaniu na zasadzie analogicznej do użycia polecenia
941 <acronym>SQL</acronym> <acronym>INSERT</acronym>:
942 Jeśli kolumna ma podaną wartość domyślną (<acronym>DEFAULT</acronym>)
943 to ta wartość zostanie zapisana w nowym wierszu.
944 W przeciwnym przypadku kolumna nie będzie miała żadnej
945 wartości (<constant>NULL</constant>).
949 Domyślnym sposobem zapisu danych jest użycie parametrów wiązanych.
950 Dzięki temu ryzyko wystąpienia niektórych form zagrożenia
951 bezpieczeństwa aplikacji jest ograniczone.
952 W tablicy z danymi nie trzeba używać unikania
953 lub umieszczania wartości w cudzysłowiu.
957 Może wystąpić potrzeba potraktowania wartości w tablicy danych jako wyrażeń
958 <acronym>SQL</acronym>. W takim wypadku nie powinno się stosować
959 umieszczania w cudzysłowiu.
960 Domyślnie wszystkie podane wartości string są traktowane jak literały.
962 wartość jest wyrażeniem <acronym>SQL</acronym> i nie powinna zostać umieszczona w
963 cudzysłowie, należy ją podać jako obiekt klasy
964 <classname>Zend_Db_Expr</classname> zamiast
965 prostego łańcucha znaków.
968 <example id="zend.db.adapter.write.insert.example2">
969 <title>Umieszczanie wyrażeń w tabeli</title>
970 <programlisting language="php"><![CDATA[
972 'created_on' => new Zend_Db_Expr('CURDATE()'),
973 'bug_description' => 'Something wrong',
974 'bug_status' => 'NEW'
977 $db->insert('bugs', $data);
983 <sect3 id="zend.db.adapter.write.lastinsertid">
985 <title>Pobranie wygenerowanej wartości</title>
988 Niektóre systemy zarządzania bazą danych wspierają klucze pierwotne o automatycznie
989 zwiększanych wartościach. Tabela zdefiniowana w ten sposób generuje wartość klucza
990 pierwotnego automatycznie przy każdym poleceniu <acronym>INSERT</acronym>.
991 Wartością zwracaną przez metodę
992 <methodname>insert()</methodname> <emphasis>nie</emphasis> jest
993 ostatni zapisany identyfikator, ponieważ tabela mogła nie posiadać automatycznie
994 inkrementowanej kolumny.
995 Zamiast tego wartością zwrotną jest ilość zapisanych wierszy (przeważnie 1).
999 Jeśli tabela jest zdefiniowana za pomocą automatycznego klucza pierwotnego to można
1000 użyć metody <methodname>lastInsertId()</methodname>.
1001 Po udanym dodaniu wiersza metoda
1002 ta zwraca ostatnią wartość klucza wygenerowaną w ramach bieżącego połączenia.
1005 <example id="zend.db.adapter.write.lastinsertid.example-1">
1006 <title>Użycie lastInsertId() dla automatycznego klucza pierwotnego</title>
1007 <programlisting language="php"><![CDATA[
1008 $db->insert('bugs', $data);
1010 // zwrócenie ostatniej wartości wygenerowanej przez automatyczną kolumnę
1011 $id = $db->lastInsertId();
1012 ]]></programlisting>
1016 Niektóre systemy zarządzania bazą danych wspierają obiekt sekwencji, który służy
1017 do generowania unikalnych wartości, które mogą posłużyć jako klucz pierwotny.
1018 Aby obsługiwać również sekwencje metoda <methodname>lastInsertId()</methodname>
1019 akceptuje dodatkowe dwa argumenty. Pierwszym z nich jest nazwa tabeli zaś
1020 drugim - nazwa kolumny. Założona jest konwencja według której sekwencja ma nazwę
1021 składającą się z nazwy tabeli oraz kolumny do której generuje wartości z dodatkowym
1022 sufiksem "_seq". Podstawą tego założenia są domyślne ustawienia PostgreSQL.
1023 Przykładowo tabela "bugs" z kluczem pierwotnym w kolumnie "bug_id"
1024 będzie używała sekwencji o nazwie "bugs_bug_id_seq".
1027 <example id="zend.db.adapter.write.lastinsertid.example-2">
1028 <title>Użycie lastInsertId() dla sekwencji</title>
1029 <programlisting language="php"><![CDATA[
1030 $db->insert('bugs', $data);
1032 // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_bug_id_seq'
1033 $id = $db->lastInsertId('bugs', 'bug_id');
1035 // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_seq'
1036 $id = $db->lastInsertId('bugs');
1037 ]]></programlisting>
1041 Jeśli nazwa obiektu sekwencji nie podąża za tą konwencją można użyć metody
1042 <methodname>lastSequenceId()</methodname>, która przyjmuje pojedynczy łańcuch
1043 znaków - nazwę sekwencji - jako argument.
1046 <example id="zend.db.adapter.write.lastinsertid.example-3">
1047 <title>Użycie lastSequenceId()</title>
1048 <programlisting language="php"><![CDATA[
1049 $db->insert('bugs', $data);
1051 // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_id_gen'
1052 $id = $db->lastSequenceId('bugs_id_gen');
1053 ]]></programlisting>
1057 Dla systemów zarządzania bazą danych które nie wspierają sekwencji, włączając MySQL,
1058 Microsoft <acronym>SQL</acronym> Server, oraz SQLite dodatkowe argumenty podane do
1059 metody <methodname>lastInsertId()</methodname> są ignorowane a zwrócona jest
1060 ostatnia wartość wygenerowana dla dowolnej tabeli poprzez polecenie
1061 <acronym>INSERT</acronym>
1062 podczas bieżącego połączenia. Dla tych <acronym>RDBMS</acronym> metoda
1063 <methodname>lastSequenceId()</methodname> zawsze zwraca <constant>NULL</constant>.
1067 <title>Dlaczego nie należy używać "SELECT MAX(id) FROM table"?</title>
1069 Powyższe zapytanie często zwraca ostatni klucz pierwotny, jaki został zapisany
1070 w wierszu tabeli. Ten sposób nie jest jednak bezpieczny w przypadku, gdy
1071 wiele klientów zapisuje rekordy do bazy danych. Jest możliwe, że w momencie
1072 pomiędzy zapisaniem jednego rekordu a zapytaniem o
1073 <methodname>MAX(id)</methodname>, do tabeli zostanie zapisany kolejny rekord,
1074 wprowadzony przez innego użytkownika. Przez to zwrócona wartość nie będzie
1075 identyfikowała pierwszego wprowadzonego wiersza tylko drugi - wprowadzony przez
1076 inne połączenie. Nie ma pewnego sposobu na wykrycie, że do takiego zdarzenia
1080 Zastosowanie mocnej izolacji transakcji, tak jak przy trybie
1081 "repeatable read" może pomóc w ograniczeniu ryzyka wystąpienia takiej
1082 sytuacji ale niektóre systemy zarządzania bazą danych nie wspierają
1083 izolacji transakcji w wystarczającym stopniu lub aplikacja może
1084 intencjonalnie korzystać jedynie z niskiego trybu izolacji transakcji.
1088 Dodatkowo, używanie wyrażeń takich jak "MAX(id)+1" do generowania
1089 nowych wartości klucza głównego nie jest bezpieczne bo
1090 dwa połączenia mogą wykonać to zapytanie
1091 praktycznie jednocześnie i w rezultacie próbować użyć jednakowej wartości
1092 dla kolejnego polecenia <acronym>INSERT</acronym>.
1096 Wszystkie systemy zarządzania bazą danych udostępniają
1097 mechanizmy służące generowaniu
1098 unikalnych wartości oraz zwracaniu ostatniej z nich.
1099 Mechanizmy te intencjonalnie działają poza zasięgiem izolacji
1100 transakcji więc nie jest możliwe aby wartość wygenerowana dla jednego
1101 klienta pojawiła się jako ostatnia wygenerowana dla innego połączenia.
1107 <sect3 id="zend.db.adapter.write.update">
1108 <title>Aktualizacja danych</title>
1111 Aktualizacji wierszy tabeli w bazie danych można dokonać poprzez metodę adaptera
1112 <methodname>update()</methodname> . Metoda przyjmuje trzy argumenty: pierwszym
1113 jest nazwa tabeli; drugim - tablica asocjacyjna mapująca kolumny, które mają ulec
1114 zmianie oraz wartości jakie kolumny przybiorą; trzecim - warunek
1115 wyznaczający wiersze do zmiany.
1119 Wartości w tablicy z danymi są traktowane jak literały znakowe. Należy zapoznać
1120 się z akapitem <xref linkend="zend.db.adapter.write.insert" /> aby uzyskać więcej
1121 informacji na temat użyci w niej wyrażeń <acronym>SQL</acronym>.
1125 Trzecim argumentem metody jest string zawierający wyrażenie <acronym>SQL</acronym>
1126 będące kryterium wyznaczającym wiersze do zmiany. Wartości i identyfikatory w tym
1127 argumencie nie są umieszczane w cudzysłowie ani unikane. Należy, więc, zadbać o to
1128 samemu. Należy zapoznać się z akapitem <xref linkend="zend.db.adapter.quoting" />
1129 aby zasięgnąć dodatkowych informacji.
1133 Wartością zwracaną jest ilość wierszy zmienionych przez operację aktualizacji.
1136 <example id="zend.db.adapter.write.update.example">
1137 <title>Aktualizacja wierszy</title>
1138 <programlisting language="php"><![CDATA[
1140 'updated_on' => '2007-03-23',
1141 'bug_status' => 'FIXED'
1144 $n = $db->update('bugs', $data, 'bug_id = 2');
1145 ]]></programlisting>
1149 Jeśli trzeci argument nie zostanie podany to wszystkie wiersze w tabeli
1150 zostaną zaktualizowane zgodnie z kolumnami i wartościami podanymi w
1155 Jeśli trzeci argument zostanie podany jako tablica łańcuchów znakowych to
1156 w zapytaniu łańcuchy zostaną połączone za pomocą operatorów
1157 <constant>AND</constant>.
1161 Przy podaniu trzeciego argumentu jako tablicy tablic, ich wartości
1162 zostaną automatycznie
1163 otoczone cudzysłowami i umieszczone w kluczach tych tablic. Po czym zostaną
1164 połączone za pomocą operatorów <constant>AND</constant>.
1167 <example id="zend.db.adapter.write.update.example-array">
1168 <title>Aktualizacja wierszy tablicy za pomocą tablicy wyrażeń</title>
1169 <programlisting language="php"><![CDATA[
1171 'updated_on' => '2007-03-23',
1172 'bug_status' => 'FIXED'
1175 $where[] = "reported_by = 'goofy'";
1176 $where[] = "bug_status = 'OPEN'";
1178 $n = $db->update('bugs', $data, $where);
1180 // Powstałe wyrażenie SQL to:
1181 // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
1182 // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
1183 ]]></programlisting>
1186 <example id="zend.db.adapter.write.update.example-arrayofarrays">
1187 <title>Aktualizacja wierszy tablicy za pomocą tablicy tablic</title>
1188 <programlisting language="php"><![CDATA[
1190 'updated_on' => '2007-03-23',
1191 'bug_status' => 'FIXED'
1194 $where['reported_by = ?'] = 'goofy';
1195 $where['bug_status = ?'] = 'OPEN';
1197 $n = $db->update('bugs', $data, $where);
1199 // Powstałe wyrażenie SQL to:
1200 // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
1201 // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
1202 ]]></programlisting>
1206 <sect3 id="zend.db.adapter.write.delete">
1207 <title>Usuwanie danych</title>
1209 Usuwania danych można dokonać używając metody <methodname>delete()</methodname>.
1210 Przyjmuje ona dwa argumenty: pierwszym z nich jest łańcuch znaków z nazwą tabeli;
1211 Drugim - warunek określający wiersze do usunięcia.
1215 Drugi argument to string zawierający wyrażenie <acronym>SQL</acronym> użyte jako
1216 kryterium wyznaczania usuwanych wierszy. Wartości i identyfikatory nie są
1217 unikane ani umieszczane w cudzysłowie - należy zatroszczyć się o to samemu. Aby
1218 dowiedzieć się więcej na ten temat
1219 można skorzystać z akapitu <xref linkend="zend.db.adapter.quoting" />.
1223 Wartość zwrotna to ilość wierszy, jakie uległy zmianie w wyniku zadziałania
1227 <example id="zend.db.adapter.write.delete.example">
1228 <title>Usuwanie wierszy</title>
1229 <programlisting language="php"><![CDATA[
1230 $n = $db->delete('bugs', 'bug_id = 3');
1231 ]]></programlisting>
1235 Jeśli drugi argument nie zostanie podany to wszystkie wiersze z tabeli
1240 Jeśli drugi argument zostanie podany jako tablica łańcuchów znaków to
1241 te łańcuchy ulegną konkatenacji jako wyrażenia logiczne połączone
1242 operatorem <constant>AND</constant>.
1246 Jeśli trzeci argument będzie tablicą tablic to jej wartości zostaną
1247 automatycznie otoczone cudzysłowami i umieszczona w kluczach tablic. Potem
1248 zostaną połączone razem za pomocą operatora <constant>AND</constant>.
1255 <sect2 id="zend.db.adapter.quoting">
1257 <title>Umieszczanie wartości i identyfikatorów w cudzysłowie</title>
1260 Podczas tworzenia zapytań <acronym>SQL</acronym> często dochodzi do sytuacji, w której
1261 niezbędne jest umieszczenie wartości zmiennych <acronym>PHP</acronym> w wyrażeniach
1262 <acronym>SQL</acronym>. Stanowi to zagrożenie, ponieważ jeśli wartość
1263 łańcuchowej zmiennej <acronym>PHP</acronym> zawiera określone znaki, takie jak symbol
1264 cudzysłowu, to mogą one spowodować błąd w poleceniu <acronym>SQL</acronym>. Poniżej
1265 znajduje się przykład zapytania zawierającego niespójną liczbę symboli cudzysłowu:
1266 <programlisting language="php"><![CDATA[
1268 $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
1271 // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
1272 ]]></programlisting>
1278 Zagrożenie potęguje fakt iż podobne błędy mogą zostać wykorzystane przez osobę
1279 próbującą zmanipulować działanie funkcji aplikacji. Jeśli takiej osobie
1280 uda się wpłynąć na wartość zmiennej <acronym>PHP</acronym> poprzez
1281 parametr <acronym>HTTP</acronym>
1282 (bądź inny mechanizm), to będzie mogła zmienić zapytanie <acronym>SQL</acronym>
1283 tak by dokonywało operacji zupełnie niezamierzonych przez twórców, takich jak
1284 zwrócenie danych, do których osoba nie powinna mieć dostępu. To jest poważny i szeroko
1285 rozpowszechniony sposób łamania zabezpieczeń aplikacji znany pod nazwą "SQL Injection"
1286 (wstrzyknięcie SQL - <ulink url="http://en.wikipedia.org/wiki/SQL_Injection">
1287 http://en.wikipedia.org/wiki/SQL_Injection</ulink>).
1291 Adaptery klasy <classname>Zend_Db</classname> udostępniają funkcje przydatne
1292 do zredukowania zagrożenia atakiem <acronym>SQL</acronym> Injection w kodzie
1293 <acronym>PHP</acronym>.
1294 Przyjętym rozwiązaniem jest unikanie znaków specjalnych takich jak cudzysłów w
1295 wartościach zmiennych <acronym>PHP</acronym>
1296 przed umieszczeniem ich w poleceniu <acronym>SQL</acronym>.
1297 Takie podejście zapewnia ochronę przed przypadkową jak i intencjonalną zmianą
1298 znaczenia poleceń <acronym>SQL</acronym> przez
1299 zmienne <acronym>PHP</acronym> zawierające znaki specjalne.
1302 <sect3 id="zend.db.adapter.quoting.quote">
1304 <title>Użycie quote()</title>
1307 Metoda <methodname>quote()</methodname> przyjmuje pojedynczy
1308 argument - łańcuch znaków.
1309 Na wyjściu zwraca podany argument ze wszystkimi znakami specjalnymi
1310 poddanymi uniknięciu w sposób właściwy dla używanego
1311 <acronym>RDBMS</acronym> i otoczony znakami ograniczającymi
1312 łańcuchy znakowe. Standardowym znakiem ograniczającym
1313 stringi w <acronym>SQL</acronym> jest pojedynczy cudzysłów (').
1316 <example id="zend.db.adapter.quoting.quote.example">
1317 <title>Użycie quote()</title>
1318 <programlisting language="php"><![CDATA[
1319 $name = $db->quote("O'Reilly");
1323 $sql = "SELECT * FROM bugs WHERE reported_by = $name";
1326 // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
1327 ]]></programlisting>
1331 Należy zwrócić uwagę, że wartość zwrotna metody <methodname>quote()</methodname>
1332 zawiera znaki ograniczające stringi. Jest to zachowanie różne od niektórych funkcji
1333 które unikają specjalne znaki ale nie ujmują całego łańcucha w znaki ograniczające,
1334 tak jak <ulink url="http://www.php.net/mysqli_real_escape_string">
1335 mysql_real_escape_string()</ulink>.
1339 Wartości mogą wymagać umieszczenia w cudzysłowach lub nie, zgodnie z
1340 kontekstem używanego typu danych <acronym>SQL</acronym>.
1341 W przypadku niektórych rodzajów systemów zarządzania
1342 bazą danych liczby całkowite nie mogą być ograniczane cudzysłowami
1343 jeśli są porównywane z kolumną lub wyrażeniem zwracającym inną liczbę całkowitą.
1344 Innymi słowy, poniższy zapis może wywołać błąd w niektórych
1345 implementacjach <acronym>SQL</acronym> zakładając, że
1346 <property>intColumn</property> jest określona
1347 typem danych <constant>INTEGER</constant>.
1349 <programlisting language="php"><![CDATA[
1350 SELECT * FROM atable WHERE intColumn = '123'
1351 ]]></programlisting>
1355 Można użyć opcjonalnego, drugiego argumentu metody <methodname>quote()</methodname>
1356 aby określić typ danych <acronym>SQL</acronym> i ograniczyć stosowanie cudzysłowu.
1359 <example id="zend.db.adapter.quoting.quote.example-2">
1360 <title>Użycie quote() z podanym typem danych SQL</title>
1362 <programlisting language="php"><![CDATA[
1364 $sql = 'SELECT * FROM atable WHERE intColumn = '
1365 . $db->quote($value, 'INTEGER');
1366 ]]></programlisting>
1370 Każda klasa <classname>Zend_Db_Adapter</classname> ma zapisane nazwy numerycznych
1371 typów danych <acronym>SQL</acronym> odpowiednio do swojego rodzaju
1372 <acronym>RDBMS</acronym>.
1373 Zamiast tego można w tym miejscu również korzystać ze stałych
1374 <constant>Zend_Db::INT_TYPE</constant>,
1375 <constant>Zend_Db::BIGINT_TYPE</constant> oraz
1376 <constant>Zend_Db::FLOAT_TYPE</constant> aby uniezależnić kod
1377 od rodzaju bazy danych.
1381 <classname>Zend_Db_Table</classname> automatycznie określa
1382 typy danych <acronym>SQL</acronym>
1383 dla metody <methodname>quote()</methodname> podczas generowania
1384 zapytań <acronym>SQL</acronym> odnoszących się do klucza pierwotnego tabeli.
1389 <sect3 id="zend.db.adapter.quoting.quote-into">
1391 <title>Użycie quoteInto()</title>
1394 Najbardziej typowym przypadkiem użycia cudzysłowu do ograniczania zmiennych jest
1395 umieszczenie zmiennej <acronym>PHP</acronym> w zapytaniu <acronym>SQL</acronym>.
1396 Aby to osiągnąć można użyć metody <methodname>quoteInto()</methodname>.
1397 Przyjmuje ona dwa argumenty: pierwszym jest łańcuch znaków zawierający
1398 symbol "?", który zostanie zastąpiony; drugim jest zmienna
1399 <acronym>PHP</acronym>, która ma trafić na miejsce "?".
1403 Zastępowany symbol jest używany przez wielu producentów baz danych do oznaczenia
1404 pozycyjnych parametrów wiązanych ale metoda <methodname>quoteInto()</methodname>
1405 jedynie emuluje takie parametry. W wyniku jej działania wartość zmiennej jest
1406 zwyczajnie umieszczana w łańcuchu z zapytaniem, po wstępnym uniknięciu specjalnych
1407 znaków i umieszczeniu w cudzysłowie. Prawdziwa implementacja parametrów wiązanych
1408 zakłada separację łańcucha znaków polecenia <acronym>SQL</acronym> od samych
1409 parametrów oraz wstępne parsowanie polecenia na serwerze bazy danych.
1412 <example id="zend.db.adapter.quoting.quote-into.example">
1413 <title>Użycie quoteInto()</title>
1414 <programlisting language="php"><![CDATA[
1415 $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
1418 // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
1419 ]]></programlisting>
1423 Można użyć opcjonalnego, trzeciego parametru metody
1424 <methodname>quoteInto()</methodname>
1425 aby określić typ danych <acronym>SQL</acronym>.
1426 Numeryczne typy danych (w przeciwieństwie
1427 do innych typów) nie podlegają umieszczaniu w cudzysłowie.
1430 <example id="zend.db.adapter.quoting.quote-into.example-2">
1431 <title>Użycie quoteInto() z podaniem typu danych SQL</title>
1432 <programlisting language="php"><![CDATA[
1434 ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
1437 // SELECT * FROM bugs WHERE reported_by = 1234
1438 ]]></programlisting>
1442 <sect3 id="zend.db.adapter.quoting.quote-identifier">
1444 <title>Użycie quoteIdentifier()</title>
1447 Wartości nie są jedyną częścią składni polecenia <acronym>SQL</acronym>, która może
1448 być zmienna. W przypadku użycia zmiennych <acronym>PHP</acronym> do określenia
1449 tabel, kolumn lub innych identyfikatorów zapytania <acronym>SQL</acronym>,
1450 może zajść potrzeba umieszczenia również tych elementów w cudzysłowie.
1451 Domyślnie identyfikatory <acronym>SQL</acronym> muszą przestrzegać określonych
1452 reguł - podobnie jak w <acronym>PHP</acronym> oraz większości innych
1453 języków programowania. Przykładem takiej reguły jest zakaz używania spacji
1454 lub określonych znaków interpunkcyjnych, specjalnych ani też znaków spoza ASCII.
1455 Poza tym istnieje lista określonych słów, które służą
1456 do tworzenia zapytań - ich też nie powinno się używać jako identyfikatorów.
1460 Mimo to <acronym>SQL</acronym> posiada
1461 <emphasis>ograniczone identyfikatory</emphasis> (delimited identifiers),
1462 dzięki którym można skorzystać z większego wachlarza znaków
1463 do nazywania obiektów.
1464 Jeśli określony identyfikator zostanie ograniczony odpowiednim
1465 rodzajem cudzysłowu to będzie można użyć znaków, które bez tego ograniczenia
1466 spowodowałyby błąd. Identyfikatory ograniczone mogą zawierać spacje,
1467 znaki interpunkcyjne czy lokalne litery.
1468 Można nawet używać zarezerwowanych słów <acronym>SQL</acronym> jeśli
1469 zostaną otoczone odpowiednimi znakami ograniczającymi.
1473 Metoda <methodname>quoteIdentifier()</methodname> zachowuje się podobnie jak
1474 <methodname>quote()</methodname> ale otacza podany łańcuch znaków za pomocą
1475 znaków ograniczających zgodnie z rodzajem używanego adaptera.
1476 Standardowy <acronym>SQL</acronym>
1477 używa podwójnego cudzysłowu (") jako znaku ograniczającego a większość systemów
1478 zarządzania bazą danych podąża za tym przykładem. MySQL domyślnie używa znaków
1479 back-tick (`). Metoda <methodname>quoteIdentifier()</methodname> dokonuje również
1480 unikania znaków specjalnych znajdujących się w przekazanym argumencie.
1483 <example id="zend.db.adapter.quoting.quote-identifier.example">
1484 <title>Użycie quoteIdentifier()</title>
1485 <programlisting language="php"><![CDATA[
1486 // można użyć tabeli o nazwie takiej samej jak słowo zarezerwowane SQL
1487 $tableName = $db->quoteIdentifier("order");
1489 $sql = "SELECT * FROM $tableName";
1492 // SELECT * FROM "order"
1493 ]]></programlisting>
1497 W <acronym>SQL</acronym> identyfikatory ograniczone są wrażliwe na wielkość liter,
1498 w przeciwieństwie do zwykłych identyfikatorów. Przez to, należy upewnić się, że
1499 pisownia identyfikatora w 100% odpowiada pisowni zapisanej w schemacie, włącznie
1504 W większości przypadków gdzie polecenie <acronym>SQL</acronym> jest
1505 generowane wewnątrz klas <classname>Zend_Db</classname>,
1506 domyślnym zachowaniem jest automatyczne ograniczanie
1507 identyfikatorów. Można to zmienić poprzez opcję
1508 <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> wywoływaną
1509 podczas inicjalizacji adaptera.
1511 <xref linkend="zend.db.adapter.connecting.parameters.example2" />.
1518 <sect2 id="zend.db.adapter.transactions">
1520 <title>Kontrolowanie transakcji bazy danych</title>
1523 W świecie baz danych transakcja to zbiór operacji, który może zostać zapisany
1524 bądź cofnięty za pomocą jednej instrukcji, nawet jeśli zmiany wynikające z tych operacji
1525 dotyczyły wielu tabel. Wszystkie zapytania do bazy danych są przeprowadzane w
1526 kontekście transakcji. Jeśli nie są zarządzane jawnie to sterownik bazy danych używa ich
1527 w sposób przezroczysty dla użytkownika. Takie podejście nazywa się trybem
1528 <emphasis>auto-commit</emphasis> - sterownik bazy danych tworzy transakcje dla każdego
1529 tworzonego polecenia i zapisuje efekty jego działania po każdym wywołaniu polecenia
1530 <acronym>SQL</acronym>. Domyślnie wszystkie adaptery <classname>Zend_Db</classname>
1531 działają w trybie <emphasis>auto-commit</emphasis>.
1535 Można również bezpośrednio wskazać początek i koniec transakcji i w ten sposób
1536 kontrolować ilość zapytań <acronym>SQL</acronym> jakie trafiają do zapisania (bądź
1537 cofnięcia) jako pojedyncza operacja. Aby rozpocząć transakcję należy wywołać metodę
1538 <methodname>beginTransaction()</methodname>. Następujące po niej polecenia
1539 <acronym>SQL</acronym> są wykonywane w kontekście wspólnej transakcji do momentu
1540 zasygnalizowania jej końca.
1544 Aby zakończyć transakcję należy użyć metody <methodname>commit()</methodname> lub
1545 <methodname>rollBack()</methodname>.
1546 Pierwsza z nich powoduje zapisanie zmian wynikających
1547 z operacji przeprowadzonych w czasie transakcji.
1548 Oznacza to, że efekty tych zmian będą
1549 widoczne w wynikach zapytań wywołanych w ramach innych transakcji.
1553 Metoda <methodname>rollBack()</methodname> dokonuje odwrotnej operacji: cofa zmiany
1554 dokonane podczas transakcji.
1555 W efekcie wszystkie dane zmienione podczas transakcji zostają cofnięte do
1556 wartości z momentu przed jej rozpoczęciem. Cofnięcie zmian jednej transakcji nie
1557 ma wpływu na zmiany dokonane przez inną transakcję trwającą nawet w tym samym czasie.
1561 Po skończonej transakcji <classname>Zend_Db_Adapter</classname> wraca
1562 do trybu auto-commit do momentu ponownego wywołania metody
1563 <methodname>beginTransaction()</methodname> i ręcznego
1564 rozpoczęcia nowej transakcji.
1567 <example id="zend.db.adapter.transactions.example">
1568 <title>Kontrolowanie transakcjami dla zachowania spójności</title>
1569 <programlisting language="php"><![CDATA[
1570 // Ręczne rozpoczęcie transakcji
1571 $db->beginTransaction();
1574 // Próba wywołania jednego bądź wielu zapytań:
1579 // Jeśli wszystkie odniosły sukces - zapisanie transakcji, dzięki czemu wszystkie rezultaty
1580 // zostaną zapisane za jednym razem.
1583 } catch (Exception $e) {
1584 // Jeśli któreś z zapytań zakończyło się niepowodzeniem i został wyrzucony wyjątek, należy
1585 // cofnąć całą transakcję odwracając zmiany w niej dokonane (nawet te które zakończyły się
1586 // sukcesem). Przez to albo wszystkie zmiany zostają zapisane albo żadna.
1588 echo $e->getMessage();
1590 ]]></programlisting>
1595 <sect2 id="zend.db.adapter.list-describe">
1597 <title>Uzyskiwanie listy i opisu tabel</title>
1600 Metoda <methodname>listTables()</methodname> zwraca tablicę łańcuchów znakowych,
1601 zawierającą wszystkie tabele w bieżącej bazie danych.
1605 Metoda <methodname>describeTable()</methodname> zwraca tablicę asocjacyjną metadanych
1606 tabeli. Jako argument należy podać nazwę tabeli.
1607 Drugi argument jest opcjonalny - wskazuje
1608 nazwę schematu w którym tabela się znajduje.
1612 Kluczami zwracanej tablicy asocjacyjnej są nazwy kolumn tabeli. Wartość przy każdej
1613 kolumnie to następna tablica asocjacyjna z następującymi kluczami i wartościami:
1616 <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
1617 <title>Metadane zwracane przez describeTable()</title>
1618 <tgroup cols="3" align="left" colsep="1" rowsep="1">
1621 <entry>Klucz</entry>
1628 <entry><constant>SCHEMA_NAME</constant></entry>
1629 <entry>(string)</entry>
1630 <entry>Nazwa schematu bazy danych, w którym tabela się znajduje.</entry>
1633 <entry><constant>TABLE_NAME</constant></entry>
1634 <entry>(string)</entry>
1635 <entry>Nazwa tabeli zawierającej daną kolumnę.</entry>
1638 <entry><constant>COLUMN_NAME</constant></entry>
1639 <entry>(string)</entry>
1640 <entry>Nazwa kolumny.</entry>
1643 <entry><constant>COLUMN_POSITION</constant></entry>
1644 <entry>(integer)</entry>
1645 <entry>Liczba porządkowa wskazująca na miejsce kolumny w tabeli.</entry>
1648 <entry><constant>DATA_TYPE</constant></entry>
1649 <entry>(string)</entry>
1650 <entry>Nazwa typu danych dozwolonych w kolumnie.</entry>
1653 <entry><constant>DEFAULT</constant></entry>
1654 <entry>(string)</entry>
1655 <entry>Domyślna wartość kolumny (jeśli istnieje).</entry>
1658 <entry><constant>NULLABLE</constant></entry>
1659 <entry>(boolean)</entry>
1661 <constant>TRUE</constant> jeśli columna dopuszcza wartości
1662 <acronym>SQL</acronym>
1663 <constant>NULL</constant>, <constant>FALSE</constant>
1664 jeśli kolumna zawiera
1665 ograniczenie <constant>NOT</constant> <constant>NULL</constant>.
1669 <entry><constant>LENGTH</constant></entry>
1670 <entry>(integer)</entry>
1672 Dopuszczalny rozmiar kolumny, w formie zgłoszonej przez serwer
1677 <entry><constant>SCALE</constant></entry>
1678 <entry>(integer)</entry>
1680 Skala typów <acronym>SQL</acronym> NUMERIC lub
1681 <constant>DECIMAL</constant>.
1685 <entry><constant>PRECISION</constant></entry>
1686 <entry>(integer)</entry>
1688 Precyzja typów <acronym>SQL</acronym> NUMERIC
1689 lub <constant>DECIMAL</constant>.
1693 <entry><constant>UNSIGNED</constant></entry>
1694 <entry>(boolean)</entry>
1697 <constant>TRUE</constant> jeśli typ danych liczbowych ma klauzulę
1698 <constant>UNSIGNED</constant>.
1702 <entry><constant>PRIMARY</constant></entry>
1703 <entry>(boolean)</entry>
1706 <constant>TRUE</constant> jeśli kolumna jest częścią
1707 klucza pierwotnego tabeli.
1711 <entry><constant>PRIMARY_POSITION</constant></entry>
1712 <entry>(integer)</entry>
1714 Liczba porządkowa (min. 1) oznaczająca pozycję
1715 kolumny w kluczu pierwotnym.
1719 <entry><constant>IDENTITY</constant></entry>
1720 <entry>(boolean)</entry>
1723 <constant>TRUE</constant> jeśli kolumna korzysta
1724 z wartości automatycznie generowanych.
1732 <title>Pole metadanych IDENTITY w różnych systemach zarządzania bazą danych</title>
1734 Pole metadanych IDENTITY zostało wybrane jako ogólny
1735 termin określający relację do klucza tabeli. Może być znany
1736 pod następującymi nazwami:
1741 <constant>IDENTITY</constant> - DB2, MSSQL
1746 <constant>AUTO_INCREMENT</constant> - MySQL
1751 <constant>SERIAL</constant> - PostgreSQL
1756 <constant>SEQUENCE</constant> - Oracle
1763 Jeśli w bazie danych nie istnieje tabela i schemat o podanych nazwach to
1764 <methodname>describeTable()</methodname> zwraca pustą tablicę.
1769 <sect2 id="zend.db.adapter.closing">
1771 <title>Zamykanie połączenia</title>
1774 Najczęściej nie ma potrzeby zamykać połączenia z bazą danych. <acronym>PHP</acronym>
1775 automatycznie czyści wszystkie zasoby pod koniec działania. Rozszerzenia bazy danych są
1776 zaprojektowane w taki sposób aby połączenie zostało zamknięte w momencie usunięcia
1777 referencji do obiektu zasobu.
1781 Jednak w przypadku skryptu <acronym>PHP</acronym>, którego czas wykonania jest znaczący,
1782 który inicjuje wiele połączeń z bazą danych, może zajść potrzeba
1783 ręcznego zamknięcia połączenia aby ograniczyć wykorzystanie
1784 zasobów serwera bazy danych. Aby wymusić zamknięcie połączenia
1785 z bazą danych należy użyć metody adaptera <methodname>closeConnection()</methodname>.
1789 Od wersji 1.7.2 istnieje możliwość sprawdzenia czy w obecnej chwili
1790 połączenie z serwerem bazy danych występuje za pomocą metody
1791 <methodname>isConnected()</methodname>.
1792 Jej rezultat oznacza czy zasób połączenia został ustanowiony i nie został zamknięty.
1793 Ta metoda nie jest zdolna sprawdzić zamknięcia połączenia od strony
1794 serwera bazy danych.
1795 Dzięki użyciu jej w wewnętrznych metodach zamykających połączenie
1796 można dokonywać wielokrotnego zamknięcia połączenia bez ryzyka wystąpienia błędów.
1797 Przed wersją 1.7.2 było to możliwe jedynie w
1798 przypadku adapterów <acronym>PDO</acronym>.
1801 <example id="zend.db.adapter.closing.example">
1802 <title>Zamknięcie połączenia z bazą danych</title>
1803 <programlisting language="php"><![CDATA[
1804 $db->closeConnection();
1805 ]]></programlisting>
1809 <title>Czy Zend_Db wspiera połączenia trwałe (Persistent Connections)?</title>
1811 Tak, trwałe połączenia są wspierane poprzez flagę <property>persistent</property>
1812 ustawioną na wartość <constant>TRUE</constant> w konfiguracji
1813 adaptera <classname>Zend_Db</classname> (a nie sterownika bazy danych).
1816 <example id="zend.db.adapter.connecting.persistence.example">
1817 <title>Użycie flagi stałego połączenia z adapterem Oracle</title>
1818 <programlisting language="php"><![CDATA[
1819 $db = Zend_Db::factory('Oracle', array(
1820 'host' => '127.0.0.1',
1821 'username' => 'webuser',
1822 'password' => 'xxxxxxxx',
1824 'persistent' => true
1826 ]]></programlisting>
1830 Należy zwrócić uwagę, że używanie połączeń stałych może zwiększyć ilość
1831 nieużywanych połączeń na serwerze bazy danych. Przez to, korzyści
1832 w wydajności (wynikające z wykluczenia potrzeby nawiązywania połączenia
1833 przy każdym żądaniu) mogą zostać skutecznie przeważone przez problemy
1834 spowodowane przez tą technikę.
1837 Połączenia z bazą danych mają stany. Oznacza to, że pewne obiekty na serwerze
1838 bazy danych istnieją w kontekście sesji. Chodzi o blokady, zmienne użytkownika,
1839 tabele tymczasowe, informacje o ostatnio wykonanym zapytaniu - takie jak
1840 ilość pobranych wierszy, ostatnia wygenerowana wartość identyfikatora. W
1841 przypadku użycia połączeń stałych istnieje ryzyko, że aplikacja uzyska
1842 dostęp do niepoprawnych bądź zastrzeżonych danych, które zostały utworzone
1843 podczas poprzedniego żądania.
1846 W obecnym stanie jedynie adaptery Oracle, DB2 oraz <acronym>PDO</acronym>
1847 (zgodnie z dokumentacją <acronym>PHP</acronym>) wspierają połączenia stałe
1848 w <classname>Zend_Db</classname>.
1854 <sect2 id="zend.db.adapter.other-statements">
1856 <title>Wykonywanie innych poleceń na bazie danych</title>
1859 Podczas tworzenia kodu może zajść potrzeba uzyskania dostępu bezpośrednio do
1860 obiektu połączenia tak jak udostępnia to używane rozszerzenie bazy danych
1861 <acronym>PHP</acronym>. Niektóre rozszerzenia mogą oferować funkcje nieodzwierciedlone
1862 w metodach klasy <classname>Zend_Db_Adapter_Abstract</classname>.
1866 Wszystkie polecenia <acronym>SQL</acronym> w <classname>Zend_Db</classname>
1867 są wywoływane poprzez instrukcje preparowane (prepared statement). Jednak niektóre
1868 funkcje bazy danych są z nimi niekompatybilne. Polecenia <acronym>DDL</acronym> takie
1869 jak CREATE czy ALTER nie mogą być wywoływane w ten sposób w MySQL. Dodatkowo polecenia
1870 <acronym>SQL</acronym> nie korzystają z
1871 <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">cache'u zapytań
1872 MySQL (MySQL Query Cache)</ulink> dla wersji wcześniejszej niż MySQL 5.1.17.
1876 Większość rozszerzeń baz danych <acronym>PHP</acronym> umożliwia wywoływanie poleceń
1877 <acronym>SQL</acronym> bez preparowania. W przypadku <acronym>PDO</acronym> jest to
1878 możliwe poprzez metodę <methodname>exec()</methodname>. Aby uzyskać dostęp do obiektu
1879 połączenia odpowiedniego rozszerzenia <acronym>PHP</acronym> należy wywołać metodę
1880 <methodname>getConnection()</methodname>.
1883 <example id="zend.db.adapter.other-statements.example">
1884 <title>Wywołanie polecenia niepreparowanego dla adaptera PDO</title>
1885 <programlisting language="php"><![CDATA[
1886 $result = $db->getConnection()->exec('DROP TABLE bugs');
1887 ]]></programlisting>
1891 W podobny sposób można korzystać z innych metod szczególnych dla konkretnego
1892 rozszerzenia <acronym>PHP</acronym>. Należy jednak mieć w pamięci, iż w ten
1893 sposób ogranicza się tworzoną aplikację do współpracy z interfejsem oferowanym
1894 jedynie przez konkretne rozszerzenie konkretnej bazy danych.
1898 W przyszłych wersjach <classname>Zend_Db</classname> planowane jest umieszczanie
1899 dodatkowych metod służących do obejmowania funkcjonalności wspólnych dla wielu
1900 rozszerzeń baz danych <acronym>PHP</acronym> ale wsteczna kompatybilność zostanie
1906 <sect2 id="zend.db.adapter.server-version">
1907 <title>Pobranie wersji serwera</title>
1910 Począwszy od wersji 1.7.2 można pobrać wersję serwera bazy danych w formie podobnej do
1911 numeru wersji <acronym>PHP</acronym> tak aby można było skorzystać z funkcji
1912 <methodname>version_compare()</methodname>. Jeśli taka informacja nie jest dostępna
1913 to zostanie zwrócona wartość <constant>NULL</constant>.
1916 <example id="zend.db.adapter.server-version.example">
1917 <title>Weryfikacja wersji serwera przed wywołaniem zapytania</title>
1918 <programlisting language="php"><![CDATA[
1919 $version = $db->getServerVersion();
1920 if (!is_null($version)) {
1921 if (version_compare($version, '5.0.0', '>=')) {
1922 // wykonanie zapytania
1924 // wykonanie innego zapytania
1927 // wersja serwera niedostępna
1929 ]]></programlisting>
1933 <sect2 id="zend.db.adapter.adapter-notes">
1935 <title>Informacje o konkretnych adapterach</title>
1938 Ten akapit wymienia różnice pomiędzy klasami adapterów, z istnienia których
1939 należy sobie zdawać sprawę.
1942 <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
1943 <title>IBM DB2</title>
1947 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
1948 należy użyć nazwy 'Db2'.
1953 Ten adapter używa rozszerzenia <acronym>PHP</acronym> ibm_db2.
1958 IBM DB2 wspiera sekwencje oraz klucze automatycznie zwiększające.
1959 Przez to argumenty dla <methodname>lastInsertId()</methodname> są
1960 opcjonalne. Jeśli nie poda się argumentów adapter zwróci ostatnią
1961 wartość wygenerowaną dla klucza automatycznego. Jeśli argumenty zostaną
1962 podane to adapter zwróci ostatnią wartość wygenerowaną przez sekwencję
1963 o nazwie zgodnej z konwencją
1964 '<emphasis>tabela</emphasis>_<emphasis>kolumna</emphasis>_seq'.
1970 <sect3 id="zend.db.adapter.adapter-notes.mysqli">
1971 <title>MySQLi</title>
1975 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
1976 należy użyć nazwy 'Mysqli'.
1981 Ten adapter używa rozszerzenia <acronym>PHP</acronym> mysqli.
1986 MySQL nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
1987 ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
1988 automatycznego. Metoda <methodname>lastSequenceId()</methodname>
1989 zwraca <constant>NULL</constant>.
1995 <sect3 id="zend.db.adapter.adapter-notes.oracle">
1996 <title>Oracle</title>
2000 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2001 należy użyć nazwy 'Oracle'.
2006 Ten adapter używa rozszerzenia <acronym>PHP</acronym> oci8.
2011 Oracle nie wspiera kluczy automatycznych więc należy podać nazwę
2012 sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
2013 <methodname>lastSequenceId()</methodname>.
2018 Rozszerzenie Oracle nie wspiera parametrów pozycyjnych. Należy
2019 używać nazwanych parametrów.
2024 Obecnie, opcja <constant>Zend_Db::CASE_FOLDING</constant> nie jest
2025 zaimplementowana w tym adapterze. Aby użyć tej opcji z Oracle zalecane
2026 jest korzystanie z adaptera <acronym>PDO</acronym> OCI.
2031 Domyślnie pola LOB są zwracane jako obiekty OCI-Lob. Można ustawić
2032 pobieranie ich w formie łańcuchów znakowych dla wszystkich żądań
2033 poprzez opcję sterownika '<property>lob_as_string</property>'. Aby
2034 jednorazowo pobrać obiekt Lob jako string należy użyć metody
2035 <methodname>setLobAsString(boolean)</methodname> na adapterze lub
2036 na obiekcie zapytania.
2042 <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
2043 <title>Microsoft SQL Server</title>
2047 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2048 należy użyć nazwy 'Sqlsrv'.
2053 Ten adapter używa rozszerzenia <acronym>PHP</acronym> sqlsrv.
2058 Microsoft <acronym>SQL</acronym> Server nie wspiera sekwencji więc
2059 <methodname>lastInsertId()</methodname> ignoruje argument określający
2060 klucz pierwotny i zwraca ostatnią wartość wygenerowaną przez automatyczny
2061 klucz (jeśli jest podana nazwa tabeli) lub identyfikator zwrócony przez
2062 ostatnie polecenie INSERT. Metoda <methodname>lastSequenceId()</methodname>
2063 zwraca <constant>NULL</constant>.
2068 <classname>Zend_Db_Adapter_Sqlsrv</classname> ustawia opcję
2069 <constant>QUOTED_IDENTIFIER ON</constant> bezpośrednio po połączeniu się
2070 z bazą danych <acronym>SQL</acronym> Server. To powoduje, że sterownik
2071 zaczyna używać standardowego znaku cudzysłowu (<emphasis>"</emphasis>) jako
2072 ograniczenia identyfikatorów zamiast - charakterystycznych dla produktu
2073 Microsoftu - nawiasów kwadratowych.
2078 Jednym z kluczy podawanych do tablicy opcji może być
2079 <property>driver_options</property>
2080 dzięki czemu można skorzystać z wartości podanych w dokumentacji
2081 <acronym>SQL</acronym> Server
2082 <ulink url="http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx">
2083 http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx</ulink>.
2088 Dzięki metodzie <methodname>setTransactionIsolationLevel()</methodname>
2089 można ustawić poziom izolacji transakcji dla bieżącego połączenia.
2090 Rozpoznawane wartości
2091 to <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>,
2092 <constant>SQLSRV_TXN_READ_COMMITTED</constant>,
2093 <constant>SQLSRV_TXN_REPEATABLE_READ</constant>,
2094 <constant>SQLSRV_TXN_SNAPSHOT</constant> or
2095 <constant>SQLSRV_TXN_SERIALIZABLE</constant>.
2100 Począwszy od Zend Framework 1.9 minimalną wspieraną wersją rozszerzenia
2101 <acronym>PHP</acronym> Microsoft <acronym>SQL</acronym> Server jest
2102 1.0.1924.0. a dla <acronym>MSSQL</acronym> Server Native
2103 Client - wersja 9.00.3042.00.
2109 <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
2110 <title>PDO dla IBM DB2 oraz Informix Dynamic Server (IDS)</title>
2114 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2115 należy użyć nazwy '<classname>Pdo_Ibm</classname>'.
2120 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_ibm.
2125 Należy używać wersji 1.2.2 lub wyższej rozszerzenia PDO_IBM. Zaleca się
2126 uaktualnienie wcześniejszych wersji poprzez <acronym>PECL</acronym>.
2132 <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
2133 <title>PDO Microsoft SQL Server</title>
2137 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2138 należy użyć nazwy '<classname>Pdo_Mssql</classname>'.
2143 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_dblib.
2148 Microsoft <acronym>SQL</acronym> Server nie wspiera sekwencji więc
2149 <methodname>lastInsertId()</methodname> ignoruje argument określający
2150 klucz pierwotny i zwraca ostatnią wartość wygenerowaną przez automatyczny
2151 klucz (jeśli jest podana nazwa tabeli) lub identyfikator zwrócony przez
2152 ostatnie polecenie INSERT. Metoda <methodname>lastSequenceId()</methodname>
2153 zwraca <constant>NULL</constant>.
2158 W przypadku pracy z łańcuchami znaków unicode zakodowanych w sposób inny
2159 niż UCS-2 (czyli również w formie UTF-8), może zajść potrzeba dokonania
2160 konwersji w kodzie aplikacji lub przechowywania
2161 danych w kolumnach binarnych.
2162 Aby uzyskać więcej informacji można skorzystać z
2163 <ulink url="http://support.microsoft.com/kb/232580">Microsoft's Knowledge
2169 <classname>Zend_Db_Adapter_Pdo_Mssql</classname> ustawia opcję
2170 <constant>QUOTED_IDENTIFIER ON</constant> bezpośrednio po połączeniu się
2171 z bazą danych <acronym>SQL</acronym> Server. To powoduje, że sterownik
2172 zaczyna używać standardowego znaku cudzysłowu (<emphasis>"</emphasis>) jako
2173 ograniczenia identyfikatorów zamiast - charakterystycznych dla produktu
2174 Microsoftu - nawiasów kwadratowych.
2179 Adapter rozpoznaje klucz <property>pdoType</property> w tablicy opcji. Jego
2180 wartość może wynosić "mssql" (domyślnie), "dblib", "freetds", lub "sybase".
2181 To wpływa na prefiks <acronym>DSN</acronym> używany przez
2182 adapter do utworzenia łańcucha połączenia.
2183 Wartości "freetds" oraz "sybase" powodują utworzenie prefiksu
2184 "sybase:" używanego przez biblioteki
2185 <ulink url="http://www.freetds.org/">FreeTDS</ulink>.
2186 Należy zapoznać się z informacjami dotyczącymi prefiksów
2187 <acronym>DSN</acronym>
2188 używanymi przez ten sterownik pod adresem
2189 <ulink url="http://www.php.net/manual/en/ref.pdo-dblib.connection.php">
2190 http://www.php.net/manual/en/ref.pdo-dblib.connection.php</ulink>
2196 <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
2197 <title>PDO MySQL</title>
2201 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2202 należy użyć nazwy '<classname>Pdo_Mysql</classname>'.
2207 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_mysql.
2212 MySQL nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
2213 ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
2214 automatycznego. Metoda <methodname>lastSequenceId()</methodname>
2215 zwraca <constant>NULL</constant>.
2221 <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
2222 <title>PDO Oracle</title>
2226 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2227 należy użyć nazwy '<classname>Pdo_Oci</classname>'.
2232 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_oci.
2237 Oracle nie wspiera kluczy automatycznych więc należy podać nazwę
2238 sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
2239 <methodname>lastSequenceId()</methodname>.
2245 <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
2246 <title>PDO PostgreSQL</title>
2250 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2251 należy użyć nazwy '<classname>Pdo_Pgsql</classname>'.
2256 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_pgsql.
2261 PostgreSQL wspiera sekwencje oraz klucze automatyczne. Przez to
2262 podawanie argumentów w <methodname>lastInsertId()</methodname> jest
2263 opcjonalne. Jeśli nie poda się argumentów adapter zwróci ostatnią
2264 wartość wygenerowaną dla klucza automatycznego. Jeśli argumenty zostaną
2265 podane to adapter zwróci ostatnią wartość wygenerowaną przez sekwencję
2266 o nazwie zgodnej z konwencją
2267 '<emphasis>tabela</emphasis>_<emphasis>kolumna</emphasis>_seq'.
2273 <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
2274 <title>PDO SQLite</title>
2278 Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
2279 należy użyć nazwy '<classname>Pdo_Sqlite</classname>'.
2284 Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_sqlite.
2289 SQLite nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
2290 ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
2291 automatycznego. Metoda <methodname>lastSequenceId()</methodname>
2292 zwraca <constant>NULL</constant>.
2297 Aby połączyć się z bazą danych SQLite2 należy podać
2298 <command>'sqlite2' => true</command> jako jeden z elementów
2299 tablicy parametrów podczas tworzenia instancji adaptera
2300 <classname>Pdo_Sqlite</classname>.
2305 Aby połączyć się z bazą danych SQLite rezydującą w pamięci
2306 należy podać <command>'dbname' => ':memory:'</command> jako
2307 jeden z elementów tablicy parametrów podczas tworzenia instancji adaptera
2308 <classname>Pdo_Sqlite</classname>.
2313 Starsze wersje sterownika <acronym>PHP</acronym> SQLite nie wspierają
2314 poleceń PRAGMA niezbędnych dla zachowania krótkich nazw kolumn w
2315 wynikach zapytania. W przypadku wystąpienia problemów z zapytaniami JOIN
2316 polegających na zwracaniu wyników z nazwami kolumn w postaci
2317 "tabela.kolumna" zaleca się aktualizację <acronym>PHP</acronym> do
2324 <sect3 id="zend.db.adapter.adapter-notes.firebird">
2325 <title>Firebird/Interbase</title>
2329 Ten adapter używa rozszerzenia <acronym>PHP</acronym> php_interbase.
2334 Firebird/Interbase nie wspiera kluczy automatycznych więc należy podać nazwę
2335 sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
2336 <methodname>lastSequenceId()</methodname>.
2341 Obecnie, opcja <constant>Zend_Db::CASE_FOLDING</constant> nie jest
2342 zaimplementowana w tym adapterze. Identyfikatory bez znaków ograniczających
2343 są zwracane w postaci wielkich liter.
2349 Nazwa adaptera to <classname>ZendX_Db_Adapter_Firebird</classname>.
2352 Należy pamiętać o użyciu parametru adapterNamespace z wartością
2353 <classname>ZendX_Db_Adapter</classname>.
2356 Zaleca się aktualizację pliku <filename>gds32.dll</filename> (lub
2357 odpowiednika wersji linux) dostarczanym z <acronym>PHP</acronym> do wersji odpowiadającej
2358 serwerowi bazy danych. Dla Firebird odpowiednikiem
2359 <filename>gds32.dll</filename> jest
2360 <filename>fbclient.dll</filename>.
2363 Domyślnie wszystkie identyfikatory (nazwy tabel, kolumn) są zwracane
2374 vim:se ts=4 sw=4 et: