Zend_Db_Adapter.xml 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 21740 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.db.adapter">
  5. <title>Zend_Db_Adapter</title>
  6. <para>
  7. <classname>Zend_Db</classname> i powiązane z nim klasy udostępniają prosty interfejs
  8. dla baz danych <acronym>SQL</acronym> z poziomu Zend Framework. Klasa
  9. <classname>Zend_Db_Adapter</classname> jest podstawowym komponentem potrzebnym by
  10. połączyć aplikację PHP z systemem zarządzania bazą danych (<acronym>RDBMS</acronym>).
  11. Dla każdego rodzaju bazy danych istnieje oddzielna klasa adaptera
  12. <classname>Zend_Db</classname>.
  13. </para>
  14. <para>
  15. Adaptery <classname>Zend_Db</classname> tworzą połączenie pomiędzy rozszerzeniami
  16. <acronym>PHP</acronym> dla konkretnych rodzajów baz danych a wspólnym interfejsem,
  17. dzięki czemu można napisać aplikację raz i w nieskomplikowany sposób uruchamiać
  18. ją z wieloma rodzajami <acronym>RDBMS</acronym>
  19. </para>
  20. <para>
  21. Interfejs klasy adaptera jest podobny do interfejsu rozszerzenia
  22. <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>. <classname>Zend_Db</classname>
  23. zawiera klasy adapterów dla sterowników <acronym>PDO</acronym> następujących rodzajów
  24. baz danych:
  25. </para>
  26. <itemizedlist>
  27. <listitem>
  28. <para>
  29. IBM DB2 oraz Informix Dynamic Server (IDS), poprzez rozszerzenie
  30. <acronym>PHP</acronym>
  31. <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink>.
  32. </para>
  33. </listitem>
  34. <listitem>
  35. <para>
  36. MySQL, poprzez rozszerzenie <acronym>PHP</acronym>
  37. <ulink url="http://www.php.net/pdo-mysql">pdo_mysql</ulink>
  38. </para>
  39. </listitem>
  40. <listitem>
  41. <para>
  42. Microsoft <acronym>SQL</acronym> Server, używając rozszerzenia
  43. <acronym>PHP</acronym>
  44. <ulink url="http://www.php.net/pdo-dblib">pdo_dblib</ulink>
  45. </para>
  46. </listitem>
  47. <listitem>
  48. <para>
  49. Oracle, poprzez rozszerzenie <acronym>PHP</acronym>
  50. <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink>
  51. </para>
  52. </listitem>
  53. <listitem>
  54. <para>
  55. PostgreSQL, poprzez rozszerzenie <acronym>PHP</acronym>
  56. <ulink url="http://www.php.net/pdo-pgsql">pdo_pgsql</ulink>
  57. </para>
  58. </listitem>
  59. <listitem>
  60. <para>
  61. SQLite, używając rozszerzenia <acronym>PHP</acronym>
  62. <ulink url="http://www.php.net/pdo-sqlite">pdo_sqlite</ulink>
  63. </para>
  64. </listitem>
  65. </itemizedlist>
  66. <para>
  67. Dodatkowo <classname>Zend_Db</classname> dostarcza klas adapterów korzystających
  68. z rozszerzeń <acronym>PHP</acronym> dla następujących rodzajów
  69. baz danych:
  70. </para>
  71. <itemizedlist>
  72. <listitem>
  73. <para>
  74. MySQL, poprzez rozszerzenie <acronym>PHP</acronym>
  75. <ulink url="http://www.php.net/mysqli">mysqli</ulink>
  76. </para>
  77. </listitem>
  78. <listitem>
  79. <para>
  80. Oracle, poprzez rozszerzenie <acronym>PHP</acronym>
  81. <ulink url="http://www.php.net/oci8">oci8</ulink>
  82. </para>
  83. </listitem>
  84. <listitem>
  85. <para>
  86. IBM DB2 oraz DB2/i5, poprzez rozszerzenie <acronym>PHP</acronym>
  87. <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
  88. </para>
  89. </listitem>
  90. <listitem>
  91. <para>
  92. Firebird/Interbase, poprzez rozszerzenie <acronym>PHP</acronym>
  93. <ulink url="http://www.php.net/ibase">php_interbase</ulink>
  94. </para>
  95. </listitem>
  96. </itemizedlist>
  97. <note>
  98. <para>
  99. Każdy adapter <classname>Zend_Db</classname> używa określonego rozszerzenia
  100. <acronym>PHP</acronym>. Aby użyć adaptera należy mieć zainstalowane i włączone
  101. odpowiadające mu rozszerzenie <acronym>PHP</acronym>. Np. aby użyć dowolnego
  102. adaptera <acronym>PDO</acronym> <classname>Zend_Db</classname>, wymagane jest
  103. posiadanie włączonego rozszerzenia <acronym>PDO</acronym> oraz sterownika dla
  104. danego rodzaju <acronym>RDBMS</acronym>.
  105. </para>
  106. </note>
  107. <sect2 id="zend.db.adapter.connecting">
  108. <title>Połączenie z bazą danych za pomocą adaptera</title>
  109. <para>
  110. Ta część opisuje jak tworzy się instancję adaptera bazy danych. Jest to odpowiednik
  111. połączenia z bazą danych w aplikacji <acronym>PHP</acronym>.
  112. </para>
  113. <sect3 id="zend.db.adapter.connecting.constructor">
  114. <title>Użycie konstruktora adaptera Zend_Db</title>
  115. <para>
  116. Można utworzyć instancję adaptera za pomocą konstruktora. Przyjmuje on
  117. pojedynczy argument - tablicę parametrów używanych do deklaracji połączenia.
  118. </para>
  119. <example id="zend.db.adapter.connecting.constructor.example">
  120. <title>Użycie konstruktora adaptera</title>
  121. <programlisting language="php"><![CDATA[
  122. $db = new Zend_Db_Adapter_Pdo_Mysql(array(
  123. 'host' => '127.0.0.1',
  124. 'username' => 'webuser',
  125. 'password' => 'xxxxxxxx',
  126. 'dbname' => 'test'
  127. ));
  128. ]]></programlisting>
  129. </example>
  130. </sect3>
  131. <sect3 id="zend.db.adapter.connecting.factory">
  132. <title>Użycie fabryki Zend_Db</title>
  133. <para>
  134. Alternatywą w stosunku do bezpośredniego używania konstruktora jest utworzenie
  135. instancji adaptera za pomocą statycznej metody
  136. <methodname>Zend_Db::factory()</methodname>. Ta metoda dynamicznie ładuje plik
  137. klasy adaptera używając
  138. <link linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>.
  139. </para>
  140. <para>
  141. Pierwszy argument metody to łańcuch znaków, który wyznacza nazwę bazową klasy
  142. adaptera. Np. string '<classname>Pdo_Mysql</classname>' odpowiada klasie
  143. <classname>Zend_Db_Adapter_Pdo_Mysql</classname>. Drugi argument to ta sama
  144. tablica parametrów, którą należało podać adapterowi konstruktora.
  145. </para>
  146. <example id="zend.db.adapter.connecting.factory.example">
  147. <title>Użycie metody fabryki adaptera</title>
  148. <programlisting language="php"><![CDATA[
  149. // Poniższa instrukcja jest zbędna ponieważ plik z klasą
  150. // Zend_Db_Adapter_Pdo_Mysql zostanie załadowany przez fabrykę
  151. // Zend_Db
  152. // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
  153. // Załaduj klasę Zend_Db_Adapter_Pdo_Mysql automatycznie
  154. // i utwórz jej instancję
  155. $db = Zend_Db::factory('Pdo_Mysql', array(
  156. 'host' => '127.0.0.1',
  157. 'username' => 'webuser',
  158. 'password' => 'xxxxxxxx',
  159. 'dbname' => 'test'
  160. ));
  161. ]]></programlisting>
  162. </example>
  163. <para>
  164. Jeśli jest zdefiniowana własna klasa dziedzicząca po
  165. <classname>Zend_Db_Adapter_Abstract</classname> ale jej nazwa nie zawiera
  166. "<classname>Zend_Db_Adapter</classname>", można użyć metody
  167. <methodname>factory()</methodname> do załadowania adaptera jedynie jeśli
  168. poda się swój prefiks nazwy adaptera z kluczem 'adapterNamespace' do
  169. argumentu zawierającego parametry połączenia.
  170. </para>
  171. <example id="zend.db.adapter.connecting.factory.example2">
  172. <title>Użycie metody fabryki dla własnej klasy adaptera</title>
  173. <programlisting language="php"><![CDATA[
  174. // Nie trzeba ładować pliku klasy adaptera
  175. // bo robi to metoda fabryki Zend_Db
  176. // Załadowanie klasy MyProject_Db_Adapter_Pdo_Mysql automatycznie
  177. // i utworzenie jej instancji
  178. $db = Zend_Db::factory('Pdo_Mysql', array(
  179. 'host' => '127.0.0.1',
  180. 'username' => 'webuser',
  181. 'password' => 'xxxxxxxx',
  182. 'dbname' => 'test',
  183. 'adapterNamespace' => 'MyProject_Db_Adapter'
  184. ));
  185. ]]></programlisting>
  186. </example>
  187. </sect3>
  188. <sect3 id="zend.db.adapter.connecting.factory-config">
  189. <title>Użycie Zend_Config z fabryką Zend_Db</title>
  190. <para>
  191. Każdy z argumentów metody <methodname>factory()</methodname> może również zostać
  192. podany w formie obiektu klasy <link linkend="zend.config">Zend_Config</link>.
  193. </para>
  194. <para>
  195. Jeśli pierwszy argument jest obiektem <classname>Zend_Config</classname>
  196. to wymagane jest aby posiadał właściwość o nazwie
  197. <property>adapter</property>, w której będzie zapisany łańcuch znaków
  198. określający nazwę bazową klasy adaptera. Opcjonalnie, obiekt ten może zawierać
  199. właściwość '<property>params</property>' z właściwościami potomnymi
  200. odpowiadającymi nazwom parametrów adaptera. Będą one użyte jedynie w
  201. przypadku braku drugiego argumentu metody
  202. <methodname>factory()</methodname>.
  203. </para>
  204. <example id="zend.db.adapter.connecting.factory.example1">
  205. <title>Użycie metody fabryki adaptera z obiektem Zend_Config</title>
  206. <para>
  207. W poniższym przykładzie, obiekt <classname>Zend_Config</classname>
  208. jest utworzony z tablicy.
  209. Można również załadować dane z pliku zewnętrznego poprzez klasy
  210. <link linkend="zend.config.adapters.ini">Zend_Config_Ini</link> oraz
  211. <link linkend="zend.config.adapters.xml">Zend_Config_Xml</link>.
  212. </para>
  213. <programlisting language="php"><![CDATA[
  214. $config = new Zend_Config(
  215. array(
  216. 'database' => array(
  217. 'adapter' => 'Mysqli',
  218. 'params' => array(
  219. 'host' => '127.0.0.1',
  220. 'dbname' => 'test',
  221. 'username' => 'webuser',
  222. 'password' => 'secret',
  223. )
  224. )
  225. )
  226. );
  227. $db = Zend_Db::factory($config->database);
  228. ]]></programlisting>
  229. </example>
  230. <para>
  231. Drugi argument metody <methodname>factory()</methodname> może stanowić tablicę
  232. asocjacyjną zawierającą wartości odpowiadające parametrom adaptera. Ten argument
  233. jest opcjonalny. Jeśli pierwszy argument jest obiektem klasy
  234. <classname>Zend_Config</classname> to powinien zawierać wszystkie parametry a
  235. drugi argument jest ignorowany.
  236. </para>
  237. </sect3>
  238. <sect3 id="zend.db.adapter.connecting.parameters">
  239. <title>Parametry adaptera</title>
  240. <para>
  241. Poniższa lista opisuje parametry wspólne dla klas adapterów
  242. <classname>Zend_Db</classname>.
  243. </para>
  244. <itemizedlist>
  245. <listitem>
  246. <para>
  247. <emphasis>host</emphasis>:
  248. łańcuch znaków zawierający nazwę hosta lub adres IP serwera bazy danych.
  249. Jeśli baza danych jest uruchomiona na tej samej maszynie co aplikacja to
  250. można tu umieścić 'localhost' lub '127.0.0.1'.
  251. </para>
  252. </listitem>
  253. <listitem>
  254. <para>
  255. <emphasis>username</emphasis>:
  256. identyfikator użytkownika używany do autoryzacji połączenia z serwerem
  257. bazy danych.
  258. </para>
  259. </listitem>
  260. <listitem>
  261. <para>
  262. <emphasis>password</emphasis>:
  263. hasło użytkownika używane do autoryzacji połączenia z serwerem
  264. bazy danych.
  265. </para>
  266. </listitem>
  267. <listitem>
  268. <para>
  269. <emphasis>dbname</emphasis>:
  270. nazwa instancji bazy danych na serwerze.
  271. </para>
  272. </listitem>
  273. <listitem>
  274. <para>
  275. <emphasis>port</emphasis>:
  276. niektóre serwery bazy danych używają do komunikacji numeru portu określonego
  277. przez administratora. Ten parametr pozwala na ustawienie numeru portu przez
  278. który aplikacja <acronym>PHP</acronym> się łączy tak aby zgadzał się z tym
  279. ustawionym na serwerze bazy danych.
  280. </para>
  281. </listitem>
  282. <listitem>
  283. <para>
  284. <emphasis>charset</emphasis>:
  285. określenie zestawu znaków używanego podczas połączenia.
  286. </para>
  287. </listitem>
  288. <listitem>
  289. <para>
  290. <emphasis>options</emphasis>:
  291. ten parametr to tablica asocjacyjna opcji obsługiwanych przez wszystkie
  292. klasy <classname>Zend_Db_Adapter</classname>.
  293. </para>
  294. </listitem>
  295. <listitem>
  296. <para>
  297. <emphasis>driver_options</emphasis>:
  298. ten parametr to tablica asocjacyjna zawierająca dodatkowe opcje
  299. specyficzne dla każdego rozszerzenia bazy danych. Typowym przykładem
  300. użycia tego parametru jest zbiór atrybutów sterownika
  301. <acronym>PDO</acronym>.
  302. </para>
  303. </listitem>
  304. <listitem>
  305. <para>
  306. <emphasis>adapterNamespace</emphasis>:
  307. początkowa część nazwy klasy używanego adaptera, używana zamiast
  308. '<classname>Zend_Db_Adapter</classname>'. Przydatna w przypadku użycia
  309. metody <methodname>factory()</methodname> do załadowana własnej klasy
  310. adaptera.
  311. </para>
  312. </listitem>
  313. </itemizedlist>
  314. <example id="zend.db.adapter.connecting.parameters.example1">
  315. <title>Przekazanie do fabryki opcji zmiany wielkości znaków</title>
  316. <para>
  317. Opcję tą można podać za pomocą stałej
  318. <constant>Zend_Db::CASE_FOLDING</constant>.
  319. Odpowiada ona atrybutowi <constant>ATTR_CASE</constant> w <acronym>PDO</acronym>
  320. oraz rozszerzeniu IBM DB2, który zmienia wielkość znaków w nazwach kolumn
  321. zwracanych w rezultacie zapytania. Opcja przybiera wartości
  322. <constant>Zend_Db::CASE_NATURAL</constant> (bez zmiany - domyślnie),
  323. <constant>Zend_Db::CASE_UPPER</constant> (zmiana na wielkie znaki) oraz
  324. <constant>Zend_Db::CASE_LOWER</constant> (zmiana na małe znaki).
  325. </para>
  326. <programlisting language="php"><![CDATA[
  327. $options = array(
  328. Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
  329. );
  330. $params = array(
  331. 'host' => '127.0.0.1',
  332. 'username' => 'webuser',
  333. 'password' => 'xxxxxxxx',
  334. 'dbname' => 'test',
  335. 'options' => $options
  336. );
  337. $db = Zend_Db::factory('Db2', $params);
  338. ]]></programlisting>
  339. </example>
  340. <example id="zend.db.adapter.connecting.parameters.example2">
  341. <title>Przekazanie do fabryki opcji automatycznego umieszczania
  342. w cudzysłowie</title>
  343. <para>
  344. Tą opcję można podać za pomocą stałej
  345. <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant>.
  346. Jeśli jej wartość wynosi <constant>TRUE</constant> (domyślnie) to identyfikatory
  347. takie jak nazwy tabel, kolumn oraz aliasy w składni każdego polecenia
  348. <acronym>SQL</acronym> generowanego za pomocą danego adaptera będą
  349. umieszczane w cudzysłowie. Takie podejście upraszcza używanie identyfikatorów
  350. zawierających słowa kluczowe <acronym>SQL</acronym> lub znaki specjalne. Jeśli
  351. wartość opcji wynosi <constant>FALSE</constant> to identyfikatory nie są
  352. umieszczane w cudzysłowie. Jeśli zachodzi potrzeba owinięcia identyfikatorów
  353. cudzysłowami należy to zrobić samodzielnie za pomocą metody
  354. <methodname>quoteIdentifier()</methodname>.
  355. </para>
  356. <programlisting language="php"><![CDATA[
  357. $options = array(
  358. Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
  359. );
  360. $params = array(
  361. 'host' => '127.0.0.1',
  362. 'username' => 'webuser',
  363. 'password' => 'xxxxxxxx',
  364. 'dbname' => 'test',
  365. 'options' => $options
  366. );
  367. $db = Zend_Db::factory('Pdo_Mysql', $params);
  368. ]]></programlisting>
  369. </example>
  370. <example id="zend.db.adapter.connecting.parameters.example3">
  371. <title>Przekazanie do fabryki opcji sterownika PDO</title>
  372. <programlisting language="php"><![CDATA[
  373. $pdoParams = array(
  374. PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
  375. );
  376. $params = array(
  377. 'host' => '127.0.0.1',
  378. 'username' => 'webuser',
  379. 'password' => 'xxxxxxxx',
  380. 'dbname' => 'test',
  381. 'driver_options' => $pdoParams
  382. );
  383. $db = Zend_Db::factory('Pdo_Mysql', $params);
  384. echo $db->getConnection()
  385. ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
  386. ]]></programlisting>
  387. </example>
  388. <example id="zend.db.adapter.connecting.parameters.example4">
  389. <title>Przekazanie do fabryki opcji serializacji</title>
  390. <programlisting language="php"><![CDATA[
  391. $options = array(
  392. Zend_Db::ALLOW_SERIALIZATION => false
  393. );
  394. $params = array(
  395. 'host' => '127.0.0.1',
  396. 'username' => 'webuser',
  397. 'password' => 'xxxxxxxx',
  398. 'dbname' => 'test',
  399. 'options' => $options
  400. );
  401. $db = Zend_Db::factory('Pdo_Mysql', $params);
  402. ]]></programlisting>
  403. </example>
  404. </sect3>
  405. <sect3 id="zend.db.adapter.connecting.getconnection">
  406. <title>Zarządzanie leniwymi połączeniami</title>
  407. <para>
  408. Utworzenie instancji klasy adaptera nie powoduje natychmiastowego połączenia
  409. z serwerem bazy danych. Adapter zachowuje parametry połączenia ale łączy się
  410. na żądanie - w momencie pierwszego wywołania zapytania. Dzięki temu zainicjowanie
  411. adaptera jest szybkie i tanie. Można utworzyć adapter nawet jeśli nie jest
  412. się pewnym czy wykonanie jakiegokolwiek zapytania przy danym połączeniu będzie
  413. niezbędne.
  414. </para>
  415. <para>
  416. Jeśli zajdzie potrzeba zmuszenia adaptera do połączenia z bazą danych,
  417. należy wówczas wywołać metodę <methodname>getConnection()</methodname>.
  418. Zwraca ona obiekt połączenia odpowiednio do rozszerzenia
  419. <acronym>PHP</acronym> używanego do połączenia. Jeśli
  420. używa się adaptera korzystającego z <acronym>PDO</acronym>, to metoda
  421. <methodname>getConnection()</methodname>, po zainicjowaniu połączenia
  422. z serwerem bazy danych, zwróci obiekt <acronym>PDO</acronym>.
  423. </para>
  424. <para>
  425. Możliwość wymuszenia połączenia z bazą danych może być przydatna gdy chce się
  426. złapać wyjątki rzucane przez adapter powstałe w rezultacie podania złych danych
  427. uwierzytelniających lub innych błędów połączenia. Te wyjątki nie są rzucane dopóki
  428. nie jest ustanowiona próba połączenia, więc można uprościć kod aplikacji i obsłużyć
  429. je w jednym miejscu. W przeciwnym razie należałoby je przechwycać w momencie
  430. wywołania pierwszego zapytania do bazy danych.
  431. </para>
  432. <para>
  433. Dodatkowo adapter może zostać poddany serializacji i przechowany
  434. np. w zmiennej sesyjnej.
  435. Może to być pomocne nie tylko dla adaptera ale również z punktu widzenia obiektów,
  436. które z niego korzystają, takich jak <classname>Zend_Db_Select</classname>.
  437. Domyślnie serializacja adapterów jest dozwolona ale jeśli jest taka
  438. potrzeba - można ją wyłączyć poprzez podanie opcji
  439. <constant>Zend_Db::ALLOW_SERIALIZATION</constant> z wartością
  440. <constant>FALSE</constant> (przykład niżej).
  441. Aby pozostać w zgodzie z zasadą leniwego połączenia, adapter nie połączy się
  442. automatycznie po odserializowaniu. Należy zatem
  443. wywołać metodę <methodname>getConnection()</methodname>.
  444. Można również zmusić adapter aby po odserializowaniu łączył się z bazą
  445. danych automatycznie poprzez podanie opcji
  446. <constant>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE</constant>
  447. z wartością <constant>TRUE</constant>.
  448. </para>
  449. <example id="zend.db.adapter.connecting.getconnection.example">
  450. <title>Obsługa wyjątków połączenia</title>
  451. <programlisting language="php"><![CDATA[
  452. try {
  453. $db = Zend_Db::factory('Pdo_Mysql', $parameters);
  454. $db->getConnection();
  455. } catch (Zend_Db_Adapter_Exception $e) {
  456. // przyczyną problemów mogą być złe dane uwierzytelniające lub np. baza danych
  457. // nie jest uruchomiona
  458. } catch (Zend_Exception $e) {
  459. // przyczyną może być np. problem z załadowaniem odpowiedniej klasy adaptera
  460. }
  461. ]]></programlisting>
  462. </example>
  463. </sect3>
  464. </sect2>
  465. <sect2 id="zend.db.adapter.example-database">
  466. <title>Przykładowa baza danych</title>
  467. <para>
  468. W dokumentacji klas <classname>Zend_Db</classname> używany jest prosty zestaw tabel w
  469. celu zilustrowania użycia klas i metod. Te tabele mogą przechowywać dane związane z
  470. przechowywaniem błędów (bugs) powstałych podczas rozwijania projektu informatycznego.
  471. Baza danych zawiera cztery tabele:
  472. </para>
  473. <itemizedlist>
  474. <listitem>
  475. <para>
  476. <emphasis>accounts</emphasis> przechowuje informacje o każdym użytkowniku
  477. bazy danych błędów.
  478. </para>
  479. </listitem>
  480. <listitem>
  481. <para>
  482. <emphasis>products</emphasis> przechowuje informacje o każdym produkcie,
  483. dla którego można zapisać wystąpienie usterki.
  484. </para>
  485. </listitem>
  486. <listitem>
  487. <para>
  488. <emphasis>bugs</emphasis> przechowuje informacje o błędach, włączając
  489. jego obecny stan, osobę zgłaszającą, osobę przypisaną do rozwiązania
  490. problemu oraz osobę przeznaczoną do zweryfikowania poprawności
  491. zastosowanego rozwiązania.
  492. </para>
  493. </listitem>
  494. <listitem>
  495. <para>
  496. <emphasis>bugs_products</emphasis> przechowuje relację pomiędzy usterkami
  497. a produktami. To odzwierciedla połączenie wiele-do-wielu, ponieważ dany błąd
  498. może się odnosić do wielu produktów a jeden produkt może posiadać wiele usterek.
  499. </para>
  500. </listitem>
  501. </itemizedlist>
  502. <para>
  503. Poniższy pseudokod definicji danych <acronym>SQL</acronym> opisuje tabele z tego
  504. przykładu. Te tabele są bardzo często używane w testach jednostkowych
  505. <classname>Zend_Db</classname>.
  506. </para>
  507. <programlisting language="sql"><![CDATA[
  508. CREATE TABLE accounts (
  509. account_name VARCHAR(100) NOT NULL PRIMARY KEY
  510. );
  511. CREATE TABLE products (
  512. product_id INTEGER NOT NULL PRIMARY KEY,
  513. product_name VARCHAR(100)
  514. );
  515. CREATE TABLE bugs (
  516. bug_id INTEGER NOT NULL PRIMARY KEY,
  517. bug_description VARCHAR(100),
  518. bug_status VARCHAR(20),
  519. reported_by VARCHAR(100) REFERENCES accounts(account_name),
  520. assigned_to VARCHAR(100) REFERENCES accounts(account_name),
  521. verified_by VARCHAR(100) REFERENCES accounts(account_name)
  522. );
  523. CREATE TABLE bugs_products (
  524. bug_id INTEGER NOT NULL REFERENCES bugs,
  525. product_id INTEGER NOT NULL REFERENCES products,
  526. PRIMARY KEY (bug_id, product_id)
  527. );
  528. ]]></programlisting>
  529. <para>
  530. Należy zwrócić uwagę, iż tabela 'bugs' zawiera wiele kluczy obcych
  531. odnoszących się do tabeli 'accounts'. Każdy z nich może prowadzić do
  532. innego wiersza tabeli 'accounts' w ramach jednego bugu.
  533. </para>
  534. <para>
  535. Poniższy diagram ilustruje fizyczny model danych przykładowej bazy danych
  536. </para>
  537. <para>
  538. <inlinegraphic width="387" scale="100" align="center" valign="middle"
  539. fileref="figures/zend.db.adapter.example-database.png" format="PNG" />
  540. </para>
  541. </sect2>
  542. <sect2 id="zend.db.adapter.select">
  543. <title>Pobranie rezultatów zapytania</title>
  544. <para>
  545. Ta część opisuje metody klasy adaptera za pomocą których można wywołać
  546. zapytania <acronym>SELECT</acronym> oraz pobrać ich rezultaty.
  547. </para>
  548. <sect3 id="zend.db.adapter.select.fetchall">
  549. <title>Pobranie całego zbioru rezultatów</title>
  550. <para>
  551. Za pomocą metody <methodname>fetchAll()</methodname> można wywołać zapytanie
  552. <acronym>SQL</acronym> <acronym>SELECT</acronym> oraz pobrać jego rezultaty
  553. w jednym kroku.
  554. </para>
  555. <para>
  556. Pierwszym argumentem metody jest łańcuch znaków zawierający polecenie
  557. <acronym>SELECT</acronym>. Alternatywnie, w pierwszym argumencie można umieścić
  558. obiekt klasy <link linkend="zend.db.select">Zend_Db_Select</link>. Adapter
  559. automatycznie dokonuje konwersji tego obiektu do łańcucha znaków zawierającego
  560. zapytanie <acronym>SELECT</acronym>.
  561. </para>
  562. <para>
  563. Drugi argument metody <methodname>fetchAll()</methodname> to tablica wartości
  564. używanych do zastąpienia parametrów wiązanych w zapytaniu <acronym>SQL</acronym>.
  565. </para>
  566. <example id="zend.db.adapter.select.fetchall.example">
  567. <title>Użycie metody fetchAll()</title>
  568. <programlisting language="php"><![CDATA[
  569. $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
  570. $result = $db->fetchAll($sql, 2);
  571. ]]></programlisting>
  572. </example>
  573. </sect3>
  574. <sect3 id="zend.db.adapter.select.fetch-mode">
  575. <title>Zmiana trybu zwracania danych</title>
  576. <para>
  577. Domyślnie <methodname>fetchAll()</methodname> zwraca tablicę wierszy, z których
  578. każdy jest tablicą asocjacyjną. Kluczami tablicy asocjacyjnej są kolumny lub ich
  579. aliasy podane w zapytaniu <acronym>SELECT</acronym>.
  580. </para>
  581. <para>
  582. Można ustawić inny tryb zwracania rezultatów poprzez metodę
  583. <methodname>setFetchMode()</methodname>. Dopuszczalne tryby są identyfikowane
  584. przez stałe:
  585. </para>
  586. <itemizedlist>
  587. <listitem>
  588. <para>
  589. <emphasis>Zend_Db::FETCH_ASSOC</emphasis>:
  590. zwraca dane w postaci tablicy tablic asocjacyjnych.
  591. Klucze tablicy asocjacyjnej
  592. to nazwy kolumn. To jest domyślny tryb zwrotu danych w klasach
  593. <classname>Zend_Db_Adapter</classname>.
  594. </para>
  595. <para>
  596. Należy zwrócić uwagę na fakt iż jeśli lista kolumn do zwrotu
  597. zawiera więcej niż jedną kolumnę o określonej nazwie,
  598. np. jeśli pochodzą one z różnych tabel
  599. połączonych klauzulą <acronym>JOIN</acronym>, to w asocjacyjnej
  600. tablicy wynikowej może być tylko jeden klucz o podanej nazwie.
  601. Jeśli używany jest tryb <acronym>FETCH_ASSOC</acronym>,
  602. należy upewnić się, że kolumny w zapytaniu
  603. <acronym>SELECT</acronym> posiadają aliasy, dzięki czemu rezultat zapytania
  604. będzie zawierał unikatowe nazwy kolumn.
  605. </para>
  606. <para>
  607. Domyślnie, łańcuchy znaków z nazwami kolumn są zwracane w taki sposób w jaki
  608. zostały otrzymane przez sterownik bazy danych. Przeważnie jest odpowiada to
  609. stylowi nazw kolumn używanego rodzaju bazy danych. Dzięki opcji
  610. <constant>Zend_Db::CASE_FOLDING</constant> można określić wielkość
  611. zwracanych znaków.
  612. Opcji tej można użyć podczas inicjowania adaptera.
  613. Przykład: <xref linkend="zend.db.adapter.connecting.parameters.example1" />.
  614. </para>
  615. </listitem>
  616. <listitem>
  617. <para>
  618. <emphasis>Zend_Db::FETCH_NUM</emphasis>:
  619. zwraca dane jako tablicę tablic. Indeksami tablicy są liczby całkowite
  620. odpowiadające pozycji danej kolumny w liście <acronym>SELECT</acronym>
  621. zapytania.
  622. </para>
  623. </listitem>
  624. <listitem>
  625. <para>
  626. <emphasis>Zend_Db::FETCH_BOTH</emphasis>:
  627. zwraca dane jako tablicę tablic. Kluczami tablicy są zarówno łańcuchy znaków
  628. (tak jak w trybie FETCH_ASSOC) oraz liczby całkowite (tak jak w trybie
  629. FETCH_NUM). Należy zwrócić uwagę na fakt iż liczba elementów
  630. tablicy wynikowej będzie dwukrotnie większa niż w przypadku
  631. użycia trybów FETCH_ASSOC lub FETCH_NUM.
  632. </para>
  633. </listitem>
  634. <listitem>
  635. <para>
  636. <emphasis>Zend_Db::FETCH_COLUMN</emphasis>:
  637. zwraca dane jako tablicę wartości. Wartości odpowiadają rezultatom
  638. zapytania przypisanym jednej kolumnie zbioru wynikowego.
  639. Domyślnie, jest to pierwsza kolumna,
  640. indeksy rozpoczynają się od 0.
  641. </para>
  642. </listitem>
  643. <listitem>
  644. <para>
  645. <emphasis>Zend_Db::FETCH_OBJ</emphasis>:
  646. zwraca dane jako tablicę obiektów. Domyślną klasą jest wbudowana
  647. w <acronym>PHP</acronym> klasa stdClass.
  648. Kolumny rezultatu zapytania stają się właściwościami powstałego obiektu.
  649. </para>
  650. </listitem>
  651. </itemizedlist>
  652. <example id="zend.db.adapter.select.fetch-mode.example">
  653. <title>Użycie metody setFetchMode()</title>
  654. <programlisting language="php"><![CDATA[
  655. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  656. $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
  657. // $result jest tablicą obiektów
  658. echo $result[0]->bug_description;
  659. ]]></programlisting>
  660. </example>
  661. </sect3>
  662. <sect3 id="zend.db.adapter.select.fetchassoc">
  663. <title>Pobranie rezultatów jako tablicy asocjacyjnej</title>
  664. <para>
  665. Metoda <methodname>fetchAssoc()</methodname> zwraca dane w formie tablicy tablic
  666. asocjacyjnych, niezależnie od wartości ustalonej jako tryb
  667. zwracania rezultatów zapytania.
  668. </para>
  669. <example id="zend.db.adapter.select.fetchassoc.example">
  670. <title>Użycie fetchAssoc()</title>
  671. <programlisting language="php"><![CDATA[
  672. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  673. $result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
  674. // $result staje się tablicą tablic asocjacyjnych, mimo ustawionego
  675. // trybu zwracania rezultatów zapytania
  676. echo $result[0]['bug_description'];
  677. ]]></programlisting>
  678. </example>
  679. </sect3>
  680. <sect3 id="zend.db.adapter.select.fetchcol">
  681. <title>Zwrócenie pojedynczej kolumny ze zbioru wynikowego</title>
  682. <para>
  683. Metoda <methodname>fetchCol()</methodname> zwraca dane w postaci tablicy wartości
  684. niezależnie od wartości ustalonej jako tryb zwrcania rezultatów zapytania. Ta
  685. metoda zwraca pierwszą kolumnę ze zbioru powstałego na skutek wywołania zapytania.
  686. Inne kolumny znajdujące się w tym zbiorze są ignorowane. Aby zwrócić inną niż
  687. pierwsza kolumnę należy skorzystać z przykładu
  688. <xref linkend="zend.db.statement.fetching.fetchcolumn" />.
  689. </para>
  690. <example id="zend.db.adapter.select.fetchcol.example">
  691. <title>Użycie fetchCol()</title>
  692. <programlisting language="php"><![CDATA[
  693. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  694. $result = $db->fetchCol(
  695. 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
  696. // zawiera bug_description; bug_id nie zostanie zwrócona
  697. echo $result[0];
  698. ]]></programlisting>
  699. </example>
  700. </sect3>
  701. <sect3 id="zend.db.adapter.select.fetchpairs">
  702. <title>Zwrócenie ze zbioru wynikowego par klucz-wartość</title>
  703. <para>
  704. Metoda <methodname>fetchPairs()</methodname> zwraca dane w postaci tablicy
  705. par klucz-wartość. Zwracana jest to tablica asocjacyjna z pojedynczą wartością
  706. w każdym polu. Wartości z pierwszej kolumny zapytania <acronym>SELECT</acronym>
  707. stają się kluczami tablicy wynikowej zaś wartości drugiej zostają umieszczone
  708. jako wartości tablicy. Pozostałe kolumny zwracane przez zapytanie są ignorowane.
  709. </para>
  710. <para>
  711. Należy konstruować zapytanie <acronym>SELECT</acronym> w taki sposób aby pierwsza
  712. kolumna posiadała unikalne wartości. W przeciwnym wypadku wartości
  713. tablicy asocjacyjnej zostaną nadpisane.
  714. </para>
  715. <example id="zend.db.adapter.select.fetchpairs.example">
  716. <title>Użycie fetchPairs()</title>
  717. <programlisting language="php"><![CDATA[
  718. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  719. $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
  720. echo $result[2];
  721. ]]></programlisting>
  722. </example>
  723. </sect3>
  724. <sect3 id="zend.db.adapter.select.fetchrow">
  725. <title>Zwrócenie pojedynczego wiersza ze zbioru wynikowego</title>
  726. <para>
  727. Metoda <methodname>fetchRow()</methodname> pobiera dane używając bieżącego
  728. trybu zwracania rezultatów ale zwraca jedynie pierwszy wiersz ze zbioru
  729. wynikowego.
  730. </para>
  731. <example id="zend.db.adapter.select.fetchrow.example">
  732. <title>Using fetchRow()</title>
  733. <programlisting language="php"><![CDATA[
  734. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  735. $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
  736. // $result to pojedynczy obiekt a nie tablica obiektów
  737. echo $result->bug_description;
  738. ]]></programlisting>
  739. </example>
  740. </sect3>
  741. <sect3 id="zend.db.adapter.select.fetchone">
  742. <title>Zwrócenie pojedynczej wartości ze zbioru wynikowego</title>
  743. <para>
  744. Metoda <methodname>fetchOne()</methodname> można opisać jako kombinacja
  745. <methodname>fetchRow()</methodname> oraz <methodname>fetchCol()</methodname>
  746. bo zwraca dane pochodzące z pierwszego wiersza zbioru wynikowego ograniczając
  747. kolumny do pierwszej w wierszu. Ostatecznie zostaje zwrócona pojedyncza
  748. wartość skalarna a nie tablica czy obiekt
  749. </para>
  750. <example id="zend.db.adapter.select.fetchone.example">
  751. <title>Using fetchOne()</title>
  752. <programlisting language="php"><![CDATA[
  753. $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
  754. // pojedyncza wartość string
  755. echo $result;
  756. ]]></programlisting>
  757. </example>
  758. </sect3>
  759. </sect2>
  760. <sect2 id="zend.db.adapter.write">
  761. <title>Zapisywanie zmian do bazy danych</title>
  762. <para>
  763. Adaptera klasy można użyć również do zapisania nowych, bądź do zmiany
  764. istniejących danych w bazie. Ta część opisuje metody włąściwe dla tych operacji.
  765. </para>
  766. <sect3 id="zend.db.adapter.write.insert">
  767. <title>Dodawanie danych</title>
  768. <para>
  769. Za pomocą metody <methodname>insert()</methodname> można dodać nowe wiersze
  770. do tabeli bazy danych. Jej pierwszym argumentem jest łańcuch znaków oznaczający
  771. nazwę tabeli. Drugim - tablica asocjacyjna z odwzorowaniem nazw kolumn i wartości
  772. jakie mają zostać w nich zapisane.
  773. </para>
  774. <example id="zend.db.adapter.write.insert.example">
  775. <title>Dodawanie danych do tabeli</title>
  776. <programlisting language="php"><![CDATA[
  777. $data = array(
  778. 'created_on' => '2007-03-22',
  779. 'bug_description' => 'Something wrong',
  780. 'bug_status' => 'NEW'
  781. );
  782. $db->insert('bugs', $data);
  783. ]]></programlisting>
  784. </example>
  785. <para>
  786. Kolumny, które nie zostały podane w tablicy z danymi nie będą umieszczone
  787. w zapytaniu na zasadzie analogicznej do użycia polecenia
  788. <acronym>SQL</acronym> <acronym>INSERT</acronym>:
  789. Jeśli kolumna ma podaną wartość domyślną (<acronym>DEFAULT</acronym>)
  790. to ta wartość zostanie zapisana w nowym wierszu.
  791. W przeciwnym przypadku kolumna nie będzie miała żadnej
  792. wartości (<constant>NULL</constant>).
  793. </para>
  794. <para>
  795. Domyślnym sposobem zapisu danych jest użycie parametrów wiązanych.
  796. Dzięki temu ryzyko wystąpienia niektórych form zagrożenia
  797. bezpieczeństwa aplikacji jest ograniczone.
  798. W tablicy z danymi nie trzeba używać unikania
  799. lub umieszczania wartości w cudzysłowiu.
  800. </para>
  801. <para>
  802. Może wystąpić potrzeba potraktowania wartości w tablicy danych jako wyrażeń
  803. <acronym>SQL</acronym>. W takim wypadku nie powinno się stosować
  804. umieszczania w cudzysłowiu.
  805. Domyślnie wszystkie podane wartości string są traktowane jak literały.
  806. Aby upewnić się, że
  807. wartość jest wyrażeniem <acronym>SQL</acronym> i nie powinna zostać umieszczona w
  808. cudzysłowie, należy ją podać jako obiekt klasy
  809. <classname>Zend_Db_Expr</classname> zamiast
  810. prostego łańcucha znaków.
  811. </para>
  812. <example id="zend.db.adapter.write.insert.example2">
  813. <title>Umieszczanie wyrażeń w tabeli</title>
  814. <programlisting language="php"><![CDATA[
  815. $data = array(
  816. 'created_on' => new Zend_Db_Expr('CURDATE()'),
  817. 'bug_description' => 'Something wrong',
  818. 'bug_status' => 'NEW'
  819. );
  820. $db->insert('bugs', $data);
  821. ]]></programlisting>
  822. </example>
  823. </sect3>
  824. <sect3 id="zend.db.adapter.write.lastinsertid">
  825. <title>Pobranie wygenerowanej wartości</title>
  826. <para>
  827. Niektóre systemy zarządzania bazą danych wspierają klucze pierwotne o automatycznie
  828. zwiększanych wartościach. Tabela zdefiniowana w ten sposób generuje wartość klucza
  829. pierwotnego automatycznie przy każdym poleceniu <acronym>INSERT</acronym>.
  830. Wartością zwracaną przez metodę
  831. <methodname>insert()</methodname> <emphasis>nie</emphasis> jest
  832. ostatni zapisany identyfikator, ponieważ tabela mogła nie posiadać automatycznie
  833. inkrementowanej kolumny.
  834. Zamiast tego wartością zwrotną jest ilość zapisanych wierszy (przeważnie 1).
  835. </para>
  836. <para>
  837. Jeśli tabela jest zdefiniowana za pomocą automatycznego klucza pierwotnego to można
  838. użyć metody <methodname>lastInsertId()</methodname>.
  839. Po udanym dodaniu wiersza metoda
  840. ta zwraca ostatnią wartość klucza wygenerowaną w ramach bieżącego połączenia.
  841. </para>
  842. <example id="zend.db.adapter.write.lastinsertid.example-1">
  843. <title>Użycie lastInsertId() dla automatycznego klucza pierwotnego</title>
  844. <programlisting language="php"><![CDATA[
  845. $db->insert('bugs', $data);
  846. // zwrócenie ostatniej wartości wygenerowanej przez automatyczną kolumnę
  847. $id = $db->lastInsertId();
  848. ]]></programlisting>
  849. </example>
  850. <para>
  851. Niektóre systemy zarządzania bazą danych wspierają obiekt sekwencji, który służy
  852. do generowania unikalnych wartości, które mogą posłużyć jako klucz pierwotny.
  853. Aby obsługiwać również sekwencje metoda <methodname>lastInsertId()</methodname>
  854. akceptuje dodatkowe dwa argumenty. Pierwszym z nich jest nazwa tabeli zaś
  855. drugim - nazwa kolumny. Założona jest konwencja według której sekwencja ma nazwę
  856. składającą się z nazwy tabeli oraz kolumny do której generuje wartości z dodatkowym
  857. sufiksem "_seq". Podstawą tego założenia są domyślne ustawienia PostgreSQL.
  858. Przykładowo tabela "bugs" z kluczem pierwotnym w kolumnie "bug_id"
  859. będzie używała sekwencji o nazwie "bugs_bug_id_seq".
  860. </para>
  861. <example id="zend.db.adapter.write.lastinsertid.example-2">
  862. <title>Użycie lastInsertId() dla sekwencji</title>
  863. <programlisting language="php"><![CDATA[
  864. $db->insert('bugs', $data);
  865. // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_bug_id_seq'
  866. $id = $db->lastInsertId('bugs', 'bug_id');
  867. // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_seq'
  868. $id = $db->lastInsertId('bugs');
  869. ]]></programlisting>
  870. </example>
  871. <para>
  872. Jeśli nazwa obiektu sekwencji nie podąża za tą konwencją można użyć metody
  873. <methodname>lastSequenceId()</methodname>, która przyjmuje pojedynczy łańcuch
  874. znaków - nazwę sekwencji - jako argument.
  875. </para>
  876. <example id="zend.db.adapter.write.lastinsertid.example-3">
  877. <title>Użycie lastSequenceId()</title>
  878. <programlisting language="php"><![CDATA[
  879. $db->insert('bugs', $data);
  880. // zwrócenie ostatniej wartości wygenerowanej przez sekwencję 'bugs_id_gen'
  881. $id = $db->lastSequenceId('bugs_id_gen');
  882. ]]></programlisting>
  883. </example>
  884. <para>
  885. Dla systemów zarządzania bazą danych które nie wspierają sekwencji, włączając MySQL,
  886. Microsoft <acronym>SQL</acronym> Server, oraz SQLite dodatkowe argumenty podane do
  887. metody <methodname>lastInsertId()</methodname> są ignorowane a zwrócona jest
  888. ostatnia wartość wygenerowana dla dowolnej tabeli poprzez polecenie
  889. <acronym>INSERT</acronym>
  890. podczas bieżącego połączenia. Dla tych <acronym>RDBMS</acronym> metoda
  891. <methodname>lastSequenceId()</methodname> zawsze zwraca <constant>NULL</constant>.
  892. </para>
  893. <note>
  894. <title>Dlaczego nie należy używać "SELECT MAX(id) FROM table"?</title>
  895. <para>
  896. Powyższe zapytanie często zwraca ostatni klucz pierwotny, jaki został zapisany
  897. w wierszu tabeli. Ten sposób nie jest jednak bezpieczny w przypadku, gdy
  898. wiele klientów zapisuje rekordy do bazy danych. Jest możliwe, że w momencie
  899. pomiędzy zapisaniem jednego rekordu a zapytaniem o
  900. <methodname>MAX(id)</methodname>, do tabeli zostanie zapisany kolejny rekord,
  901. wprowadzony przez innego użytkownika. Przez to zwrócona wartość nie będzie
  902. identyfikowała pierwszego wprowadzonego wiersza tylko drugi - wprowadzony przez
  903. inne połączenie. Nie ma pewnego sposobu na wykrycie, że do takiego zdarzenia
  904. doszło.
  905. </para>
  906. <para>
  907. Zastosowanie mocnej izolacji transakcji, tak jak przy trybie
  908. "repeatable read" może pomóc w ograniczeniu ryzyka wystąpienia takiej
  909. sytuacji ale niektóre systemy zarządzania bazą danych nie wspierają
  910. izolacji transakcji w wystarczającym stopniu lub aplikacja może
  911. intencjonalnie korzystać jedynie z niskiego trybu izolacji transakcji.
  912. </para>
  913. <para>
  914. Dodatkowo, używanie wyrażeń takich jak "MAX(id)+1" do generowania
  915. nowych wartości klucza głównego nie jest bezpieczne bo
  916. dwa połączenia mogą wykonać to zapytanie
  917. praktycznie jednocześnie i w rezultacie próbować użyć jednakowej wartości
  918. dla kolejnego polecenia <acronym>INSERT</acronym>.
  919. </para>
  920. <para>
  921. Wszystkie systemy zarządzania bazą danych udostępniają
  922. mechanizmy służące generowaniu
  923. unikalnych wartości oraz zwracaniu ostatniej z nich.
  924. Mechanizmy te intencjonalnie działają poza zasięgiem izolacji
  925. transakcji więc nie jest możliwe aby wartość wygenerowana dla jednego
  926. klienta pojawiła się jako ostatnia wygenerowana dla innego połączenia.
  927. </para>
  928. </note>
  929. </sect3>
  930. <sect3 id="zend.db.adapter.write.update">
  931. <title>Aktualizacja danych</title>
  932. <para>
  933. Aktualizacji wierszy tabeli w bazie danych można dokonać poprzez metodę adaptera
  934. <methodname>update()</methodname> . Metoda przyjmuje trzy argumenty: pierwszym
  935. jest nazwa tabeli; drugim - tablica asocjacyjna mapująca kolumny, które mają ulec
  936. zmianie oraz wartości jakie kolumny przybiorą; trzecim - warunek
  937. wyznaczający wiersze do zmiany.
  938. </para>
  939. <para>
  940. Wartości w tablicy z danymi są traktowane jak literały znakowe. Należy zapoznać
  941. się z akapitem <xref linkend="zend.db.adapter.write.insert" /> aby uzyskać więcej
  942. informacji na temat użyci w niej wyrażeń <acronym>SQL</acronym>.
  943. </para>
  944. <para>
  945. Trzecim argumentem metody jest string zawierający wyrażenie <acronym>SQL</acronym>
  946. będące kryterium wyznaczającym wiersze do zmiany. Wartości i identyfikatory w tym
  947. argumencie nie są umieszczane w cudzysłowie ani unikane. Należy, więc, zadbać o to
  948. samemu. Należy zapoznać się z akapitem <xref linkend="zend.db.adapter.quoting" />
  949. aby zasięgnąć dodatkowych informacji.
  950. </para>
  951. <para>
  952. Wartością zwracaną jest ilość wierszy zmienionych przez operację aktualizacji.
  953. </para>
  954. <example id="zend.db.adapter.write.update.example">
  955. <title>Aktualizacja wierszy</title>
  956. <programlisting language="php"><![CDATA[
  957. $data = array(
  958. 'updated_on' => '2007-03-23',
  959. 'bug_status' => 'FIXED'
  960. );
  961. $n = $db->update('bugs', $data, 'bug_id = 2');
  962. ]]></programlisting>
  963. </example>
  964. <para>
  965. Jeśli trzeci argument nie zostanie podany to wszystkie wiersze w tabeli
  966. zostaną zaktualizowane zgodnie z kolumnami i wartościami podanymi w
  967. drugim argumencie.
  968. </para>
  969. <para>
  970. Jeśli trzeci argument zostanie podany jako tablica łańcuchów znakowych to
  971. w zapytaniu łańcuchy zostaną połączone za pomocą operatorów
  972. <constant>AND</constant>.
  973. </para>
  974. <para>
  975. Przy podaniu trzeciego argumentu jako tablicy tablic, ich wartości
  976. zostaną automatycznie
  977. otoczone cudzysłowami i umieszczone w kluczach tych tablic. Po czym zostaną
  978. połączone za pomocą operatorów <constant>AND</constant>.
  979. </para>
  980. <example id="zend.db.adapter.write.update.example-array">
  981. <title>Aktualizacja wierszy tablicy za pomocą tablicy wyrażeń</title>
  982. <programlisting language="php"><![CDATA[
  983. $data = array(
  984. 'updated_on' => '2007-03-23',
  985. 'bug_status' => 'FIXED'
  986. );
  987. $where[] = "reported_by = 'goofy'";
  988. $where[] = "bug_status = 'OPEN'";
  989. $n = $db->update('bugs', $data, $where);
  990. // Powstałe wyrażenie SQL to:
  991. // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
  992. // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
  993. ]]></programlisting>
  994. </example>
  995. <example id="zend.db.adapter.write.update.example-arrayofarrays">
  996. <title>Aktualizacja wierszy tablicy za pomocą tablicy tablic</title>
  997. <programlisting language="php"><![CDATA[
  998. $data = array(
  999. 'updated_on' => '2007-03-23',
  1000. 'bug_status' => 'FIXED'
  1001. );
  1002. $where['reported_by = ?'] = 'goofy';
  1003. $where['bug_status = ?'] = 'OPEN';
  1004. $n = $db->update('bugs', $data, $where);
  1005. // Powstałe wyrażenie SQL to:
  1006. // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
  1007. // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
  1008. ]]></programlisting>
  1009. </example>
  1010. </sect3>
  1011. <sect3 id="zend.db.adapter.write.delete">
  1012. <title>Usuwanie danych</title>
  1013. <para>
  1014. Usuwania danych można dokonać używając metody <methodname>delete()</methodname>.
  1015. Przyjmuje ona dwa argumenty: pierwszym z nich jest łańcuch znaków z nazwą tabeli;
  1016. Drugim - warunek określający wiersze do usunięcia.
  1017. </para>
  1018. <para>
  1019. Drugi argument to string zawierający wyrażenie <acronym>SQL</acronym> użyte jako
  1020. kryterium wyznaczania usuwanych wierszy. Wartości i identyfikatory nie są
  1021. unikane ani umieszczane w cudzysłowie - należy zatroszczyć się o to samemu. Aby
  1022. dowiedzieć się więcej na ten temat
  1023. można skorzystać z akapitu <xref linkend="zend.db.adapter.quoting" />.
  1024. </para>
  1025. <para>
  1026. Wartość zwrotna to ilość wierszy, jakie uległy zmianie w wyniku zadziałania
  1027. operacji usuwania.
  1028. </para>
  1029. <example id="zend.db.adapter.write.delete.example">
  1030. <title>Usuwanie wierszy</title>
  1031. <programlisting language="php"><![CDATA[
  1032. $n = $db->delete('bugs', 'bug_id = 3');
  1033. ]]></programlisting>
  1034. </example>
  1035. <para>
  1036. Jeśli drugi argument nie zostanie podany to wszystkie wiersze z tabeli
  1037. ulegną usunięciu.
  1038. </para>
  1039. <para>
  1040. Jeśli drugi argument zostanie podany jako tablica łańcuchów znaków to
  1041. te łańcuchy ulegną konkatenacji jako wyrażenia logiczne połączone
  1042. operatorem <constant>AND</constant>.
  1043. </para>
  1044. <para>
  1045. Jeśli trzeci argument będzie tablicą tablic to jej wartości zostaną
  1046. automatycznie otoczone cudzysłowami i umieszczona w kluczach tablic. Potem
  1047. zostaną połączone razem za pomocą operatora <constant>AND</constant>.
  1048. </para>
  1049. </sect3>
  1050. </sect2>
  1051. <sect2 id="zend.db.adapter.quoting">
  1052. <title>Umieszczanie wartości i identyfikatorów w cudzysłowie</title>
  1053. <para>
  1054. Podczas tworzenia zapytań <acronym>SQL</acronym> często dochodzi do sytuacji, w której
  1055. niezbędne jest umieszczenie wartości zmiennych <acronym>PHP</acronym> w wyrażeniach
  1056. <acronym>SQL</acronym>. Stanowi to zagrożenie, ponieważ jeśli wartość
  1057. łańcuchowej zmiennej <acronym>PHP</acronym> zawiera określone znaki, takie jak symbol
  1058. cudzysłowu, to mogą one spowodować błąd w poleceniu <acronym>SQL</acronym>. Poniżej
  1059. znajduje się przykład zapytania zawierającego niespójną liczbę symboli cudzysłowu:
  1060. <programlisting language="php"><![CDATA[
  1061. $name = "O'Reilly";
  1062. $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
  1063. echo $sql;
  1064. // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
  1065. ]]></programlisting>
  1066. </para>
  1067. <para>
  1068. Zagrożenie potęguje fakt iż podobne błędy mogą zostać wykorzystane przez osobę
  1069. próbującą zmanipulować działanie funkcji aplikacji. Jeśli takiej osobie
  1070. uda się wpłynąć na wartość zmiennej <acronym>PHP</acronym> poprzez
  1071. parametr <acronym>HTTP</acronym>
  1072. (bądź inny mechanizm), to będzie mogła zmienić zapytanie <acronym>SQL</acronym>
  1073. tak by dokonywało operacji zupełnie niezamierzonych przez twórców, takich jak
  1074. zwrócenie danych, do których osoba nie powinna mieć dostępu. To jest poważny i szeroko
  1075. rozpowszechniony sposób łamania zabezpieczeń aplikacji znany pod nazwą "SQL Injection"
  1076. (wstrzyknięcie SQL - <ulink url="http://en.wikipedia.org/wiki/SQL_Injection">
  1077. http://en.wikipedia.org/wiki/SQL_Injection</ulink>).
  1078. </para>
  1079. <para>
  1080. Adaptery klasy <classname>Zend_Db</classname> udostępniają funkcje przydatne
  1081. do zredukowania zagrożenia atakiem <acronym>SQL</acronym> Injection w kodzie
  1082. <acronym>PHP</acronym>.
  1083. Przyjętym rozwiązaniem jest unikanie znaków specjalnych takich jak cudzysłów w
  1084. wartościach zmiennych <acronym>PHP</acronym>
  1085. przed umieszczeniem ich w poleceniu <acronym>SQL</acronym>.
  1086. Takie podejście zapewnia ochronę przed przypadkową jak i intencjonalną zmianą
  1087. znaczenia poleceń <acronym>SQL</acronym> przez
  1088. zmienne <acronym>PHP</acronym> zawierające znaki specjalne.
  1089. </para>
  1090. <sect3 id="zend.db.adapter.quoting.quote">
  1091. <title>Użycie quote()</title>
  1092. <para>
  1093. Metoda <methodname>quote()</methodname> przyjmuje pojedynczy
  1094. argument - łańcuch znaków.
  1095. Na wyjściu zwraca podany argument ze wszystkimi znakami specjalnymi
  1096. poddanymi uniknięciu w sposób właściwy dla używanego
  1097. <acronym>RDBMS</acronym> i otoczony znakami ograniczającymi
  1098. łańcuchy znakowe. Standardowym znakiem ograniczającym
  1099. stringi w <acronym>SQL</acronym> jest pojedynczy cudzysłów (').
  1100. </para>
  1101. <example id="zend.db.adapter.quoting.quote.example">
  1102. <title>Użycie quote()</title>
  1103. <programlisting language="php"><![CDATA[
  1104. $name = $db->quote("O'Reilly");
  1105. echo $name;
  1106. // 'O\'Reilly'
  1107. $sql = "SELECT * FROM bugs WHERE reported_by = $name";
  1108. echo $sql;
  1109. // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
  1110. ]]></programlisting>
  1111. </example>
  1112. <para>
  1113. Należy zwrócić uwagę, że wartość zwrotna metody <methodname>quote()</methodname>
  1114. zawiera znaki ograniczające stringi. Jest to zachowanie różne od niektórych funkcji
  1115. które unikają specjalne znaki ale nie ujmują całego łańcucha w znaki ograniczające,
  1116. tak jak <ulink url="http://www.php.net/mysqli_real_escape_string">
  1117. mysql_real_escape_string()</ulink>.
  1118. </para>
  1119. <para>
  1120. Wartości mogą wymagać umieszczenia w cudzysłowach lub nie, zgodnie z
  1121. kontekstem używanego typu danych <acronym>SQL</acronym>.
  1122. W przypadku niektórych rodzajów systemów zarządzania
  1123. bazą danych liczby całkowite nie mogą być ograniczane cudzysłowami
  1124. jeśli są porównywane z kolumną lub wyrażeniem zwracającym inną liczbę całkowitą.
  1125. Innymi słowy, poniższy zapis może wywołać błąd w niektórych
  1126. implementacjach <acronym>SQL</acronym> zakładając, że
  1127. <property>intColumn</property> jest określona
  1128. typem danych <constant>INTEGER</constant>.
  1129. <programlisting language="php"><![CDATA[
  1130. SELECT * FROM atable WHERE intColumn = '123'
  1131. ]]></programlisting>
  1132. </para>
  1133. <para>
  1134. Można użyć opcjonalnego, drugiego argumentu metody <methodname>quote()</methodname>
  1135. aby określić typ danych <acronym>SQL</acronym> i ograniczyć stosowanie cudzysłowu.
  1136. </para>
  1137. <example id="zend.db.adapter.quoting.quote.example-2">
  1138. <title>Użycie quote() z podanym typem danych SQL</title>
  1139. <programlisting language="php"><![CDATA[
  1140. $value = '1234';
  1141. $sql = 'SELECT * FROM atable WHERE intColumn = '
  1142. . $db->quote($value, 'INTEGER');
  1143. ]]></programlisting>
  1144. </example>
  1145. <para>
  1146. Każda klasa <classname>Zend_Db_Adapter</classname> ma zapisane nazwy numerycznych
  1147. typów danych <acronym>SQL</acronym> odpowiednio do swojego rodzaju
  1148. <acronym>RDBMS</acronym>.
  1149. Zamiast tego można w tym miejscu również korzystać ze stałych
  1150. <constant>Zend_Db::INT_TYPE</constant>,
  1151. <constant>Zend_Db::BIGINT_TYPE</constant> oraz
  1152. <constant>Zend_Db::FLOAT_TYPE</constant> aby uniezależnić kod
  1153. od rodzaju bazy danych.
  1154. </para>
  1155. <para>
  1156. <classname>Zend_Db_Table</classname> automatycznie określa
  1157. typy danych <acronym>SQL</acronym>
  1158. dla metody <methodname>quote()</methodname> podczas generowania
  1159. zapytań <acronym>SQL</acronym> odnoszących się do klucza pierwotnego tabeli.
  1160. </para>
  1161. </sect3>
  1162. <sect3 id="zend.db.adapter.quoting.quote-into">
  1163. <title>Użycie quoteInto()</title>
  1164. <para>
  1165. Najbardziej typowym przypadkiem użycia cudzysłowu do ograniczania zmiennych jest
  1166. umieszczenie zmiennej <acronym>PHP</acronym> w zapytaniu <acronym>SQL</acronym>.
  1167. Aby to osiągnąć można użyć metody <methodname>quoteInto()</methodname>.
  1168. Przyjmuje ona dwa argumenty: pierwszym jest łańcuch znaków zawierający
  1169. symbol "?", który zostanie zastąpiony; drugim jest zmienna
  1170. <acronym>PHP</acronym>, która ma trafić na miejsce "?".
  1171. </para>
  1172. <para>
  1173. Zastępowany symbol jest używany przez wielu producentów baz danych do oznaczenia
  1174. pozycyjnych parametrów wiązanych ale metoda <methodname>quoteInto()</methodname>
  1175. jedynie emuluje takie parametry. W wyniku jej działania wartość zmiennej jest
  1176. zwyczajnie umieszczana w łańcuchu z zapytaniem, po wstępnym uniknięciu specjalnych
  1177. znaków i umieszczeniu w cudzysłowie. Prawdziwa implementacja parametrów wiązanych
  1178. zakłada separację łańcucha znaków polecenia <acronym>SQL</acronym> od samych
  1179. parametrów oraz wstępne parsowanie polecenia na serwerze bazy danych.
  1180. </para>
  1181. <example id="zend.db.adapter.quoting.quote-into.example">
  1182. <title>Użycie quoteInto()</title>
  1183. <programlisting language="php"><![CDATA[
  1184. $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
  1185. echo $sql;
  1186. // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
  1187. ]]></programlisting>
  1188. </example>
  1189. <para>
  1190. Można użyć opcjonalnego, trzeciego parametru metody
  1191. <methodname>quoteInto()</methodname>
  1192. aby określić typ danych <acronym>SQL</acronym>.
  1193. Numeryczne typy danych (w przeciwieństwie
  1194. do innych typów) nie podlegają umieszczaniu w cudzysłowie.
  1195. </para>
  1196. <example id="zend.db.adapter.quoting.quote-into.example-2">
  1197. <title>Użycie quoteInto() z podaniem typu danych SQL</title>
  1198. <programlisting language="php"><![CDATA[
  1199. $sql = $db
  1200. ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
  1201. echo $sql;
  1202. // SELECT * FROM bugs WHERE reported_by = 1234
  1203. ]]></programlisting>
  1204. </example>
  1205. </sect3>
  1206. <sect3 id="zend.db.adapter.quoting.quote-identifier">
  1207. <title>Użycie quoteIdentifier()</title>
  1208. <para>
  1209. Wartości nie są jedyną częścią składni polecenia <acronym>SQL</acronym>, która może
  1210. być zmienna. W przypadku użycia zmiennych <acronym>PHP</acronym> do określenia
  1211. tabel, kolumn lub innych identyfikatorów zapytania <acronym>SQL</acronym>,
  1212. może zajść potrzeba umieszczenia również tych elementów w cudzysłowie.
  1213. Domyślnie identyfikatory <acronym>SQL</acronym> muszą przestrzegać określonych
  1214. reguł - podobnie jak w <acronym>PHP</acronym> oraz większości innych
  1215. języków programowania. Przykładem takiej reguły jest zakaz używania spacji
  1216. lub określonych znaków interpunkcyjnych, specjalnych ani też znaków spoza ASCII.
  1217. Poza tym istnieje lista określonych słów, które służą
  1218. do tworzenia zapytań - ich też nie powinno się używać jako identyfikatorów.
  1219. </para>
  1220. <para>
  1221. Mimo to <acronym>SQL</acronym> posiada
  1222. <emphasis>ograniczone identyfikatory</emphasis> (delimited identifiers),
  1223. dzięki którym można skorzystać z większego wachlarza znaków
  1224. do nazywania obiektów.
  1225. Jeśli określony identyfikator zostanie ograniczony odpowiednim
  1226. rodzajem cudzysłowu to będzie można użyć znaków, które bez tego ograniczenia
  1227. spowodowałyby błąd. Identyfikatory ograniczone mogą zawierać spacje,
  1228. znaki interpunkcyjne czy lokalne litery.
  1229. Można nawet używać zarezerwowanych słów <acronym>SQL</acronym> jeśli
  1230. zostaną otoczone odpowiednimi znakami ograniczającymi.
  1231. </para>
  1232. <para>
  1233. Metoda <methodname>quoteIdentifier()</methodname> zachowuje się podobnie jak
  1234. <methodname>quote()</methodname> ale otacza podany łańcuch znaków za pomocą
  1235. znaków ograniczających zgodnie z rodzajem używanego adaptera.
  1236. Standardowy <acronym>SQL</acronym>
  1237. używa podwójnego cudzysłowu (") jako znaku ograniczającego a większość systemów
  1238. zarządzania bazą danych podąża za tym przykładem. MySQL domyślnie używa znaków
  1239. back-tick (`). Metoda <methodname>quoteIdentifier()</methodname> dokonuje również
  1240. unikania znaków specjalnych znajdujących się w przekazanym argumencie.
  1241. </para>
  1242. <example id="zend.db.adapter.quoting.quote-identifier.example">
  1243. <title>Użycie quoteIdentifier()</title>
  1244. <programlisting language="php"><![CDATA[
  1245. // można użyć tabeli o nazwie takiej samej jak słowo zarezerwowane SQL
  1246. $tableName = $db->quoteIdentifier("order");
  1247. $sql = "SELECT * FROM $tableName";
  1248. echo $sql
  1249. // SELECT * FROM "order"
  1250. ]]></programlisting>
  1251. </example>
  1252. <para>
  1253. W <acronym>SQL</acronym> identyfikatory ograniczone są wrażliwe na wielkość liter,
  1254. w przeciwieństwie do zwykłych identyfikatorów. Przez to, należy upewnić się, że
  1255. pisownia identyfikatora w 100% odpowiada pisowni zapisanej w schemacie, włącznie
  1256. z wielkością liter.
  1257. </para>
  1258. <para>
  1259. W większości przypadków gdzie polecenie <acronym>SQL</acronym> jest
  1260. generowane wewnątrz klas <classname>Zend_Db</classname>,
  1261. domyślnym zachowaniem jest automatyczne ograniczanie
  1262. identyfikatorów. Można to zmienić poprzez opcję
  1263. <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> wywoływaną
  1264. podczas inicjalizacji adaptera.
  1265. Więcej informacji:
  1266. <xref linkend="zend.db.adapter.connecting.parameters.example2" />.
  1267. </para>
  1268. </sect3>
  1269. </sect2>
  1270. <sect2 id="zend.db.adapter.transactions">
  1271. <title>Kontrolowanie transakcji bazy danych</title>
  1272. <para>
  1273. W świecie baz danych transakcja to zbiór operacji, który może zostać zapisany
  1274. bądź cofnięty za pomocą jednej instrukcji, nawet jeśli zmiany wynikające z tych operacji
  1275. dotyczyły wielu tabel. Wszystkie zapytania do bazy danych są przeprowadzane w
  1276. kontekście transakcji. Jeśli nie są zarządzane jawnie to sterownik bazy danych używa ich
  1277. w sposób przezroczysty dla użytkownika. Takie podejście nazywa się trybem
  1278. <emphasis>auto-commit</emphasis> - sterownik bazy danych tworzy transakcje dla każdego
  1279. tworzonego polecenia i zapisuje efekty jego działania po każdym wywołaniu polecenia
  1280. <acronym>SQL</acronym>. Domyślnie wszystkie adaptery <classname>Zend_Db</classname>
  1281. działają w trybie <emphasis>auto-commit</emphasis>.
  1282. </para>
  1283. <para>
  1284. Można również bezpośrednio wskazać początek i koniec transakcji i w ten sposób
  1285. kontrolować ilość zapytań <acronym>SQL</acronym> jakie trafiają do zapisania (bądź
  1286. cofnięcia) jako pojedyncza operacja. Aby rozpocząć transakcję należy wywołać metodę
  1287. <methodname>beginTransaction()</methodname>. Następujące po niej polecenia
  1288. <acronym>SQL</acronym> są wykonywane w kontekście wspólnej transakcji do momentu
  1289. zasygnalizowania jej końca.
  1290. </para>
  1291. <para>
  1292. Aby zakończyć transakcję należy użyć metody <methodname>commit()</methodname> lub
  1293. <methodname>rollBack()</methodname>.
  1294. Pierwsza z nich powoduje zapisanie zmian wynikających
  1295. z operacji przeprowadzonych w czasie transakcji.
  1296. Oznacza to, że efekty tych zmian będą
  1297. widoczne w wynikach zapytań wywołanych w ramach innych transakcji.
  1298. </para>
  1299. <para>
  1300. Metoda <methodname>rollBack()</methodname> dokonuje odwrotnej operacji: cofa zmiany
  1301. dokonane podczas transakcji.
  1302. W efekcie wszystkie dane zmienione podczas transakcji zostają cofnięte do
  1303. wartości z momentu przed jej rozpoczęciem. Cofnięcie zmian jednej transakcji nie
  1304. ma wpływu na zmiany dokonane przez inną transakcję trwającą nawet w tym samym czasie.
  1305. </para>
  1306. <para>
  1307. Po skończonej transakcji <classname>Zend_Db_Adapter</classname> wraca
  1308. do trybu auto-commit do momentu ponownego wywołania metody
  1309. <methodname>beginTransaction()</methodname> i ręcznego
  1310. rozpoczęcia nowej transakcji.
  1311. </para>
  1312. <example id="zend.db.adapter.transactions.example">
  1313. <title>Kontrolowanie transakcjami dla zachowania spójności</title>
  1314. <programlisting language="php"><![CDATA[
  1315. // Ręczne rozpoczęcie transakcji
  1316. $db->beginTransaction();
  1317. try {
  1318. // Próba wywołania jednego bądź wielu zapytań:
  1319. $db->query(...);
  1320. $db->query(...);
  1321. $db->query(...);
  1322. // Jeśli wszystkie odniosły sukces - zapisanie transakcji, dzięki czemu wszystkie rezultaty
  1323. // zostaną zapisane za jednym razem.
  1324. $db->commit();
  1325. } catch (Exception $e) {
  1326. // Jeśli któreś z zapytań zakończyło się niepowodzeniem i został wyrzucony wyjątek, należy
  1327. // cofnąć całą transakcję odwracając zmiany w niej dokonane (nawet te które zakończyły się
  1328. // sukcesem). Przez to albo wszystkie zmiany zostają zapisane albo żadna.
  1329. $db->rollBack();
  1330. echo $e->getMessage();
  1331. }
  1332. ]]></programlisting>
  1333. </example>
  1334. </sect2>
  1335. <sect2 id="zend.db.adapter.list-describe">
  1336. <title>Uzyskiwanie listy i opisu tabel</title>
  1337. <para>
  1338. Metoda <methodname>listTables()</methodname> zwraca tablicę łańcuchów znakowych,
  1339. zawierającą wszystkie tabele w bieżącej bazie danych.
  1340. </para>
  1341. <para>
  1342. Metoda <methodname>describeTable()</methodname> zwraca tablicę asocjacyjną metadanych
  1343. tabeli. Jako argument należy podać nazwę tabeli.
  1344. Drugi argument jest opcjonalny - wskazuje
  1345. nazwę schematu w którym tabela się znajduje.
  1346. </para>
  1347. <para>
  1348. Kluczami zwracanej tablicy asocjacyjnej są nazwy kolumn tabeli. Wartość przy każdej
  1349. kolumnie to następna tablica asocjacyjna z następującymi kluczami i wartościami:
  1350. </para>
  1351. <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
  1352. <title>Metadane zwracane przez describeTable()</title>
  1353. <tgroup cols="3" align="left" colsep="1" rowsep="1">
  1354. <thead>
  1355. <row>
  1356. <entry>Klucz</entry>
  1357. <entry>Typ</entry>
  1358. <entry>Opis</entry>
  1359. </row>
  1360. </thead>
  1361. <tbody>
  1362. <row>
  1363. <entry><constant>SCHEMA_NAME</constant></entry>
  1364. <entry>(string)</entry>
  1365. <entry>Nazwa schematu bazy danych, w którym tabela się znajduje.</entry>
  1366. </row>
  1367. <row>
  1368. <entry><constant>TABLE_NAME</constant></entry>
  1369. <entry>(string)</entry>
  1370. <entry>Nazwa tabeli zawierającej daną kolumnę.</entry>
  1371. </row>
  1372. <row>
  1373. <entry><constant>COLUMN_NAME</constant></entry>
  1374. <entry>(string)</entry>
  1375. <entry>Nazwa kolumny.</entry>
  1376. </row>
  1377. <row>
  1378. <entry><constant>COLUMN_POSITION</constant></entry>
  1379. <entry>(integer)</entry>
  1380. <entry>Liczba porządkowa wskazująca na miejsce kolumny w tabeli.</entry>
  1381. </row>
  1382. <row>
  1383. <entry><constant>DATA_TYPE</constant></entry>
  1384. <entry>(string)</entry>
  1385. <entry>Nazwa typu danych dozwolonych w kolumnie.</entry>
  1386. </row>
  1387. <row>
  1388. <entry><constant>DEFAULT</constant></entry>
  1389. <entry>(string)</entry>
  1390. <entry>Domyślna wartość kolumny (jeśli istnieje).</entry>
  1391. </row>
  1392. <row>
  1393. <entry><constant>NULLABLE</constant></entry>
  1394. <entry>(boolean)</entry>
  1395. <entry>
  1396. <constant>TRUE</constant> jeśli columna dopuszcza wartości
  1397. <acronym>SQL</acronym>
  1398. <constant>NULL</constant>, <constant>FALSE</constant>
  1399. jeśli kolumna zawiera
  1400. ograniczenie <constant>NOT</constant> <constant>NULL</constant>.
  1401. </entry>
  1402. </row>
  1403. <row>
  1404. <entry><constant>LENGTH</constant></entry>
  1405. <entry>(integer)</entry>
  1406. <entry>
  1407. Dopuszczalny rozmiar kolumny, w formie zgłoszonej przez serwer
  1408. bazy danych.
  1409. </entry>
  1410. </row>
  1411. <row>
  1412. <entry><constant>SCALE</constant></entry>
  1413. <entry>(integer)</entry>
  1414. <entry>
  1415. Skala typów <acronym>SQL</acronym> NUMERIC lub
  1416. <constant>DECIMAL</constant>.
  1417. </entry>
  1418. </row>
  1419. <row>
  1420. <entry><constant>PRECISION</constant></entry>
  1421. <entry>(integer)</entry>
  1422. <entry>
  1423. Precyzja typów <acronym>SQL</acronym> NUMERIC
  1424. lub <constant>DECIMAL</constant>.
  1425. </entry>
  1426. </row>
  1427. <row>
  1428. <entry><constant>UNSIGNED</constant></entry>
  1429. <entry>(boolean)</entry>
  1430. <entry>
  1431. <constant>TRUE</constant> jeśli typ danych liczbowych ma klauzulę
  1432. <constant>UNSIGNED</constant>.
  1433. </entry>
  1434. </row>
  1435. <row>
  1436. <entry><constant>PRIMARY</constant></entry>
  1437. <entry>(boolean)</entry>
  1438. <entry>
  1439. <constant>TRUE</constant> jeśli kolumna jest częścią
  1440. klucza pierwotnego tabeli.
  1441. </entry>
  1442. </row>
  1443. <row>
  1444. <entry><constant>PRIMARY_POSITION</constant></entry>
  1445. <entry>(integer)</entry>
  1446. <entry>
  1447. Liczba porządkowa (min. 1) oznaczająca pozycję
  1448. kolumny w kluczu pierwotnym.
  1449. </entry>
  1450. </row>
  1451. <row>
  1452. <entry><constant>IDENTITY</constant></entry>
  1453. <entry>(boolean)</entry>
  1454. <entry>
  1455. <constant>TRUE</constant> jeśli kolumna korzysta
  1456. z wartości automatycznie generowanych.
  1457. </entry>
  1458. </row>
  1459. </tbody>
  1460. </tgroup>
  1461. </table>
  1462. <note>
  1463. <title>Pole metadanych IDENTITY w różnych systemach zarządzania bazą danych</title>
  1464. <para>
  1465. Pole metadanych IDENTITY zostało wybrane jako ogólny
  1466. termin określający relację do klucza tabeli. Może być znany
  1467. pod następującymi nazwami:
  1468. </para>
  1469. <itemizedlist>
  1470. <listitem>
  1471. <para>
  1472. <constant>IDENTITY</constant> - DB2, MSSQL
  1473. </para>
  1474. </listitem>
  1475. <listitem>
  1476. <para>
  1477. <constant>AUTO_INCREMENT</constant> - MySQL
  1478. </para>
  1479. </listitem>
  1480. <listitem>
  1481. <para>
  1482. <constant>SERIAL</constant> - PostgreSQL
  1483. </para>
  1484. </listitem>
  1485. <listitem>
  1486. <para>
  1487. <constant>SEQUENCE</constant> - Oracle
  1488. </para>
  1489. </listitem>
  1490. </itemizedlist>
  1491. </note>
  1492. <para>
  1493. Jeśli w bazie danych nie istnieje tabela i schemat o podanych nazwach to
  1494. <methodname>describeTable()</methodname> zwraca pustą tablicę.
  1495. </para>
  1496. </sect2>
  1497. <sect2 id="zend.db.adapter.closing">
  1498. <title>Zamykanie połączenia</title>
  1499. <para>
  1500. Najczęściej nie ma potrzeby zamykać połączenia z bazą danych. <acronym>PHP</acronym>
  1501. automatycznie czyści wszystkie zasoby pod koniec działania. Rozszerzenia bazy danych są
  1502. zaprojektowane w taki sposób aby połączenie zostało zamknięte w momencie usunięcia
  1503. referencji do obiektu zasobu.
  1504. </para>
  1505. <para>
  1506. Jednak w przypadku skryptu <acronym>PHP</acronym>, którego czas wykonania jest znaczący,
  1507. który inicjuje wiele połączeń z bazą danych, może zajść potrzeba
  1508. ręcznego zamknięcia połączenia aby ograniczyć wykorzystanie
  1509. zasobów serwera bazy danych. Aby wymusić zamknięcie połączenia
  1510. z bazą danych należy użyć metody adaptera <methodname>closeConnection()</methodname>.
  1511. </para>
  1512. <para>
  1513. Od wersji 1.7.2 istnieje możliwość sprawdzenia czy w obecnej chwili
  1514. połączenie z serwerem bazy danych występuje za pomocą metody
  1515. <methodname>isConnected()</methodname>.
  1516. Jej rezultat oznacza czy zasób połączenia został ustanowiony i nie został zamknięty.
  1517. Ta metoda nie jest zdolna sprawdzić zamknięcia połączenia od strony
  1518. serwera bazy danych.
  1519. Dzięki użyciu jej w wewnętrznych metodach zamykających połączenie
  1520. można dokonywać wielokrotnego zamknięcia połączenia bez ryzyka wystąpienia błędów.
  1521. Przed wersją 1.7.2 było to możliwe jedynie w
  1522. przypadku adapterów <acronym>PDO</acronym>.
  1523. </para>
  1524. <example id="zend.db.adapter.closing.example">
  1525. <title>Zamknięcie połączenia z bazą danych</title>
  1526. <programlisting language="php"><![CDATA[
  1527. $db->closeConnection();
  1528. ]]></programlisting>
  1529. </example>
  1530. <note>
  1531. <title>Czy Zend_Db wspiera połączenia trwałe (Persistent Connections)?</title>
  1532. <para>
  1533. Tak, trwałe połączenia są wspierane poprzez flagę <property>persistent</property>
  1534. ustawioną na wartość <constant>TRUE</constant> w konfiguracji
  1535. adaptera <classname>Zend_Db</classname> (a nie sterownika bazy danych).
  1536. </para>
  1537. <example id="zend.db.adapter.connecting.persistence.example">
  1538. <title>Użycie flagi stałego połączenia z adapterem Oracle</title>
  1539. <programlisting language="php"><![CDATA[
  1540. $db = Zend_Db::factory('Oracle', array(
  1541. 'host' => '127.0.0.1',
  1542. 'username' => 'webuser',
  1543. 'password' => 'xxxxxxxx',
  1544. 'dbname' => 'test',
  1545. 'persistent' => true
  1546. ));
  1547. ]]></programlisting>
  1548. </example>
  1549. <para>
  1550. Należy zwrócić uwagę, że używanie połączeń stałych może zwiększyć ilość
  1551. nieużywanych połączeń na serwerze bazy danych. Przez to, korzyści
  1552. w wydajności (wynikające z wykluczenia potrzeby nawiązywania połączenia
  1553. przy każdym żądaniu) mogą zostać skutecznie przeważone przez problemy
  1554. spowodowane przez tą technikę.
  1555. </para>
  1556. <para>
  1557. Połączenia z bazą danych mają stany. Oznacza to, że pewne obiekty na serwerze
  1558. bazy danych istnieją w kontekście sesji. Chodzi o blokady, zmienne użytkownika,
  1559. tabele tymczasowe, informacje o ostatnio wykonanym zapytaniu - takie jak
  1560. ilość pobranych wierszy, ostatnia wygenerowana wartość identyfikatora. W
  1561. przypadku użycia połączeń stałych istnieje ryzyko, że aplikacja uzyska
  1562. dostęp do niepoprawnych bądź zastrzeżonych danych, które zostały utworzone
  1563. podczas poprzedniego żądania.
  1564. </para>
  1565. <para>
  1566. W obecnym stanie jedynie adaptery Oracle, DB2 oraz <acronym>PDO</acronym>
  1567. (zgodnie z dokumentacją <acronym>PHP</acronym>) wspierają połączenia stałe
  1568. w <classname>Zend_Db</classname>.
  1569. </para>
  1570. </note>
  1571. </sect2>
  1572. <sect2 id="zend.db.adapter.other-statements">
  1573. <title>Wykonywanie innych poleceń na bazie danych</title>
  1574. <para>
  1575. Podczas tworzenia kodu może zajść potrzeba uzyskania dostępu bezpośrednio do
  1576. obiektu połączenia tak jak udostępnia to używane rozszerzenie bazy danych
  1577. <acronym>PHP</acronym>. Niektóre rozszerzenia mogą oferować funkcje nieodzwierciedlone
  1578. w metodach klasy <classname>Zend_Db_Adapter_Abstract</classname>.
  1579. </para>
  1580. <para>
  1581. Wszystkie polecenia <acronym>SQL</acronym> w <classname>Zend_Db</classname>
  1582. są wywoływane poprzez instrukcje preparowane (prepared statement). Jednak niektóre
  1583. funkcje bazy danych są z nimi niekompatybilne. Polecenia <acronym>DDL</acronym> takie
  1584. jak CREATE czy ALTER nie mogą być wywoływane w ten sposób w MySQL. Dodatkowo polecenia
  1585. <acronym>SQL</acronym> nie korzystają z
  1586. <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">cache'u zapytań
  1587. MySQL (MySQL Query Cache)</ulink> dla wersji wcześniejszej niż MySQL 5.1.17.
  1588. </para>
  1589. <para>
  1590. Większość rozszerzeń baz danych <acronym>PHP</acronym> umożliwia wywoływanie poleceń
  1591. <acronym>SQL</acronym> bez preparowania. W przypadku <acronym>PDO</acronym> jest to
  1592. możliwe poprzez metodę <methodname>exec()</methodname>. Aby uzyskać dostęp do obiektu
  1593. połączenia odpowiedniego rozszerzenia <acronym>PHP</acronym> należy wywołać metodę
  1594. <methodname>getConnection()</methodname>.
  1595. </para>
  1596. <example id="zend.db.adapter.other-statements.example">
  1597. <title>Wywołanie polecenia niepreparowanego dla adaptera PDO</title>
  1598. <programlisting language="php"><![CDATA[
  1599. $result = $db->getConnection()->exec('DROP TABLE bugs');
  1600. ]]></programlisting>
  1601. </example>
  1602. <para>
  1603. W podobny sposób można korzystać z innych metod szczególnych dla konkretnego
  1604. rozszerzenia <acronym>PHP</acronym>. Należy jednak mieć w pamięci, iż w ten
  1605. sposób ogranicza się tworzoną aplikację do współpracy z interfejsem oferowanym
  1606. jedynie przez konkretne rozszerzenie konkretnej bazy danych.
  1607. </para>
  1608. <para>
  1609. W przyszłych wersjach <classname>Zend_Db</classname> planowane jest umieszczanie
  1610. dodatkowych metod służących do obejmowania funkcjonalności wspólnych dla wielu
  1611. rozszerzeń baz danych <acronym>PHP</acronym> ale wsteczna kompatybilność zostanie
  1612. zachowana.
  1613. </para>
  1614. </sect2>
  1615. <sect2 id="zend.db.adapter.server-version">
  1616. <title>Pobranie wersji serwera</title>
  1617. <para>
  1618. Począwszy od wersji 1.7.2 można pobrać wersję serwera bazy danych w formie podobnej do
  1619. numeru wersji <acronym>PHP</acronym> tak aby można było skorzystać z funkcji
  1620. <methodname>version_compare()</methodname>. Jeśli taka informacja nie jest dostępna
  1621. to zostanie zwrócona wartość <constant>NULL</constant>.
  1622. </para>
  1623. <example id="zend.db.adapter.server-version.example">
  1624. <title>Weryfikacja wersji serwera przed wywołaniem zapytania</title>
  1625. <programlisting language="php"><![CDATA[
  1626. $version = $db->getServerVersion();
  1627. if (!is_null($version)) {
  1628. if (version_compare($version, '5.0.0', '>=')) {
  1629. // wykonanie zapytania
  1630. } else {
  1631. // wykonanie innego zapytania
  1632. }
  1633. } else {
  1634. // wersja serwera niedostępna
  1635. }
  1636. ]]></programlisting>
  1637. </example>
  1638. </sect2>
  1639. <sect2 id="zend.db.adapter.adapter-notes">
  1640. <title>Informacje o konkretnych adapterach</title>
  1641. <para>
  1642. Ten akapit wymienia różnice pomiędzy klasami adapterów, z istnienia których
  1643. należy sobie zdawać sprawę.
  1644. </para>
  1645. <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
  1646. <title>IBM DB2</title>
  1647. <itemizedlist>
  1648. <listitem>
  1649. <para>
  1650. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1651. należy użyć nazwy 'Db2'.
  1652. </para>
  1653. </listitem>
  1654. <listitem>
  1655. <para>
  1656. Ten adapter używa rozszerzenia <acronym>PHP</acronym> ibm_db2.
  1657. </para>
  1658. </listitem>
  1659. <listitem>
  1660. <para>
  1661. IBM DB2 wspiera sekwencje oraz klucze automatycznie zwiększające.
  1662. Przez to argumenty dla <methodname>lastInsertId()</methodname> są
  1663. opcjonalne. Jeśli nie poda się argumentów adapter zwróci ostatnią
  1664. wartość wygenerowaną dla klucza automatycznego. Jeśli argumenty zostaną
  1665. podane to adapter zwróci ostatnią wartość wygenerowaną przez sekwencję
  1666. o nazwie zgodnej z konwencją
  1667. '<emphasis>tabela</emphasis>_<emphasis>kolumna</emphasis>_seq'.
  1668. </para>
  1669. </listitem>
  1670. </itemizedlist>
  1671. </sect3>
  1672. <sect3 id="zend.db.adapter.adapter-notes.mysqli">
  1673. <title>MySQLi</title>
  1674. <itemizedlist>
  1675. <listitem>
  1676. <para>
  1677. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1678. należy użyć nazwy 'Mysqli'.
  1679. </para>
  1680. </listitem>
  1681. <listitem>
  1682. <para>
  1683. Ten adapter używa rozszerzenia <acronym>PHP</acronym> mysqli.
  1684. </para>
  1685. </listitem>
  1686. <listitem>
  1687. <para>
  1688. MySQL nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
  1689. ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
  1690. automatycznego. Metoda <methodname>lastSequenceId()</methodname>
  1691. zwraca <constant>NULL</constant>.
  1692. </para>
  1693. </listitem>
  1694. </itemizedlist>
  1695. </sect3>
  1696. <sect3 id="zend.db.adapter.adapter-notes.oracle">
  1697. <title>Oracle</title>
  1698. <itemizedlist>
  1699. <listitem>
  1700. <para>
  1701. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1702. należy użyć nazwy 'Oracle'.
  1703. </para>
  1704. </listitem>
  1705. <listitem>
  1706. <para>
  1707. Ten adapter używa rozszerzenia <acronym>PHP</acronym> oci8.
  1708. </para>
  1709. </listitem>
  1710. <listitem>
  1711. <para>
  1712. Oracle nie wspiera kluczy automatycznych więc należy podać nazwę
  1713. sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
  1714. <methodname>lastSequenceId()</methodname>.
  1715. </para>
  1716. </listitem>
  1717. <listitem>
  1718. <para>
  1719. Rozszerzenie Oracle nie wspiera parametrów pozycyjnych. Należy
  1720. używać nazwanych parametrów.
  1721. </para>
  1722. </listitem>
  1723. <listitem>
  1724. <para>
  1725. Obecnie, opcja <constant>Zend_Db::CASE_FOLDING</constant> nie jest
  1726. zaimplementowana w tym adapterze. Aby użyć tej opcji z Oracle zalecane
  1727. jest korzystanie z adaptera <acronym>PDO</acronym> OCI.
  1728. </para>
  1729. </listitem>
  1730. <listitem>
  1731. <para>
  1732. Domyślnie pola LOB są zwracane jako obiekty OCI-Lob. Można ustawić
  1733. pobieranie ich w formie łańcuchów znakowych dla wszystkich żądań
  1734. poprzez opcję sterownika '<property>lob_as_string</property>'. Aby
  1735. jednorazowo pobrać obiekt Lob jako string należy użyć metody
  1736. <methodname>setLobAsString(boolean)</methodname> na adapterze lub
  1737. na obiekcie zapytania.
  1738. </para>
  1739. </listitem>
  1740. </itemizedlist>
  1741. </sect3>
  1742. <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
  1743. <title>Microsoft SQL Server</title>
  1744. <itemizedlist>
  1745. <listitem>
  1746. <para>
  1747. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1748. należy użyć nazwy 'Sqlsrv'.
  1749. </para>
  1750. </listitem>
  1751. <listitem>
  1752. <para>
  1753. Ten adapter używa rozszerzenia <acronym>PHP</acronym> sqlsrv.
  1754. </para>
  1755. </listitem>
  1756. <listitem>
  1757. <para>
  1758. Microsoft <acronym>SQL</acronym> Server nie wspiera sekwencji więc
  1759. <methodname>lastInsertId()</methodname> ignoruje argument określający
  1760. klucz pierwotny i zwraca ostatnią wartość wygenerowaną przez automatyczny
  1761. klucz (jeśli jest podana nazwa tabeli) lub identyfikator zwrócony przez
  1762. ostatnie polecenie INSERT. Metoda <methodname>lastSequenceId()</methodname>
  1763. zwraca <constant>NULL</constant>.
  1764. </para>
  1765. </listitem>
  1766. <listitem>
  1767. <para>
  1768. <classname>Zend_Db_Adapter_Sqlsrv</classname> ustawia opcję
  1769. <constant>QUOTED_IDENTIFIER ON</constant> bezpośrednio po połączeniu się
  1770. z bazą danych <acronym>SQL</acronym> Server. To powoduje, że sterownik
  1771. zaczyna używać standardowego znaku cudzysłowu (<emphasis>"</emphasis>) jako
  1772. ograniczenia identyfikatorów zamiast - charakterystycznych dla produktu
  1773. Microsoftu - nawiasów kwadratowych.
  1774. </para>
  1775. </listitem>
  1776. <listitem>
  1777. <para>
  1778. Jednym z kluczy podawanych do tablicy opcji może być
  1779. <property>driver_options</property>
  1780. dzięki czemu można skorzystać z wartości podanych w dokumentacji
  1781. <acronym>SQL</acronym> Server
  1782. <ulink url="http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx">
  1783. http://msdn.microsoft.com/en-us/library/cc296161(SQL.90).aspx</ulink>.
  1784. </para>
  1785. </listitem>
  1786. <listitem>
  1787. <para>
  1788. Dzięki metodzie <methodname>setTransactionIsolationLevel()</methodname>
  1789. można ustawić poziom izolacji transakcji dla bieżącego połączenia.
  1790. Rozpoznawane wartości
  1791. to <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>,
  1792. <constant>SQLSRV_TXN_READ_COMMITTED</constant>,
  1793. <constant>SQLSRV_TXN_REPEATABLE_READ</constant>,
  1794. <constant>SQLSRV_TXN_SNAPSHOT</constant> or
  1795. <constant>SQLSRV_TXN_SERIALIZABLE</constant>.
  1796. </para>
  1797. </listitem>
  1798. <listitem>
  1799. <para>
  1800. Począwszy od Zend Framework 1.9 minimalną wspieraną wersją rozszerzenia
  1801. <acronym>PHP</acronym> Microsoft <acronym>SQL</acronym> Server jest
  1802. 1.0.1924.0. a dla <acronym>MSSQL</acronym> Server Native
  1803. Client - wersja 9.00.3042.00.
  1804. </para>
  1805. </listitem>
  1806. </itemizedlist>
  1807. </sect3>
  1808. <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
  1809. <title>PDO dla IBM DB2 oraz Informix Dynamic Server (IDS)</title>
  1810. <itemizedlist>
  1811. <listitem>
  1812. <para>
  1813. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1814. należy użyć nazwy '<classname>Pdo_Ibm</classname>'.
  1815. </para>
  1816. </listitem>
  1817. <listitem>
  1818. <para>
  1819. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_ibm.
  1820. </para>
  1821. </listitem>
  1822. <listitem>
  1823. <para>
  1824. Należy używać wersji 1.2.2 lub wyższej rozszerzenia PDO_IBM. Zaleca się
  1825. uaktualnienie wcześniejszych wersji poprzez <acronym>PECL</acronym>.
  1826. </para>
  1827. </listitem>
  1828. </itemizedlist>
  1829. </sect3>
  1830. <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
  1831. <title>PDO Microsoft SQL Server</title>
  1832. <itemizedlist>
  1833. <listitem>
  1834. <para>
  1835. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1836. należy użyć nazwy '<classname>Pdo_Mssql</classname>'.
  1837. </para>
  1838. </listitem>
  1839. <listitem>
  1840. <para>
  1841. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_dblib.
  1842. </para>
  1843. </listitem>
  1844. <listitem>
  1845. <para>
  1846. Microsoft <acronym>SQL</acronym> Server nie wspiera sekwencji więc
  1847. <methodname>lastInsertId()</methodname> ignoruje argument określający
  1848. klucz pierwotny i zwraca ostatnią wartość wygenerowaną przez automatyczny
  1849. klucz (jeśli jest podana nazwa tabeli) lub identyfikator zwrócony przez
  1850. ostatnie polecenie INSERT. Metoda <methodname>lastSequenceId()</methodname>
  1851. zwraca <constant>NULL</constant>.
  1852. </para>
  1853. </listitem>
  1854. <listitem>
  1855. <para>
  1856. W przypadku pracy z łańcuchami znaków unicode zakodowanych w sposób inny
  1857. niż UCS-2 (czyli również w formie UTF-8), może zajść potrzeba dokonania
  1858. konwersji w kodzie aplikacji lub przechowywania
  1859. danych w kolumnach binarnych.
  1860. Aby uzyskać więcej informacji można skorzystać z
  1861. <ulink url="http://support.microsoft.com/kb/232580">Microsoft's Knowledge
  1862. Base</ulink>.
  1863. </para>
  1864. </listitem>
  1865. <listitem>
  1866. <para>
  1867. <classname>Zend_Db_Adapter_Pdo_Mssql</classname> ustawia opcję
  1868. <constant>QUOTED_IDENTIFIER ON</constant> bezpośrednio po połączeniu się
  1869. z bazą danych <acronym>SQL</acronym> Server. To powoduje, że sterownik
  1870. zaczyna używać standardowego znaku cudzysłowu (<emphasis>"</emphasis>) jako
  1871. ograniczenia identyfikatorów zamiast - charakterystycznych dla produktu
  1872. Microsoftu - nawiasów kwadratowych.
  1873. </para>
  1874. </listitem>
  1875. <listitem>
  1876. <para>
  1877. Adapter rozpoznaje klucz <property>pdoType</property> w tablicy opcji. Jego
  1878. wartość może wynosić "mssql" (domyślnie), "dblib", "freetds", lub "sybase".
  1879. To wpływa na prefiks <acronym>DSN</acronym> używany przez
  1880. adapter do utworzenia łańcucha połączenia.
  1881. Wartości "freetds" oraz "sybase" powodują utworzenie prefiksu
  1882. "sybase:" używanego przez biblioteki
  1883. <ulink url="http://www.freetds.org/">FreeTDS</ulink>.
  1884. Należy zapoznać się z informacjami dotyczącymi prefiksów
  1885. <acronym>DSN</acronym>
  1886. używanymi przez ten sterownik pod adresem
  1887. <ulink url="http://www.php.net/manual/en/ref.pdo-dblib.connection.php">
  1888. http://www.php.net/manual/en/ref.pdo-dblib.connection.php</ulink>
  1889. </para>
  1890. </listitem>
  1891. </itemizedlist>
  1892. </sect3>
  1893. <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
  1894. <title>PDO MySQL</title>
  1895. <itemizedlist>
  1896. <listitem>
  1897. <para>
  1898. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1899. należy użyć nazwy '<classname>Pdo_Mysql</classname>'.
  1900. </para>
  1901. </listitem>
  1902. <listitem>
  1903. <para>
  1904. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_mysql.
  1905. </para>
  1906. </listitem>
  1907. <listitem>
  1908. <para>
  1909. MySQL nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
  1910. ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
  1911. automatycznego. Metoda <methodname>lastSequenceId()</methodname>
  1912. zwraca <constant>NULL</constant>.
  1913. </para>
  1914. </listitem>
  1915. </itemizedlist>
  1916. </sect3>
  1917. <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
  1918. <title>PDO Oracle</title>
  1919. <itemizedlist>
  1920. <listitem>
  1921. <para>
  1922. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1923. należy użyć nazwy '<classname>Pdo_Oci</classname>'.
  1924. </para>
  1925. </listitem>
  1926. <listitem>
  1927. <para>
  1928. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_oci.
  1929. </para>
  1930. </listitem>
  1931. <listitem>
  1932. <para>
  1933. Oracle nie wspiera kluczy automatycznych więc należy podać nazwę
  1934. sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
  1935. <methodname>lastSequenceId()</methodname>.
  1936. </para>
  1937. </listitem>
  1938. </itemizedlist>
  1939. </sect3>
  1940. <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
  1941. <title>PDO PostgreSQL</title>
  1942. <itemizedlist>
  1943. <listitem>
  1944. <para>
  1945. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1946. należy użyć nazwy '<classname>Pdo_Pgsql</classname>'.
  1947. </para>
  1948. </listitem>
  1949. <listitem>
  1950. <para>
  1951. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_pgsql.
  1952. </para>
  1953. </listitem>
  1954. <listitem>
  1955. <para>
  1956. PostgreSQL wspiera sekwencje oraz klucze automatyczne. Przez to
  1957. podawanie argumentów w <methodname>lastInsertId()</methodname> jest
  1958. opcjonalne. Jeśli nie poda się argumentów adapter zwróci ostatnią
  1959. wartość wygenerowaną dla klucza automatycznego. Jeśli argumenty zostaną
  1960. podane to adapter zwróci ostatnią wartość wygenerowaną przez sekwencję
  1961. o nazwie zgodnej z konwencją
  1962. '<emphasis>tabela</emphasis>_<emphasis>kolumna</emphasis>_seq'.
  1963. </para>
  1964. </listitem>
  1965. </itemizedlist>
  1966. </sect3>
  1967. <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
  1968. <title>PDO SQLite</title>
  1969. <itemizedlist>
  1970. <listitem>
  1971. <para>
  1972. Aby uzyskać ten adapter poprzez metodę <methodname>factory()</methodname>
  1973. należy użyć nazwy '<classname>Pdo_Sqlite</classname>'.
  1974. </para>
  1975. </listitem>
  1976. <listitem>
  1977. <para>
  1978. Ten adapter używa rozszerzeń <acronym>PHP</acronym> pdo and pdo_sqlite.
  1979. </para>
  1980. </listitem>
  1981. <listitem>
  1982. <para>
  1983. SQLite nie wspiera sekwencji więc <methodname>lastInsertId()</methodname>
  1984. ignoruje argumenty i zwraca ostatnią wartość wygenerowaną dla klucza
  1985. automatycznego. Metoda <methodname>lastSequenceId()</methodname>
  1986. zwraca <constant>NULL</constant>.
  1987. </para>
  1988. </listitem>
  1989. <listitem>
  1990. <para>
  1991. Aby połączyć się z bazą danych SQLite2 należy podać
  1992. <command>'sqlite2' => true</command> jako jeden z elementów
  1993. tablicy parametrów podczas tworzenia instancji adaptera
  1994. <classname>Pdo_Sqlite</classname>.
  1995. </para>
  1996. </listitem>
  1997. <listitem>
  1998. <para>
  1999. Aby połączyć się z bazą danych SQLite rezydującą w pamięci
  2000. należy podać <command>'dbname' => ':memory:'</command> jako
  2001. jeden z elementów tablicy parametrów podczas tworzenia instancji adaptera
  2002. <classname>Pdo_Sqlite</classname>.
  2003. </para>
  2004. </listitem>
  2005. <listitem>
  2006. <para>
  2007. Starsze wersje sterownika <acronym>PHP</acronym> SQLite nie wspierają
  2008. poleceń PRAGMA niezbędnych dla zachowania krótkich nazw kolumn w
  2009. wynikach zapytania. W przypadku wystąpienia problemów z zapytaniami JOIN
  2010. polegających na zwracaniu wyników z nazwami kolumn w postaci
  2011. "tabela.kolumna" zaleca się aktualizację <acronym>PHP</acronym> do
  2012. najnowszej wersji.
  2013. </para>
  2014. </listitem>
  2015. </itemizedlist>
  2016. </sect3>
  2017. <sect3 id="zend.db.adapter.adapter-notes.firebird">
  2018. <title>Firebird/Interbase</title>
  2019. <itemizedlist>
  2020. <listitem>
  2021. <para>
  2022. Ten adapter używa rozszerzenia <acronym>PHP</acronym> php_interbase.
  2023. </para>
  2024. </listitem>
  2025. <listitem>
  2026. <para>
  2027. Firebird/Interbase nie wspiera kluczy automatycznych więc należy podać nazwę
  2028. sekwencji w metodzie <methodname>lastInsertId()</methodname> lub
  2029. <methodname>lastSequenceId()</methodname>.
  2030. </para>
  2031. </listitem>
  2032. <listitem>
  2033. <para>
  2034. Obecnie, opcja <constant>Zend_Db::CASE_FOLDING</constant> nie jest
  2035. zaimplementowana w tym adapterze. Identyfikatory bez znaków ograniczających
  2036. są zwracane w postaci wielkich liter.
  2037. </para>
  2038. </listitem>
  2039. <listitem>
  2040. <para>
  2041. Nazwa adaptera to <classname>ZendX_Db_Adapter_Firebird</classname>.
  2042. </para>
  2043. <para>
  2044. Należy pamiętać o użyciu parametru adapterNamespace z wartością
  2045. <classname>ZendX_Db_Adapter</classname>.
  2046. </para>
  2047. <para>
  2048. Zaleca się aktualizację pliku <filename>gds32.dll</filename> (lub
  2049. odpowiednika wersji linux) dostarczanym z <acronym>PHP</acronym> do wersji odpowiadającej
  2050. serwerowi bazy danych. Dla Firebird odpowiednikiem
  2051. <filename>gds32.dll</filename> jest
  2052. <filename>fbclient.dll</filename>.
  2053. </para>
  2054. <para>
  2055. Domyślnie wszystkie identyfikatory (nazwy tabel, kolumn) są zwracane
  2056. wielkimi literami.
  2057. </para>
  2058. </listitem>
  2059. </itemizedlist>
  2060. </sect3>
  2061. </sect2>
  2062. </sect1>
  2063. <!--
  2064. vim:se ts=4 sw=4 et:
  2065. -->