Zend_Db_Adapter.xml 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <!-- EN-Revision: 15207 -->
  4. <sect1 id="zend.db.adapter">
  5. <title>Zend_Db_Adapter</title>
  6. <para>
  7. <classname>Zend_Db</classname> とその関連クラス群は、Zend Framework
  8. において SQL データベースとのインターフェイスを担当します。
  9. <classname>Zend_Db_Adapter</classname> は、PHP アプリケーションから RDBMS
  10. に接続する際に使用する基本クラスです。
  11. RDBMS の種類に応じて、それぞれ個別のアダプタクラスがあります。
  12. </para>
  13. <para>
  14. <classname>Zend_Db</classname> のアダプタは、
  15. ベンダ固有の PHP 拡張モジュールを共通インターフェイスにとりまとめる役割を果たします。
  16. これにより、いちど書いた PHP アプリケーションが
  17. ほんの少しの手間で複数 RDBMS に対応するようになります。
  18. </para>
  19. <para>
  20. アダプタクラスのインターフェイスは、
  21. <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink>
  22. 拡張モジュールのインターフェイスと似ています。
  23. <classname>Zend_Db</classname> では、次の RDBMS 用の PDO ドライバに対するアダプタクラスを用意しています。
  24. </para>
  25. <itemizedlist>
  26. <listitem>
  27. <para>
  28. IBM DB2 および Informix Dynamic Server (IDS) (<ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink> PHP 拡張モジュールを使用)
  29. </para>
  30. </listitem>
  31. <listitem>
  32. <para>
  33. MySQL (<ulink url="http://www.php.net/pdo-mysql">pdo_mysql</ulink> PHP 拡張モジュールを使用)
  34. </para>
  35. </listitem>
  36. <listitem>
  37. <para>
  38. Microsoft SQL Server (<ulink url="http://www.php.net/pdo-mssql">pdo_mssql</ulink> PHP 拡張モジュールを使用)
  39. </para>
  40. </listitem>
  41. <listitem>
  42. <para>
  43. Oracle (<ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink> PHP 拡張モジュールを使用)
  44. </para>
  45. </listitem>
  46. <listitem>
  47. <para>
  48. PostgreSQL (<ulink url="http://www.php.net/pdo-pgsql">pdo_pgsql</ulink> PHP 拡張モジュールを使用)
  49. </para>
  50. </listitem>
  51. <listitem>
  52. <para>
  53. SQLite (<ulink url="http://www.php.net/pdo-sqlite">pdo_sqlite</ulink> PHP 拡張モジュールを使用)
  54. </para>
  55. </listitem>
  56. </itemizedlist>
  57. <para>
  58. さらに、<classname>Zend_Db</classname> では、
  59. 以下の RDBMS 用の拡張モジュールを使用するアダプタクラスも用意しています。
  60. </para>
  61. <itemizedlist>
  62. <listitem>
  63. <para>
  64. MySQL (<ulink url="http://www.php.net/mysqli">mysqli</ulink> を使用します)
  65. </para>
  66. </listitem>
  67. <listitem>
  68. <para>
  69. Oracle (<ulink url="http://www.php.net/oci8">oci8</ulink> を使用します)
  70. </para>
  71. </listitem>
  72. <listitem>
  73. <para>
  74. IBM DB2 および DB2/i5 (<ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink> を使用します)
  75. </para>
  76. </listitem>
  77. <listitem>
  78. <para>
  79. Firebird/Interbase (<ulink url="http://www.php.net/ibase">php_interbase</ulink> を使用します)
  80. </para>
  81. </listitem>
  82. </itemizedlist>
  83. <note>
  84. <para>
  85. <classname>Zend_Db</classname> のアダプタは、どれも PHP の拡張モジュールを使用しています。
  86. <classname>Zend_Db</classname> のアダプタを使用するには、
  87. 対応する PHP 拡張モジュールが使用できる環境でなければなりません。
  88. たとえば、PDO 系の Zend_Db アダプタを使用するのなら、
  89. PDO 拡張モジュールが必要で、
  90. また使用する RDBMS 用の PDO ドライバも必要となります。
  91. </para>
  92. </note>
  93. <sect2 id="zend.db.adapter.connecting">
  94. <title>アダプタを使用したデータベース接続</title>
  95. <para>
  96. ここでは、データベースアダプタのインスタンスを作成する方法を説明します。
  97. これは、PHP アプリケーションから RDBMS
  98. サーバへの接続を確立することに対応します。
  99. </para>
  100. <sect3 id="zend.db.adapter.connecting.constructor">
  101. <title>Zend_Db アダプタのコンストラクタの使用</title>
  102. <para>
  103. コンストラクタを使用して、アダプタのインスタンスを作成することができます。
  104. アダプタのコンストラクタが受け取る引数はひとつで、
  105. 接続を確立するために必要なパラメータを配列で渡します。
  106. </para>
  107. <example id="zend.db.adapter.connecting.constructor.example">
  108. <title>アダプタのコンストラクタの使用</title>
  109. <programlisting role="php"><![CDATA[
  110. $db = new Zend_Db_Adapter_Pdo_Mysql(array(
  111. 'host' => '127.0.0.1',
  112. 'username' => 'webuser',
  113. 'password' => 'xxxxxxxx',
  114. 'dbname' => 'test'
  115. ));
  116. ]]></programlisting>
  117. </example>
  118. </sect3>
  119. <sect3 id="zend.db.adapter.connecting.factory">
  120. <title>Zend_Db のファクトリの使用</title>
  121. <para>
  122. コンストラクタを直接使用する以外の方法として、静的メソッド
  123. <classname>Zend_Db::factory()</classname> を使用することもできます。
  124. このメソッドは、必要に応じて
  125. <link linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>
  126. を使用して動的にアダプタクラスを読み込みます。
  127. </para>
  128. <para>
  129. 最初の引数には、アダプタクラスのベース名を文字列で指定します。
  130. たとえば、文字列 'Pdo_Mysql' は Zend_Db_Adapter_Pdo_Mysql
  131. クラスに対応します。その次の引数は、
  132. アダプタのコンストラクタに指定するのと同じ形式の配列となります。
  133. </para>
  134. <example id="zend.db.adapter.connecting.factory.example">
  135. <title>ファクトリメソッドの使用</title>
  136. <programlisting role="php"><![CDATA[
  137. // 次の文は不要です。Zend_Db_Adapter_Pdo_Mysql ファイルは
  138. // Zend_Db の factory メソッドが読み込みます。
  139. // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
  140. // 自動的に Zend_Db_Adapter_Pdo_Mysql クラスを読み込み、
  141. // そのインスタンスを作成します
  142. $db = Zend_Db::factory('Pdo_Mysql', array(
  143. 'host' => '127.0.0.1',
  144. 'username' => 'webuser',
  145. 'password' => 'xxxxxxxx',
  146. 'dbname' => 'test'
  147. ));
  148. ]]></programlisting>
  149. </example>
  150. <para>
  151. 独自に <classname>Zend_Db_Adapter_Abstract</classname>
  152. の派生クラスを作成し、そのクラス名のプレフィックスが
  153. "Zend_Db_Adapter" でない場合に <code>factory()</code>
  154. でそのアダプタを読み込むには、
  155. 作成したクラス名の先頭の部分をパラメータ配列のキー
  156. 'adapterNamespace' で指定します。
  157. </para>
  158. <example id="zend.db.adapter.connecting.factory.example2">
  159. <title>自作のアダプタクラスをアダプタのファクトリメソッドで使用する方法</title>
  160. <programlisting role="php"><![CDATA[
  161. // アダプタのクラスファイルの読み込みは不要です
  162. // Zend_Db の factory メソッドが読み込みます
  163. // 自動的に MyProject_Db_Adapter_Pdo_Mysql クラスを読み込み、
  164. // インスタンスを作成します
  165. $db = Zend_Db::factory('Pdo_Mysql', array(
  166. 'host' => '127.0.0.1',
  167. 'username' => 'webuser',
  168. 'password' => 'xxxxxxxx',
  169. 'dbname' => 'test',
  170. 'adapterNamespace' => 'MyProject_Db_Adapter'
  171. ));
  172. ]]></programlisting>
  173. </example>
  174. </sect3>
  175. <sect3 id="zend.db.adapter.connecting.factory-config">
  176. <title>Zend_Db ファクトリでの Zend_Config の使用</title>
  177. <para>
  178. <code>factory()</code> メソッドの引数として、
  179. <link linkend="zend.config">Zend_Config</link>
  180. のオブジェクトを渡すこともできます。
  181. </para>
  182. <para>
  183. 最初の引数に config オブジェクトを渡す場合は、そのプロパティに
  184. <code>adapter</code> が含まれているものとします。
  185. そこに、アダプタクラス名を表す文字列を指定します。
  186. また、オプションで <code>params</code> というプロパティも指定することができ、
  187. その配下のサブプロパティとしてアダプタのパラメータ名を指定します。
  188. これは、<code>factory()</code> メソッドの
  189. 2 番目のパラメータを省略した場合にのみ読み込まれます。
  190. </para>
  191. <example id="zend.db.adapter.connecting.factory.example1">
  192. <title>アダプタのファクトリメソッドでの Zend_Config オブジェクトの使用</title>
  193. <para>
  194. 次の例では、配列から <classname>Zend_Config</classname> オブジェクトを作成します。
  195. それ以外にも、
  196. <link linkend="zend.config.adapters.ini">Zend_Config_Ini</link>
  197. や <link linkend="zend.config.adapters.xml">Zend_Config_Xml</link>
  198. などを用いて外部ファイルからデータを読み込むこともできます。
  199. </para>
  200. <programlisting role="php"><![CDATA[
  201. $config = new Zend_Config(
  202. array(
  203. 'database' => array(
  204. 'adapter' => 'Mysqli',
  205. 'params' => array(
  206. 'host' => '127.0.0.1',
  207. 'dbname' => 'test',
  208. 'username' => 'webuser',
  209. 'password' => 'secret',
  210. )
  211. )
  212. )
  213. );
  214. $db = Zend_Db::factory($config->database);
  215. ]]></programlisting>
  216. </example>
  217. <para>
  218. <code>factory()</code> メソッドの 2 番目の引数には、
  219. アダプタのパラメータに対応するエントリをもつ連想配列となります。
  220. この引数はオプションです。最初の引数が <classname>Zend_Config</classname>
  221. である場合は、そこにすべてのパラメータが含まれているものとみなし、
  222. 2 番目の引数は無視されます。
  223. </para>
  224. </sect3>
  225. <sect3 id="zend.db.adapter.connecting.parameters">
  226. <title>アダプタのパラメータ</title>
  227. <para>
  228. <classname>Zend_Db</classname> のアダプタクラスで使用できるパラメータを以下にまとめます。
  229. </para>
  230. <itemizedlist>
  231. <listitem>
  232. <para>
  233. <emphasis role="strong">host</emphasis>:
  234. データベースサーバのホスト名あるいは IP アドレス。
  235. データベースが PHP アプリケーションと同じホスト上で動いている場合は、
  236. 'localhost' あるいは '127.0.0.1' を指定します。
  237. </para>
  238. </listitem>
  239. <listitem>
  240. <para>
  241. <emphasis role="strong">username</emphasis>:
  242. RDBMS サーバへの接続時に使用する認証用アカウントの ID。
  243. </para>
  244. </listitem>
  245. <listitem>
  246. <para>
  247. <emphasis role="strong">password</emphasis>:
  248. RDBMS サーバへの接続時に使用する認証用パスワード。
  249. </para>
  250. </listitem>
  251. <listitem>
  252. <para>
  253. <emphasis role="strong">dbname</emphasis>:
  254. RDBMS サーバ上のデータベースインスタンス名。
  255. </para>
  256. </listitem>
  257. <listitem>
  258. <para>
  259. <emphasis role="strong">port</emphasis>:
  260. RDBMS サーバによっては、管理者が指定した
  261. ポート番号によるネットワーク接続を許可しているものもあります。
  262. このパラメータを使用すると、PHP
  263. アプリケーションが接続時に使用するポート番号を指定できます。
  264. これは RDBMS サーバの設定にあわせなければなりません。
  265. </para>
  266. </listitem>
  267. <listitem>
  268. <para>
  269. <emphasis role="strong">options</emphasis>:
  270. このパラメータは、すべての <classname>Zend_Db_Adapter</classname>
  271. クラスで共通のオプションを連想配列で指定します。
  272. </para>
  273. </listitem>
  274. <listitem>
  275. <para>
  276. <emphasis role="strong">driver_options</emphasis>:
  277. このパラメータは、各データベース拡張モジュールに固有の
  278. 追加オプションを連想配列で指定します。
  279. 典型的な使用例としては、PDO ドライバの属性などがあります。
  280. </para>
  281. </listitem>
  282. <listitem>
  283. <para>
  284. <emphasis role="strong">adapterNamespace</emphasis>:
  285. アダプタクラスの名前の先頭が 'Zend_Db_Adapter'
  286. 以外である場合に、それを指定します。これは、
  287. Zend 以外が作成したアダプタクラスを
  288. <code>factory()</code> メソッドで使いたい場合に指定します。
  289. </para>
  290. </listitem>
  291. </itemizedlist>
  292. <example id="zend.db.adapter.connecting.parameters.example1">
  293. <title>ファクトリでの大文字小文字変換オプションの指定</title>
  294. <para>
  295. このオプションは、定数
  296. <classname>Zend_Db::CASE_FOLDING</classname> で指定します。
  297. これは、PDO や IBM DB2 データベースドライバにおける
  298. <code>ATTR_CASE</code> 属性に対応するもので、
  299. 結果セットの文字列キーの大文字小文字変換を指定します。
  300. 設定できる値は
  301. <classname>Zend_Db::CASE_NATURAL</classname> (デフォルト)、
  302. <classname>Zend_Db::CASE_UPPER</classname> および
  303. <classname>Zend_Db::CASE_LOWER</classname> のいずれかです。
  304. </para>
  305. <programlisting role="php"><![CDATA[
  306. $options = array(
  307. Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
  308. );
  309. $params = array(
  310. 'host' => '127.0.0.1',
  311. 'username' => 'webuser',
  312. 'password' => 'xxxxxxxx',
  313. 'dbname' => 'test',
  314. 'options' => $options
  315. );
  316. $db = Zend_Db::factory('Db2', $params);
  317. ]]></programlisting>
  318. </example>
  319. <example id="zend.db.adapter.connecting.parameters.example2">
  320. <title>ファクトリでの自動クォートオプションの指定</title>
  321. <para>
  322. このオプションは、定数
  323. <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname> で指定します。
  324. この値が <code>true</code> (デフォルト) の場合は、
  325. アダプタが生成する SQL 文中のテーブル名やカラム名、
  326. エイリアスといった識別子をすべてクォートします。これにより、
  327. SQL のキーワードや特殊文字を含む識別子を使用できるようになります。
  328. この値が <code>false</code> の場合は、
  329. 識別子の自動クォートは行いません。
  330. クォートすべき文字を使用している場合は、自分で
  331. <code>quoteIdentifier()</code> メソッドをコールする必要があります。
  332. </para>
  333. <programlisting role="php"><![CDATA[
  334. $options = array(
  335. Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
  336. );
  337. $params = array(
  338. 'host' => '127.0.0.1',
  339. 'username' => 'webuser',
  340. 'password' => 'xxxxxxxx',
  341. 'dbname' => 'test',
  342. 'options' => $options
  343. );
  344. $db = Zend_Db::factory('Pdo_Mysql', $params);
  345. ]]></programlisting>
  346. </example>
  347. <example id="zend.db.adapter.connecting.parameters.example3">
  348. <title>ファクトリでの PDO ドライバのオプションの指定</title>
  349. <programlisting role="php"><![CDATA[
  350. $pdoParams = array(
  351. PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
  352. );
  353. $params = array(
  354. 'host' => '127.0.0.1',
  355. 'username' => 'webuser',
  356. 'password' => 'xxxxxxxx',
  357. 'dbname' => 'test',
  358. 'driver_options' => $pdoParams
  359. );
  360. $db = Zend_Db::factory('Pdo_Mysql', $params);
  361. echo $db->getConnection()
  362. ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
  363. ]]></programlisting>
  364. </example>
  365. <example id="zend.db.adapter.connecting.parameters.example4">
  366. <title>ファクトリでのシリアライズオプションの指定</title>
  367. <programlisting role="php"><![CDATA[
  368. $options = array(
  369. Zend_Db::ALLOW_SERIALIZATION => false
  370. );
  371. $params = array(
  372. 'host' => '127.0.0.1',
  373. 'username' => 'webuser',
  374. 'password' => 'xxxxxxxx',
  375. 'dbname' => 'test',
  376. 'options' => $options
  377. );
  378. $db = Zend_Db::factory('Pdo_Mysql', $params);
  379. ]]></programlisting>
  380. </example>
  381. </sect3>
  382. <sect3 id="zend.db.adapter.connecting.getconnection">
  383. <title>遅延接続の管理</title>
  384. <para>
  385. アダプタクラスのインスタンスを作成した時点では、
  386. まだ RDBMS サーバへの接続は行われません。
  387. 接続用のパラメータを内部で保持しておき、
  388. 実際にクエリを実行することになった時点で初めて接続を確立します。
  389. これにより、アダプタオブジェクトをすばやく作成できるようになっています。
  390. つまり、そのリクエストの中で
  391. 実際にデータベースクエリを発行するかどうかが確定していなくても、
  392. とりあえずアダプタのインスタンスを作成しておくということもできます。
  393. </para>
  394. <para>
  395. 強制的に RDBMS との接続を確立する必要がある場合は、
  396. <code>getConnection()</code> メソッドを使用します。
  397. このメソッドは、対応する PHP 拡張モジュール用の接続オブジェクトを返します。
  398. たとえば、PDO ドライバ系のアダプタクラスを使った場合は、
  399. <code>getConnection()</code> は
  400. データベースとの接続を確立してから PDO オブジェクトを返します。
  401. </para>
  402. <para>
  403. データベースへの接続時に発生する例外、
  404. すなわち ID やパスワードの間違いなどを捕捉したい場合に、
  405. これは役立つでしょう。
  406. 実際に接続を行うまで例外はスローされないので、
  407. どこか一か所に例外処理をまとめておいたほうが
  408. アプリケーションがシンプルになって便利でしょう。
  409. </para>
  410. <para>
  411. さらに、アダプタをシリアライズしてたとえばセッション変数などに格納することもできます。
  412. これは、アダプタだけでなくアダプタを利用する側
  413. (<classname>Zend_Db_Select</classname> オブジェクトなど) にとっても有用です。
  414. デフォルトではアダプタのシリアライズが許可されています。
  415. シリアライズをしたくない場合は、上の例のように
  416. <classname>Zend_Db::ALLOW_SERIALIZATION=false</classname> オプションを渡します。
  417. 遅延接続の理念を尊重し、アンシリアライズされたアダプタの
  418. 自動再接続は行いません。つまり、自分で
  419. <code>getConnection()</code> をコールしなければなりません。
  420. 自動再接続を有効にするには、アダプタのオプションに
  421. <classname>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE=true</classname>
  422. を渡します。
  423. </para>
  424. <example id="zend.db.adapter.connecting.getconnection.example">
  425. <title>接続時の例外処理</title>
  426. <programlisting role="php"><![CDATA[
  427. try {
  428. $db = Zend_Db::factory('Pdo_Mysql', $parameters);
  429. $db->getConnection();
  430. } catch (Zend_Db_Adapter_Exception $e) {
  431. // ID かパスワードが間違っている、あるいは RDBMS が起動していないなど……
  432. } catch (Zend_Exception $e) {
  433. // factory() が指定したアダプタクラスを読み込めなかったなど……
  434. }
  435. ]]></programlisting>
  436. </example>
  437. </sect3>
  438. </sect2>
  439. <sect2 id="zend.db.adapter.example-database">
  440. <title>サンプルデータベース</title>
  441. <para>
  442. <classname>Zend_Db</classname> クラスのドキュメントでは、
  443. クラスやメソッドの使用法を説明するために単純なデータベースを使用します。
  444. これは、とあるソフトウェア開発プロジェクトにおけるバグ管理を想定したものです。
  445. 次の 4 つのテーブルで構成されています。
  446. </para>
  447. <itemizedlist>
  448. <listitem>
  449. <para>
  450. <emphasis role="strong">accounts</emphasis> テーブルには、
  451. バグ管理データベースを使用するユーザについての情報を格納します。
  452. </para>
  453. </listitem>
  454. <listitem>
  455. <para>
  456. <emphasis role="strong">products</emphasis> テーブルには、
  457. バグを記録する対象となる製品についての情報を格納します。
  458. </para>
  459. </listitem>
  460. <listitem>
  461. <para>
  462. <emphasis role="strong">bugs</emphasis> テーブルには、
  463. バグについての情報を格納します。
  464. バグの状態や報告者、修正担当者、検証担当者などの情報が含まれます。
  465. </para>
  466. </listitem>
  467. <listitem>
  468. <para>
  469. <emphasis role="strong">bugs_products</emphasis> テーブルには、
  470. バグと製品の関連付け情報を格納します。
  471. これは、いわゆる多対多のリレーションシップを実装するものです。
  472. ひとつのバグが複数の製品に関連するものであることもあれば、
  473. 当然ひとつの製品には複数のバグが存在するからです。
  474. </para>
  475. </listitem>
  476. </itemizedlist>
  477. <para>
  478. このサンプルデータベースを作成するための SQL
  479. の擬似コードは、次のようになります。
  480. これらのテーブルは、<classname>Zend_Db</classname> 自体のユニットテストでも使用します。
  481. </para>
  482. <programlisting role="sql"><![CDATA[
  483. CREATE TABLE accounts (
  484. account_name VARCHAR(100) NOT NULL PRIMARY KEY
  485. );
  486. CREATE TABLE products (
  487. product_id INTEGER NOT NULL PRIMARY KEY,
  488. product_name VARCHAR(100)
  489. );
  490. CREATE TABLE bugs (
  491. bug_id INTEGER NOT NULL PRIMARY KEY,
  492. bug_description VARCHAR(100),
  493. bug_status VARCHAR(20),
  494. reported_by VARCHAR(100) REFERENCES accounts(account_name),
  495. assigned_to VARCHAR(100) REFERENCES accounts(account_name),
  496. verified_by VARCHAR(100) REFERENCES accounts(account_name)
  497. );
  498. CREATE TABLE bugs_products (
  499. bug_id INTEGER NOT NULL REFERENCES bugs,
  500. product_id INTEGER NOT NULL REFERENCES products,
  501. PRIMARY KEY (bug_id, product_id)
  502. );
  503. ]]></programlisting>
  504. <para>
  505. また、<code>bugs</code> テーブルには <code>accounts</code>
  506. テーブルを指す外部キー参照が複数含まれることにも注意しましょう。
  507. それぞれの外部キーは、そのバグに対して
  508. <code>accounts</code> テーブルの別々の行を参照することもあります。
  509. </para>
  510. <para>
  511. サンプルデータベースの物理データモデルは、次の図のようになります。
  512. </para>
  513. <para>
  514. <inlinegraphic width="387" scale="100" align="center" valign="middle"
  515. fileref="figures/zend.db.adapter.example-database.png" format="PNG" />
  516. </para>
  517. </sect2>
  518. <sect2 id="zend.db.adapter.select">
  519. <title>クエリ結果の読み込み</title>
  520. <para>
  521. ここでは、SELECT クエリを実行してその結果を取得するための
  522. アダプタのメソッドについて説明します。
  523. </para>
  524. <sect3 id="zend.db.adapter.select.fetchall">
  525. <title>結果セット全体の取得</title>
  526. <para>
  527. SQL の SELECT クエリの実行とその結果の取得を一度に行うには
  528. <code>fetchAll()</code> メソッドを使用します。
  529. </para>
  530. <para>
  531. このメソッドの最初の引数には、SELECT 文を文字列で指定します。
  532. あるいは、文字列ではなく
  533. <link linkend="zend.db.select">Zend_Db_Select</link>
  534. クラスのオブジェクトを指定することもできます。
  535. オブジェクトを渡した場合は、アダプタの内部でそれを自動的に
  536. SELECT 文の文字列に変換します。
  537. </para>
  538. <para>
  539. <code>fetchAll()</code> でその次に指定する引数は、
  540. SQL 文中のパラメータプレースホルダを置換する値の配列となります。
  541. </para>
  542. <example id="zend.db.adapter.select.fetchall.example">
  543. <title>fetchAll() の使用</title>
  544. <programlisting role="php"><![CDATA[
  545. $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
  546. $result = $db->fetchAll($sql, 2);
  547. ]]></programlisting>
  548. </example>
  549. </sect3>
  550. <sect3 id="zend.db.adapter.select.fetch-mode">
  551. <title>フェッチモードの変更</title>
  552. <para>
  553. デフォルトでは、<code>fetchAll()</code>
  554. は行の配列を返します。各行のデータは連想配列となります。
  555. 連署配列のキーは、列名かあるいは SELECT
  556. クエリで指定した列の別名となります。
  557. </para>
  558. <para>
  559. 返り値の形式を別のものにするには
  560. <code>setFetchMode()</code> メソッドを使用します。
  561. 対応しているモードは、以下の定数で表されるものです。
  562. </para>
  563. <itemizedlist>
  564. <listitem>
  565. <para>
  566. <emphasis role="strong">Zend_Db::FETCH_ASSOC</emphasis>:
  567. データを、連想配列の配列として返します。
  568. 配列のキーは、カラム名を文字列で表したものとなります。
  569. これは、<classname>Zend_Db_Adapter</classname> クラスのデフォルトのフェッチモードです。
  570. </para>
  571. <para>
  572. select で取得する一覧の中に同名のカラムが含まれている場合
  573. (たとえば複数テーブルを JOIN した場合など)
  574. は、その名前のエントリはひとつしか含まれません。
  575. FETCH_ASSOC モードを使用する場合は、
  576. SELECT クエリでカラムの別名を指定するなどして、
  577. 結果の配列におけるキーが一意になるようにしなければなりません。
  578. </para>
  579. <para>
  580. デフォルトでは、これらの文字列はデータベースドライバから返されるものをそのまま使用します。
  581. 通常は、これは RDBMS サーバでのカラム名となるでしょう。
  582. 大文字小文字を指定するには、<classname>Zend_Db::CASE_FOLDING</classname>
  583. オプションを使用します。これは、
  584. アダプタのインスタンスを作成する際に使用します。
  585. <xref linkend="zend.db.adapter.connecting.parameters.example1" />
  586. を参照ください。
  587. </para>
  588. </listitem>
  589. <listitem>
  590. <para>
  591. <emphasis role="strong">Zend_Db::FETCH_NUM</emphasis>:
  592. データを、配列の配列で返します。
  593. 配列は数値添字形式となり、クエリで指定した順番での位置がキーとなります。
  594. </para>
  595. </listitem>
  596. <listitem>
  597. <para>
  598. <emphasis role="strong">Zend_Db::FETCH_BOTH</emphasis>:
  599. データを、配列の配列で返します。
  600. 配列のキーは、FETCH_ASSOC モードで用いる文字列と
  601. FETCH_NUM モードで用いる数値の両方を含んだものとなります。
  602. 配列の要素数が、FETCH_ASSOC や FETCH_NUM
  603. の場合の倍になることに注意しましょう。
  604. </para>
  605. </listitem>
  606. <listitem>
  607. <para>
  608. <emphasis role="strong">Zend_Db::FETCH_COLUMN</emphasis>:
  609. データを、値の配列で返します。
  610. 配列の各要素の値は、結果セットのあるひとつのカラムの値となります。
  611. デフォルトでは、これは最初の (0 番目の) カラムとなります。
  612. </para>
  613. </listitem>
  614. <listitem>
  615. <para>
  616. <emphasis role="strong">Zend_Db::FETCH_OBJ</emphasis>:
  617. データを、オブジェクトの配列で返します。
  618. デフォルトのクラスは、PHP の組み込みクラス stdClass
  619. となります。結果セットのカラムは、このクラスのプロパティとしてアクセスできます。
  620. </para>
  621. </listitem>
  622. </itemizedlist>
  623. <example id="zend.db.adapter.select.fetch-mode.example">
  624. <title>setFetchMode() の使用</title>
  625. <programlisting role="php"><![CDATA[
  626. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  627. $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
  628. // $result はオブジェクトの配列となります
  629. echo $result[0]->bug_description;
  630. ]]></programlisting>
  631. </example>
  632. </sect3>
  633. <sect3 id="zend.db.adapter.select.fetchassoc">
  634. <title>連想配列形式での結果セットの取得</title>
  635. <para>
  636. <code>fetchAssoc()</code> メソッドは、
  637. フェッチモードの設定にかかわらず、
  638. 結果のデータを連想配列の配列で返します。
  639. </para>
  640. <example id="zend.db.adapter.select.fetchassoc.example">
  641. <title>fetchAssoc() の使用</title>
  642. <programlisting role="php"><![CDATA[
  643. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  644. $result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
  645. // $result は、フェッチモードの指定とは関係なく連想配列の配列となります
  646. echo $result[0]['bug_description'];
  647. ]]></programlisting>
  648. </example>
  649. </sect3>
  650. <sect3 id="zend.db.adapter.select.fetchcol">
  651. <title>結果セットの単一のカラムの取得</title>
  652. <para>
  653. <code>fetchCol()</code> メソッドは、
  654. フェッチモードの設定にかかわらず、
  655. 結果のデータを値の配列で返します。
  656. これは、クエリの最初のカラムのみを返します。
  657. それ以外のカラムの内容は破棄されます。
  658. 別のカラムが必要な場合は
  659. <xref linkend="zend.db.statement.fetching.fetchcolumn" />
  660. を参照ください。
  661. </para>
  662. <example id="zend.db.adapter.select.fetchcol.example">
  663. <title>fetchCol() の使用</title>
  664. <programlisting role="php"><![CDATA[
  665. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  666. $result = $db->fetchCol(
  667. 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
  668. // bug_description を含み、bug_id は含みません
  669. echo $result[0];
  670. ]]></programlisting>
  671. </example>
  672. </sect3>
  673. <sect3 id="zend.db.adapter.select.fetchpairs">
  674. <title>結果セットからの キー/値 のペアの取得</title>
  675. <para>
  676. <code>fetchPairs()</code> メソッドは、データを キー/値
  677. のペア (連想配列) の配列で返します。
  678. この連想配列のキーは、SELECT クエリが返す最初のカラムの値となります。
  679. また、連想配列の値は、SELECT クエリが返す二番目のカラムの値となります。
  680. クエリから返されるその他のカラムは破棄されます。
  681. </para>
  682. <para>
  683. SELECT クエリをうまく設計し、最初のカラムの値が一意になるようにしなければなりません。
  684. もし最初のカラムに重複する値があれば、連想配列のエントリが上書きされてしまいます。
  685. </para>
  686. <example id="zend.db.adapter.select.fetchpairs.example">
  687. <title>fetchPairs() の例</title>
  688. <programlisting role="php"><![CDATA[
  689. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  690. $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
  691. echo $result[2];
  692. ]]></programlisting>
  693. </example>
  694. </sect3>
  695. <sect3 id="zend.db.adapter.select.fetchrow">
  696. <title>結果セットからの単一の行の取得</title>
  697. <para>
  698. <code>fetchRow()</code> メソッドは、
  699. 結果のデータを現在のフェッチモードで返します。
  700. ただ、返すのは結果セットから取得した最初の行のみです。
  701. </para>
  702. <example id="zend.db.adapter.select.fetchrow.example">
  703. <title>fetchRow() の使用</title>
  704. <programlisting role="php"><![CDATA[
  705. $db->setFetchMode(Zend_Db::FETCH_OBJ);
  706. $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
  707. // $result はオブジェクトの配列ではなく、単なるオブジェクトとなります
  708. echo $result->bug_description;
  709. ]]></programlisting>
  710. </example>
  711. </sect3>
  712. <sect3 id="zend.db.adapter.select.fetchone">
  713. <title>結果セットからの単一のスカラー値の取得</title>
  714. <para>
  715. <code>fetchOne()</code> メソッドは
  716. <code>fetchRow()</code> と <code>fetchCol()</code>
  717. を組み合わせたようなものです。
  718. 結果セットからの最初の行から、最初のカラムの値のみを返します。
  719. したがって、このメソッドの返り値は配列やオブジェクトではなく単一のスカラー値となります。
  720. </para>
  721. <example id="zend.db.adapter.select.fetchone.example">
  722. <title>fetchOne() の使用法</title>
  723. <programlisting role="php"><![CDATA[
  724. $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
  725. // これは単なる文字列となります
  726. echo $result;
  727. ]]></programlisting>
  728. </example>
  729. </sect3>
  730. </sect2>
  731. <sect2 id="zend.db.adapter.write">
  732. <title>データベースへの変更の書き出し</title>
  733. <para>
  734. アダプタクラスを使用して、
  735. 新しいデータをデータベースに書き込んだり
  736. 既存のデータに変更を加えたりすることができます。
  737. ここでは、そのためのメソッドについて説明します。
  738. </para>
  739. <sect3 id="zend.db.adapter.write.insert">
  740. <title>データの挿入</title>
  741. <para>
  742. データベースのテーブルに新しい行を追加するには、
  743. <code>insert()</code> メソッドを使用します。
  744. 最初の引数はテーブル名を表す文字列で、
  745. その次の引数はカラム名とデータの値を関連付けた連想配列となります。
  746. </para>
  747. <example id="zend.db.adapter.write.insert.example">
  748. <title>テーブルへのデータの挿入</title>
  749. <programlisting role="php"><![CDATA[
  750. $data = array(
  751. 'created_on' => '2007-03-22',
  752. 'bug_description' => 'Something wrong',
  753. 'bug_status' => 'NEW'
  754. );
  755. $db->insert('bugs', $data);
  756. ]]></programlisting>
  757. </example>
  758. <para>
  759. データの配列で指定しなかったカラムについてはデータベースに対して何も指示しません。
  760. つまり、SQL の INSERT 文で列を指定しなかった場合と同じ挙動となります。
  761. DEFAULT 句が設定されていればその値が追加され、
  762. 設定されていなければ NULL のままとなります。
  763. </para>
  764. <para>
  765. デフォルトでは、データ配列の値を挿入する際にはパラメータを使用します。
  766. これにより、ある種のセキュリティ問題が発生する可能性を軽減します。
  767. データ配列で指定するデータについては、
  768. エスケープやクォート処理を考慮する必要はありません。
  769. </para>
  770. <para>
  771. データ配列の中の値を SQL の式として扱い、
  772. クォートしたくない場合もあるかもしれません。
  773. デフォルトでは、文字列として渡した値はすべて文字列リテラルとして扱われます。
  774. その値が SQL の式であること、つまりクォートしてはいけないということを指定するには、
  775. 文字列ではなく <classname>Zend_Db_Expr</classname> 型のオブジェクトをデータ配列に渡します。
  776. </para>
  777. <example id="zend.db.adapter.write.insert.example2">
  778. <title>テーブルへの式の挿入</title>
  779. <programlisting role="php"><![CDATA[
  780. $data = array(
  781. 'created_on' => new Zend_Db_Expr('CURDATE()'),
  782. 'bug_description' => 'Something wrong',
  783. 'bug_status' => 'NEW'
  784. );
  785. $db->insert('bugs', $data);
  786. ]]></programlisting>
  787. </example>
  788. </sect3>
  789. <sect3 id="zend.db.adapter.write.lastinsertid">
  790. <title>生成された値の取得</title>
  791. <para>
  792. RDBMS によっては、主キーの自動インクリメントをサポートしているものもあります。
  793. この方法で定義したテーブルに新しい行を INSERT すると、
  794. 主キーの値が自動的に生成されます。
  795. <code>insert()</code> メソッドの返り値は、最後に追加された ID
  796. では<emphasis>ありません</emphasis>。
  797. そのテーブルには自動インクリメントのカラムがないかもしれないからです。
  798. 返り値は、変更された行数 (通常は 1 です) となります。
  799. </para>
  800. <para>
  801. そのテーブルで自動インクリメントの主キーを定義している場合は、
  802. データを追加した後で <code>lastInsertId()</code>
  803. メソッドを使用することができます。このメソッドは、
  804. 現在のデータベース接続において最後に自動生成された値を返します。
  805. </para>
  806. <example id="zend.db.adapter.write.lastinsertid.example-1">
  807. <title>自動インクリメントのキーにおける lastInsertId() の使用法</title>
  808. <programlisting role="php"><![CDATA[
  809. $db->insert('bugs', $data);
  810. // 自動インクリメントのカラムで最後に生成された値を返します
  811. $id = $db->lastInsertId();
  812. ]]></programlisting>
  813. </example>
  814. <para>
  815. RDBMS によっては、シーケンスをサポートしているものもあります。
  816. シーケンスを使用して、主キー用の一意な値を生成することができます。
  817. シーケンスをサポートするために、<code>lastInsertId()</code>
  818. ではオプションの文字列引数を 2 つ受け取れるようにしています。
  819. これらの引数には、それぞれテーブル名とカラム名を指定します。
  820. シーケンスの名前は、このテーブル名とカラム名をつなげたものの後に
  821. "_seq" を付加したものとなります。これは、PostgreSQL
  822. が SERIAL 型のカラムに対して自動生成するシーケンス名の規約にもとづいています。
  823. たとえば、"bugs" テーブルの主キーカラムが
  824. "bug_id" である場合は、"bugs_bug_id_seq"
  825. という名前のシーケンスを使用することになります。
  826. </para>
  827. <example id="zend.db.adapter.write.lastinsertid.example-2">
  828. <title>シーケンスにおける lastInsertId() の使用法</title>
  829. <programlisting role="php"><![CDATA[
  830. $db->insert('bugs', $data);
  831. // シーケンス 'bugs_bug_id_seq' が最後に生成した値を返します
  832. $id = $db->lastInsertId('bugs', 'bug_id');
  833. // これは、シーケンス 'bugs_seq' が最後に生成した値を返します
  834. $id = $db->lastInsertId('bugs');
  835. ]]></programlisting>
  836. </example>
  837. <para>
  838. もしこの命名規約とは異なる名前のシーケンスを使用している場合は、代わりに
  839. <code>lastSequenceId()</code> メソッドを使用します。
  840. このメソッドの引数には、シーケンスの名前を直接指定します。
  841. </para>
  842. <example id="zend.db.adapter.write.lastinsertid.example-3">
  843. <title>lastSequenceId() の使用法</title>
  844. <programlisting role="php"><![CDATA[
  845. $db->insert('bugs', $data);
  846. // シーケンス 'bugs_id_gen' が最後に生成した値を返します
  847. $id = $db->lastSequenceId('bugs_id_gen');
  848. ]]></programlisting>
  849. </example>
  850. <para>
  851. シーケンスをサポートしていない RDBMS、たとえば MySQL や
  852. Microsoft SQL Server、SQLite などの場合、
  853. lastInsertId() メソッドの引数は無視されます。
  854. このメソッドの返り値は、現在の接続で最後に実行された
  855. INSERT 操作が生成した値となります。また、これらの RDBMS では
  856. lastSequenceId() メソッドの返り値は常に <code>null</code>
  857. となります。
  858. </para>
  859. <note>
  860. <title>"SELECT MAX(id) FROM table" じゃあダメなんですか?</title>
  861. <para>
  862. たしかにこのクエリは、最後にテーブルに追加された主キーの値を返すこともあります。
  863. しかしこれは、複数のクライアントがデータベースにレコードを追加するという環境では
  864. 安全ではありません。
  865. つまり、データを追加してから MAX(id) の値を取得するまでの間に
  866. 他のクライアントが別のデータを追加する可能性があるということです。
  867. この場合、クエリが返す結果はあなたが実際に追加した行の ID とは異なり、
  868. 誰か他の人が追加した行の ID となってしまいます。
  869. しかも、もしそのような状況になっていたとしても
  870. あなたにはそれを知ることはできません。
  871. </para>
  872. <para>
  873. たとえば "repeatable read" のようなトランザクション分離モードを使用すれば、
  874. この危険性を減らせます。しかし、
  875. このレベルのトランザクション分離をサポートしていない RDBMS
  876. もあります。また、そのアプリケーション自体がもっと緩いレベルの
  877. トランザクション分離モードを想定して作成されているかもしれません。
  878. </para>
  879. <para>
  880. さらに、新しい主キーの値を生成する際に "MAX(id)+1"
  881. のような式を使うのも同様に危険です。ふたつのクライアントから同時にこのクエリを実行すると、
  882. どちらも同じ値を取得することになり、同じ値で INSERT
  883. を行なうことになってしまいます。
  884. </para>
  885. <para>
  886. どんな RDBMS でも、一意な値を生成する機能や
  887. 最後に生成した値を返す機能は持っています。
  888. この機能はトランザクション分離レベルとは無関係に機能するはずなので、
  889. ふたつのクライアントで同じ値が重複してしまうことはありません。
  890. また、他のクライアントで作成した値が
  891. あなたの接続で「最後に生成した値」として返されることもありません。
  892. </para>
  893. </note>
  894. </sect3>
  895. <sect3 id="zend.db.adapter.write.update">
  896. <title>データの更新</title>
  897. <para>
  898. データベースのテーブルの行を更新するには、アダプタの
  899. <code>update()</code> メソッドを使用します。このメソッドへの引数は
  900. 3 つです。まず最初はテーブルの名前、
  901. その次はカラム名と新しい値を関連づけた連想配列となります。
  902. </para>
  903. <para>
  904. 配列で指定した値は、文字列リテラルとして扱われます。
  905. データ配列で SQL の式を扱う方法については
  906. <xref linkend="zend.db.adapter.write.insert" />
  907. を参照ください。
  908. </para>
  909. <para>
  910. 三番目の引数は、SQL の式を文字列で指定します。
  911. これが、変更する行を絞り込むための条件となります。
  912. ここで指定した値や識別子に対しては、クォートやエスケープは行ないません。
  913. 何らかの動的な値を使用する場合は、その内容が安全であることを確認するようにしましょう。
  914. <xref linkend="zend.db.adapter.quoting" />
  915. で説明しているメソッドを使用するといいでしょう。
  916. </para>
  917. <para>
  918. このメソッドの返り値は、更新操作によって変更された行の数となります。
  919. </para>
  920. <example id="zend.db.adapter.write.update.example">
  921. <title>行の更新</title>
  922. <programlisting role="php"><![CDATA[
  923. $data = array(
  924. 'updated_on' => '2007-03-23',
  925. 'bug_status' => 'FIXED'
  926. );
  927. $n = $db->update('bugs', $data, 'bug_id = 2');
  928. ]]></programlisting>
  929. </example>
  930. <para>
  931. 三番目の引数を省略した場合は、テーブルのすべての行が指定した値で更新されます。
  932. </para>
  933. <para>
  934. 三番目の引数に文字列の配列を指定すると、各要素の内容を
  935. <code>AND</code> 演算子で連結して使用します。
  936. </para>
  937. <example id="zend.db.adapter.write.update.example-array">
  938. <title>式の配列を指定することによる行の更新</title>
  939. <programlisting role="php"><![CDATA[
  940. $data = array(
  941. 'updated_on' => '2007-03-23',
  942. 'bug_status' => 'FIXED'
  943. );
  944. $where[] = "reported_by = 'goofy'";
  945. $where[] = "bug_status = 'OPEN'";
  946. $n = $db->update('bugs', $data, $where);
  947. // 実行される SQL は、このようになります
  948. // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
  949. // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
  950. ]]></programlisting>
  951. </example>
  952. </sect3>
  953. <sect3 id="zend.db.adapter.write.delete">
  954. <title>行の削除</title>
  955. <para>
  956. データベースのテーブルから行を削除するには
  957. <code>delete()</code> メソッドを使用します。このメソッドに渡す引数は 2 つで、
  958. 最初の引数はテーブル名を表す文字列です。
  959. </para>
  960. <para>
  961. 二番目の引数は、SQL の式を文字列で指定します。
  962. これが、削除する行を絞り込むための条件となります。
  963. ここで指定した値や識別子に対しては、クォートやエスケープは行ないません。
  964. 何らかの動的な値を使用する場合は、その内容が安全であることを確認するようにしましょう。
  965. <xref linkend="zend.db.adapter.quoting" />
  966. で説明しているメソッドを使用するといいでしょう。
  967. </para>
  968. <para>
  969. このメソッドの返り値は、削除操作によって変更された行の数となります。
  970.   </para>
  971. <example id="zend.db.adapter.write.delete.example">
  972. <title>行の削除</title>
  973. <programlisting role="php"><![CDATA[
  974. $n = $db->delete('bugs', 'bug_id = 3');
  975. ]]></programlisting>
  976. </example>
  977. <para>
  978. 二番目の引数を省略した場合は、テーブルのすべての行を削除します。
  979. </para>
  980. <para>
  981. 二番目の引数に文字列の配列を指定すると、各要素の内容を
  982. <code>AND</code> 演算子で連結して使用します。
  983. </para>
  984. </sect3>
  985. </sect2>
  986. <sect2 id="zend.db.adapter.quoting">
  987. <title>値や識別子のクォート</title>
  988. <para>
  989. SQL を作成する際には、PHP の変数の値を
  990. SQL の式で使用しなければならないこともあるでしょう。
  991. これは危険な処理です。なぜなら、PHP の文字列の中には
  992. たとえばクォート記号のような特殊文字が含まれていることがあり、
  993. できあがる SQL がおかしなものになってしまう可能性があるからです。
  994. たとえば、以下のコードで作成した SQL は、クォート文字の対応がおかしいものになります。
  995. <programlisting role="php"><![CDATA[
  996. $name = "O'Reilly";
  997. $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
  998. echo $sql;
  999. // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
  1000. ]]></programlisting>
  1001. </para>
  1002. <para>
  1003. さらに悪いことに、このようなコードを悪用されると
  1004. あなたのアプリケーションが攻撃の被害を受けることになるかもしれません。
  1005. PHP の変数の値を HTTP パラメータなどで指定することができれば、
  1006. SQL クエリを操作して予期せぬことをされてしまう可能性があります
  1007. (たとえば、その人の権限では見えないはずのデータを見られてしまうなど)。
  1008. これは、アプリケーションのセキュリティ問題としては非常に有名な手法で、
  1009. "SQL インジェクション" と呼ばれています
  1010. (<ulink url="http://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3">
  1011. http://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3</ulink>
  1012. を参照ください)。
  1013. </para>
  1014. <para>
  1015. <classname>Zend_Db</classname> Adapter クラスの提供する便利な関数を使用すると、
  1016. あなたの PHP コードが SQL インジェクション攻撃を受ける危険性を軽減することができます。
  1017. この攻撃を回避する方法は、PHP のクォート文字のような特殊文字を
  1018. 正しくエスケープしてから SQL に使用することです。
  1019. これにより、不意に (あるいは故意に)
  1020. SQL に特殊文字が埋め込まれてしまうことを防ぎます。
  1021. </para>
  1022. <sect3 id="zend.db.adapter.quoting.quote">
  1023. <title>quote() の使用法</title>
  1024. <para>
  1025. <code>quote()</code> メソッドは、引数として文字列を受け取ります。
  1026. そしてその文字列の中の特殊文字をエスケープした上で、
  1027. 両端を区切り文字で囲んだものを返します。
  1028. エスケープ処理は、使用している RDBMS
  1029. にあわせて適切に行われます。
  1030. 文字列の両端に使用する区切り文字は、標準の SQL
  1031. ではシングルクォート (<code>'</code>) となります。
  1032. </para>
  1033. <example id="zend.db.adapter.quoting.quote.example">
  1034. <title>quote() の使用法</title>
  1035. <programlisting role="php"><![CDATA[
  1036. $name = $db->quote("O'Reilly");
  1037. echo $name;
  1038. // 'O\'Reilly'
  1039. $sql = "SELECT * FROM bugs WHERE reported_by = $name";
  1040. echo $sql;
  1041. // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
  1042. ]]></programlisting>
  1043. </example>
  1044. <para>
  1045. <code>quote()</code> の返り値には、文字列の両端に区切り文字が追加されていることに注意しましょう。
  1046. これは、たとえば
  1047. <ulink url="http://www.php.net/mysqli_real_escape_string">mysql_real_escape_string()</ulink>
  1048. のようなエスケープ用関数の挙動とは異なります。
  1049. </para>
  1050. <para>
  1051. 値をクォートするかしないかは、SQL のデータ型によって異なります。
  1052. たとえば、整数値をクォートしてしまうと
  1053. 数値型カラムや計算式で利用できなくなってしまうという
  1054. RDBMS もあります。つまり、次のような SQL
  1055. がエラーになってしまう実装があるということです。
  1056. ここで、<code>intColumn</code> のデータ型は
  1057. <code>INTEGER</code> であるものとします。
  1058. <programlisting role="php"><![CDATA[
  1059. SELECT * FROM atable WHERE intColumn = '123'
  1060. ]]></programlisting>
  1061. </para>
  1062. <para>
  1063. <code>quote()</code> メソッドでオプションの
  1064. 2 番目の引数を使用すると、
  1065. SQL のデータ型に応じてクォートするかどうかを選択することができます。
  1066. </para>
  1067. <example id="zend.db.adapter.quoting.quote.example-2">
  1068. <title>quote() での SQL データ型の指定</title>
  1069. <programlisting role="php"><![CDATA[
  1070. $value = '1234';
  1071. $sql = 'SELECT * FROM atable WHERE intColumn = '
  1072. . $db->quote($value, 'INTEGER');
  1073. ]]></programlisting>
  1074. </example>
  1075. <para>
  1076. 各 <classname>Zend_Db_Adapter</classname> クラスでは、その RDBMS
  1077. 用の SQL 数値データ型の名前がコード化されています。
  1078. それら以外にも
  1079. <classname>Zend_Db::INT_TYPE</classname> や
  1080. <classname>Zend_Db::BIGINT_TYPE</classname>、そして
  1081. <classname>Zend_Db::FLOAT_TYPE</classname>
  1082. といった定数が用意されており、
  1083. これらを使用すると RDBMS に依存しないコードを書くことができます。
  1084. </para>
  1085. <para>
  1086. <classname>Zend_Db_Table</classname> は、テーブルのキーとなるカラムを使用する際には
  1087. 自動的に SQL データ型を <code>quote()</code> に指定します。
  1088. </para>
  1089. </sect3>
  1090. <sect3 id="zend.db.adapter.quoting.quote-into">
  1091. <title>quoteInto() の使用法</title>
  1092. <para>
  1093. クォートを使用する場面としていちばんよくあるのが、
  1094. PHP の変数の値を SQL の式や文中で使用するということです。
  1095. <code>quoteInto()</code> メソッドを使用すると、この処理を一度でできるようになります。
  1096. このメソッドが受け取る引数はふたつです。
  1097. まず最初の引数としてプレースホルダ記号 (<code>?</code>)
  1098. を含む文字列を指定し、次の引数で PHP の変数などの値を指定します。
  1099. ここで指定した値で、プレースホルダの部分を置き換えます。
  1100. </para>
  1101. <para>
  1102. プレースホルダ用の記号は、多くの RDBMS
  1103. でパラメータとして使用している記号と同じです。しかし、
  1104. <code>quoteInto()</code> メソッドはあくまでパラメータをエミュレートしているだけです。
  1105. このメソッドは単純に文字列の中に値を放り込み、
  1106. 特殊文字をエスケープして両端をクォートするという処理だけを行います。
  1107. RDBMS におけるパラメータのように、
  1108. SQL 文字列と値を分離して SQL だけを事前に RDBMS
  1109. サーバでパースするといったことは行いません。
  1110. </para>
  1111. <example id="zend.db.adapter.quoting.quote-into.example">
  1112. <title>quoteInto() の使用法</title>
  1113. <programlisting role="php"><![CDATA[
  1114. $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
  1115. echo $sql;
  1116. // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
  1117. ]]></programlisting>
  1118. </example>
  1119. <para>
  1120. <code>quoteInto()</code> のオプションの
  1121. 3 番目のパラメータを使用すると、SQL のデータ型を指定することができます。
  1122. 数値型はクォートをせず、それ以外の型についてはクォートを行います。
  1123. </para>
  1124. <example id="zend.db.adapter.quoting.quote-into.example-2">
  1125. <title>quoteInto() での SQL データ型の指定</title>
  1126. <programlisting role="php"><![CDATA[
  1127. $sql = $db
  1128. ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
  1129. echo $sql;
  1130. // SELECT * FROM bugs WHERE reported_by = 1234
  1131. ]]></programlisting>
  1132. </example>
  1133. </sect3>
  1134. <sect3 id="zend.db.adapter.quoting.quote-identifier">
  1135. <title>quoteIdentifier() の使用法</title>
  1136. <para>
  1137. 変数を使用する可能性があるのは、SQL 文中の値だけとは限りません。
  1138. SQL 文中でのテーブル名やカラム名などの識別子として
  1139. PHP の変数を使用する場合も、同様にクォートする必要があります。
  1140. デフォルトでは、SQL の識別子に使用できる文字は
  1141. PHP などのプログラミング言語の規則と似ています。
  1142. たとえば、識別子には空白文字や記号を使用することはできませんし、
  1143. またアルファベット以外の文字も使えません。
  1144. SQL の文法上特別な意味を持つ単語として予約されているものも、
  1145. そのままでは識別子として使用できません。
  1146. </para>
  1147. <para>
  1148. しかし、適切な区切り文字でクォートすれば、
  1149. 識別子として使用できる文字の幅が広がります。
  1150. 本来識別子として使用できない文字を含んでいても、
  1151. 適切な形式でクォートすることで SQL の識別子として使用できるようになります。
  1152. たとえば、空白や記号などを使うこともできますし、
  1153. SQL で予約語として指定されている単語であっても使用可能です。
  1154. </para>
  1155. <para>
  1156. <code>quoteIdentifier()</code> メソッドの働きは
  1157. <code>quote()</code> と似ていますが、
  1158. このメソッドは使用しているアダプタの型に応じた識別子区切り文字を付加します。
  1159. たとえば、標準 SQL ではダブルクォート
  1160. (<code>"</code>) を区切り文字として使用します。
  1161. 多くの RDBMS がこれにしたがっています。
  1162. MySQL の場合は、デフォルトではバッククォート
  1163. (<code>`</code>) を使用します。
  1164. <code>quoteIdentifier()</code> メソッドはまた、
  1165. 文字列引数内の特殊文字のエスケープも行います。
  1166. </para>
  1167. <example id="zend.db.adapter.quoting.quote-identifier.example">
  1168. <title>quoteIdentifier() の使用法</title>
  1169. <programlisting role="php"><![CDATA[
  1170. // テーブル名に、SQL の予約語を使用します
  1171. $tableName = $db->quoteIdentifier("order");
  1172. $sql = "SELECT * FROM $tableName";
  1173. echo $sql
  1174. // SELECT * FROM "order"
  1175. ]]></programlisting>
  1176. </example>
  1177. <para>
  1178. クォートしていない場合とは異なり、
  1179. クォートした識別子は大文字小文字を区別するようになります。
  1180. したがって、クォートした識別子を使用する場合は
  1181. 大文字小文字の指定も含めて識別子をきちんと記述する必要があります。
  1182. </para>
  1183. <para>
  1184. たいていの場合は <classname>Zend_Db</classname> クラスで自動的に SQL
  1185. を生成することになるでしょう。デフォルトでは、
  1186. すべての識別子が自動的にクォートされます。
  1187. この挙動を変更するには、オプション
  1188. <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname>
  1189. を変更します。これは、アダプタのインスタンスを作成する際に指定します。
  1190. <xref linkend="zend.db.adapter.connecting.parameters.example2" />
  1191. を参照ください。
  1192. </para>
  1193. </sect3>
  1194. </sect2>
  1195. <sect2 id="zend.db.adapter.transactions">
  1196. <title>データベースのトランザクションの制御</title>
  1197. <para>
  1198. データベースには「トランザクション」と呼ばれる論理的な作業単位があります。
  1199. 複数のテーブルにまたがる操作などを一括して更新 (コミット) したり、
  1200. 一括して取消 (ロールバック) したりできるようになります。
  1201. データベースドライバがトランザクションを暗黙的にサポートしている場合は、
  1202. すべてのクエリがトランザクション内で実行されます。
  1203. これを<emphasis>自動コミット</emphasis>モードといいます。
  1204. このモードでは、あらゆるクエリを実行する前に
  1205. ドライバが自動的にトランザクションを開始し、
  1206. 実行が完了したら自動的にトランザクションをコミットします。
  1207. デフォルトでは、すべての <classname>Zend_Db</classname>
  1208. アダプタクラスは自動コミットモードで動作shます。
  1209. </para>
  1210. <para>
  1211. 一方、トランザクションの始点と終点を自分で指定することにより、
  1212. 複数の SQL クエリをひとつのトランザクション内ですることもできます。
  1213. トランザクションを開始する際には <code>beginTransaction()</code>
  1214. メソッドを使用します。それ以降に実行した SQL
  1215. 文は、明示的に指定するまではすべて同じトランザクション内で動作します。
  1216. </para>
  1217. <para>
  1218. トランザクションを終了するには、<code>commit()</code>
  1219. あるいは <code>rollBack()</code> のいずれかを使用します。
  1220. <code>commit()</code> メソッドは、
  1221. そのトランザクションでの変更内容をコミットします。
  1222. つまり、そのトランザクションで行った変更が、
  1223. 他のトランザクションからも見えるようにするということです。
  1224. </para>
  1225. <para>
  1226. <code>rollBack()</code> メソッドはその反対の動作をします。
  1227. このメソッドは、そのトランザクションでの変更内容をすべて破棄します。
  1228. 変更は一切なかったことになり、トランザクションを開始する前の状態にデータを戻します。
  1229. しかし、あるトランザクションをロールバックしたとしても、
  1230. その間に他のトランザクションで行った変更には何の影響も与えません。
  1231. </para>
  1232. <para>
  1233. トランザクションを終了すると、<classname>Zend_Db_Adapter</classname>
  1234. は再び自動コミットモードに戻ります。
  1235. 手動でのトランザクション管理を使用したい場合は、
  1236. <code>beginTransaction()</code> をもう一度コールします。
  1237. </para>
  1238. <example id="zend.db.adapter.transactions.example">
  1239. <title>一貫性を保持するためのトランザクション管理</title>
  1240. <programlisting role="php"><![CDATA[
  1241. // トランザクションを明示的に開始します
  1242. $db->beginTransaction();
  1243. try {
  1244. // いくつかクエリを実行します
  1245. $db->query(...);
  1246. $db->query(...);
  1247. $db->query(...);
  1248. // すべて成功したら、トランザクションをコミットして
  1249. // すべての変更を一度に適用します
  1250. $db->commit();
  1251. } catch (Exception $e) {
  1252. // いずれかのクエリが失敗して例外が発生したら、
  1253. // もし他に成功しているクエリがあったとしても
  1254. // それも含めてすべての処理をロールバックします。
  1255. // すべて適用されるか、ひとつも適用されないかのいずれかです。
  1256. $db->rollBack();
  1257. echo $e->getMessage();
  1258. }
  1259. ]]></programlisting>
  1260. </example>
  1261. </sect2>
  1262. <sect2 id="zend.db.adapter.list-describe">
  1263. <title>テーブルの情報の取得</title>
  1264. <para>
  1265. <code>listTables()</code> メソッドは文字列の配列を返します。
  1266. この配列には、データベース内のすべてのテーブルの名前が格納されています。
  1267. </para>
  1268. <para>
  1269. <code>describeTable()</code> メソッドは、
  1270. テーブルのメタデータを格納した連想配列を返します。
  1271. このメソッドの最初の引数に、テーブル名を文字列で指定します。
  1272. 二番目の引数はオプションで、そのテーブルが存在するスキーマの名前を指定します。
  1273. exists.
  1274. </para>
  1275. <para>
  1276. 連想配列のキーは、テーブルのカラムの名前となりあmす。
  1277. 各キーに関連付けられた値も連想配列で、以下のキーが存在します。
  1278. </para>
  1279. <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
  1280. <title>describeTable() が返す連想配列のフィールド</title>
  1281. <tgroup cols="3" align="left" colsep="1" rowsep="1">
  1282. <thead>
  1283. <row>
  1284. <entry>キー</entry>
  1285. <entry>型</entry>
  1286. <entry>説明</entry>
  1287. </row>
  1288. </thead>
  1289. <tbody>
  1290. <row>
  1291. <entry>SCHEMA_NAME</entry>
  1292. <entry>(string)</entry>
  1293. <entry>このテーブルが属するデータベーススキーマの名前。</entry>
  1294. </row>
  1295. <row>
  1296. <entry>TABLE_NAME</entry>
  1297. <entry>(string)</entry>
  1298. <entry>このカラムが属するテーブルの名前。</entry>
  1299. </row>
  1300. <row>
  1301. <entry>COLUMN_NAME</entry>
  1302. <entry>(string)</entry>
  1303. <entry>カラム名。</entry>
  1304. </row>
  1305. <row>
  1306. <entry>COLUMN_POSITION</entry>
  1307. <entry>(integer)</entry>
  1308. <entry>テーブル内でのそのカラムの位置。</entry>
  1309. </row>
  1310. <row>
  1311. <entry>DATA_TYPE</entry>
  1312. <entry>(string)</entry>
  1313. <entry>RDBMS で定義されている、そのカラムのデータ型。</entry>
  1314. </row>
  1315. <row>
  1316. <entry>DEFAULT</entry>
  1317. <entry>(string)</entry>
  1318. <entry>もし存在すれば、そのカラムのデフォルト値。</entry>
  1319. </row>
  1320. <row>
  1321. <entry>NULLABLE</entry>
  1322. <entry>(boolean)</entry>
  1323. <entry>そのカラムが SQL の NULL を許可している場合は true、NOT NULL 制約が指定されている場合は false。</entry>
  1324. </row>
  1325. <row>
  1326. <entry>LENGTH</entry>
  1327. <entry>(integer)</entry>
  1328. <entry>RDBMS で定義されている、そのカラムの長さ (サイズ)。</entry>
  1329. </row>
  1330. <row>
  1331. <entry>SCALE</entry>
  1332. <entry>(integer)</entry>
  1333. <entry>SQL の NUMERIC 型あるいは DECIMAL 型での桁数。</entry>
  1334. </row>
  1335. <row>
  1336. <entry>PRECISION</entry>
  1337. <entry>(integer)</entry>
  1338. <entry>SQL の NUMERIC 型あるいは DECIMAL 型での精度。</entry>
  1339. </row>
  1340. <row>
  1341. <entry>UNSIGNED</entry>
  1342. <entry>(boolean)</entry>
  1343. <entry>整数系の型で、符号なし (UNSIGNED) である場合に true。</entry>
  1344. </row>
  1345. <row>
  1346. <entry>PRIMARY</entry>
  1347. <entry>(boolean)</entry>
  1348. <entry>そのカラムが主キーの一部である場合に true。</entry>
  1349. </row>
  1350. <row>
  1351. <entry>PRIMARY_POSITION</entry>
  1352. <entry>(integer)</entry>
  1353. <entry>主キーカラムの中での順序 (最初は 1)。</entry>
  1354. </row>
  1355. <row>
  1356. <entry>IDENTITY</entry>
  1357. <entry>(boolean)</entry>
  1358. <entry>そのカラムが自動生成の値を使用している場合に true。</entry>
  1359. </row>
  1360. </tbody>
  1361. </tgroup>
  1362. </table>
  1363. <note>
  1364. <title>各 RDBMS における IDENTITY メタデータフィールドの対応</title>
  1365. <para>
  1366. IDENTITY メタデータフィールドの名前は、サロゲートキーを表す
  1367. '慣用的な' 名前として選択されたものです。
  1368. このフィールドは、それぞれの RDBMS においては以下のような名前で知られています。
  1369. </para>
  1370. <itemizedlist>
  1371. <listitem>
  1372. <para>
  1373. <code>IDENTITY</code> - DB2, MSSQL
  1374. </para>
  1375. </listitem>
  1376. <listitem>
  1377. <para>
  1378. <code>AUTO_INCREMENT</code> - MySQL
  1379. </para>
  1380. </listitem>
  1381. <listitem>
  1382. <para>
  1383. <code>SERIAL</code> - PostgreSQL
  1384. </para>
  1385. </listitem>
  1386. <listitem>
  1387. <para>
  1388. <code>SEQUENCE</code> - Oracle
  1389. </para>
  1390. </listitem>
  1391. </itemizedlist>
  1392. </note>
  1393. <para>
  1394. 指定したテーブル名とスキーマ名に対応するテーブルが存在しない場合は、
  1395. <code>describeTable()</code> は空の配列を返します。
  1396. </para>
  1397. </sect2>
  1398. <sect2 id="zend.db.adapter.closing">
  1399. <title>接続の終了</title>
  1400. <para>
  1401. 通常は、データベースとの接続を閉じる必要はありません。
  1402. リクエストの処理が終了した時点で、PHP
  1403. が自動的にリソースの後始末を行うからです。
  1404. データベース関連の拡張モジュールは、
  1405. リソースオブジェクトへの参照がなくなった時点で接続を閉じるように設計されています。
  1406. </para>
  1407. <para>
  1408. しかし、実行時間が長くかかり、
  1409. 多くのデータベース接続を扱うような PHP
  1410. スクリプトの場合は、自分で接続を閉じる必要があるかもしれません。
  1411. これにより、RDBMS サーバが限界に達してしまうことを防ぎます。
  1412. データベース接続を明示的に閉じるには、アダプタの
  1413. <code>closeConnection()</code> メソッドを使用します。
  1414. </para>
  1415. <para>
  1416. リリース 1.7.2 以降でしゃ、現在 RDBMS に接続しているかどうかを
  1417. <code>isConnected()</code> メソッドで取得することができます。
  1418. これは、コネクションリソースが初期化されたまままだ閉じられていないことを確認します。
  1419. 現在のところ、たとえばサーバ側で接続が切断された場合などは検出することができません。
  1420. 内部的に、接続を閉じる際にこれを使用しています。
  1421. 接続を複数回閉じてもエラーにはなりません。
  1422. 1.7.2 より前でも PDO アダプタは同じ挙動でしたが、それ以外のアダプタは違いました。
  1423. </para>
  1424. <example id="zend.db.adapter.closing.example">
  1425. <title>データベースとの接続の解除</title>
  1426. <programlisting role="php"><![CDATA[
  1427. $db->closeConnection();
  1428. ]]></programlisting>
  1429. </example>
  1430. <note>
  1431. <title>Zend_Db は持続的な接続をサポートしていますか?</title>
  1432. <para>
  1433. <classname>Zend_Db</classname> では、持続的な接続の使用はサポートしていません。
  1434. </para>
  1435. <para>
  1436. 持続的な接続を使用すると、RDBMS サーバに余計な接続がたまってしまいます。
  1437. 接続作成時のオーバーヘッドが減ることによるパフォーマンスの向上よりも、
  1438. それによって引き起こされる問題のほうが多くなりえます。
  1439. </para>
  1440. <para>
  1441. データベース接続は、その状態を管理しています。
  1442. つまり、RDBMS サーバのオブジェクトの中には
  1443. セッションスコープで存在するものがあるということです。
  1444. セッションスコープで管理される情報の例としては、
  1445. ロックやユーザ変数、一時テーブル、直近に実行したクエリの情報
  1446. (変更された行数、自動生成された ID) などが挙げられます。
  1447. 持続的な接続を使用すると、
  1448. 別の PHP リクエストが作成したデータに
  1449. 誤ってアクセスしてしまう危険が生じてしまいます。
  1450. </para>
  1451. </note>
  1452. </sect2>
  1453. <sect2 id="zend.db.adapter.other-statements">
  1454. <title>その他のステートメントの実行</title>
  1455. <para>
  1456. PHP のデータベース関連拡張モジュールが提供する接続オブジェクトを、
  1457. 直接操作したくなることがあるかもしれません。
  1458. <classname>Zend_Db_Adapter_Abstract</classname> が対応していないような
  1459. そのデータベース固有の機能を使用したい場合などです。
  1460. </para>
  1461. <para>
  1462. <classname>Zend_Db</classname> で SQL 文を実行する場合は、
  1463. 常にプリペア/実行の二段階に分けて処理されます。
  1464. しかし、データベースの機能の中には
  1465. プリペアドステートメントに対応していないようなものもあります。
  1466. たとえば、CREATE や ALTER のような DDL は、
  1467. MySQL ではプリペアドステートメントとすることができません。
  1468. また、MySQL 5.1.17 より前のバージョンでは
  1469. <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">MySQL
  1470. クエリキャッシュ</ulink>
  1471. の機能を活用することができません。
  1472. </para>
  1473. <para>
  1474. たいていの拡張モジュールには、
  1475. プリペアドステートメントではなく直接 SQL
  1476. を実行するためのメソッドが用意されています。
  1477. たとえば PDO なら <code>exec()</code> がそれにあたります。
  1478. 接続オブジェクトに直接アクセスするには、getConnection()
  1479. を使用します。
  1480. </para>
  1481. <example id="zend.db.adapter.other-statements.example">
  1482. <title>PDO アダプタによる、プリペアド形式ではないクエリの実行</title>
  1483. <programlisting role="php"><![CDATA[
  1484. $result = $db->getConnection()->exec('DROP TABLE bugs');
  1485. ]]></programlisting>
  1486. </example>
  1487. <para>
  1488. 同様にして、
  1489. 拡張モジュールが提供するその他のメソッドやプロパティにも
  1490. アクセスすることができます。ただ、注意が必要です。
  1491. このようなことをすると、あなたの作成したアプリケーションが特定の
  1492. RDBMS 用の拡張モジュールに依存してしまうようになります。
  1493. </para>
  1494. <para>
  1495. 将来のバージョンの <classname>Zend_Db</classname> では、
  1496. データベースの拡張モジュールがサポートする機能への
  1497. メソッドエントリポイントを追加できるようにする予定です。
  1498. これは、過去のバージョンとの互換性を損なうことはありません。
  1499. </para>
  1500. </sect2>
  1501. <sect2 id="zend.db.adapter.server-version">
  1502. <title>サーバのバージョンの取得</title>
  1503. <para>
  1504. リリース 1.7.2 以降では、サーバのバージョンを取得することができます。これは、
  1505. PHP の <code>version_compare()</code> で使用できる形式となります。
  1506. 情報が取得できない場合は <code>null</code> が返されます。
  1507. </para>
  1508. <example id="zend.db.adapter.server-version.example">
  1509. <title>サーバのバージョンを取得してからクエリを実行する</title>
  1510. <programlisting role="php"><![CDATA[
  1511. $version = $db->getServerVersion();
  1512. if (!is_null($version)) {
  1513. if (version_compare($version, '5.0.0', '>=')) {
  1514. // 何かを行います
  1515. } else {
  1516. // 何か別のことを行います
  1517. }
  1518. } else {
  1519. // サーバのバージョンを取得できませんでした
  1520. }
  1521. ]]></programlisting>
  1522. </example>
  1523. </sect2>
  1524. <sect2 id="zend.db.adapter.adapter-notes">
  1525. <title>各アダプタ固有の注意点</title>
  1526. <para>
  1527. ここでは、使用するアダプタごとに
  1528. 注意すべき点をまとめます。
  1529. </para>
  1530. <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
  1531. <title>IBM DB2</title>
  1532. <itemizedlist>
  1533. <listitem>
  1534. <para>
  1535. このアダプタを factory() で指定する場合は、名前を
  1536. 'Db2' とします。
  1537. </para>
  1538. </listitem>
  1539. <listitem>
  1540. <para>
  1541. このアダプタは、PHP の ibm_db2 拡張モジュールを使用します。
  1542. </para>
  1543. </listitem>
  1544. <listitem>
  1545. <para>
  1546. IBM DB2 は、シーケンスも自動インクリメントのキーも
  1547. 両方サポートしています。
  1548. したがって、<code>lastInsertId()</code>
  1549. への引数は指定してもしなくてもかまいません。引数を省略した場合は、
  1550. 自動インクリメントのキーが最後に生成した値を返します。
  1551. 引数を指定した場合は、
  1552. '<emphasis>テーブル名</emphasis>_<emphasis>カラム名</emphasis>_seq'
  1553. という名前のシーケンスが最後に生成した値を返します。
  1554. </para>
  1555. </listitem>
  1556. </itemizedlist>
  1557. </sect3>
  1558. <sect3 id="zend.db.adapter.adapter-notes.mysqli">
  1559. <title>MySQLi</title>
  1560. <itemizedlist>
  1561. <listitem>
  1562. <para>
  1563. このアダプタを <code>factory()</code> で指定する場合は、
  1564. 名前を 'Mysqli' とします。
  1565. </para>
  1566. </listitem>
  1567. <listitem>
  1568. <para>
  1569. このアダプタは、PHP の mysqli 拡張モジュールを使用します。
  1570. </para>
  1571. </listitem>
  1572. <listitem>
  1573. <para>
  1574. MySQL はシーケンスをサポートしていません。したがって、
  1575. <code>lastInsertId()</code> に引数を指定してもそれは無視されます。
  1576. 返り値は、常に自動インクリメントのキーの最後の値となります。
  1577. <code>lastSequenceId()</code> メソッドの返り値は
  1578. <code>null</code> となります。
  1579. </para>
  1580. </listitem>
  1581. </itemizedlist>
  1582. </sect3>
  1583. <sect3 id="zend.db.adapter.adapter-notes.oracle">
  1584. <title>Oracle</title>
  1585. <itemizedlist>
  1586. <listitem>
  1587. <para>
  1588. このアダプタを <code>factory()</code> で指定する場合は、
  1589. 名前を 'Oracle' とします。
  1590. </para>
  1591. </listitem>
  1592. <listitem>
  1593. <para>
  1594. このアダプタは、PHP の oci8 拡張モジュールを使用します。
  1595. </para>
  1596. </listitem>
  1597. <listitem>
  1598. <para>
  1599. Oracle は自動インクリメントのキーをサポートしていません。
  1600. したがって、<code>lastInsertId()</code> や
  1601. <code>lastSequenceId()</code>
  1602. にはシーケンス名を指定する必要があります。
  1603. </para>
  1604. </listitem>
  1605. <listitem>
  1606. <para>
  1607. Oracle 拡張モジュールは位置指定によるパラメータをサポートしていません。
  1608. 名前つきパラメータを使用する必要があります。
  1609. </para>
  1610. </listitem>
  1611. <listitem>
  1612. <para>
  1613. 現在、Oracle アダプタでは <classname>Zend_Db::CASE_FOLDING</classname>
  1614. オプションをサポートしていません。Oracle
  1615. でこの機能を使用したい場合は、PDO OCI
  1616. アダプタを使用する必要があります。
  1617. </para>
  1618. </listitem>
  1619. <listitem>
  1620. <para>
  1621. デフォルトでは、LOB フィールドは OCI-Lob オブジェクトで返されます。
  1622. すべてのリクエストでこれを文字列として取得したい場合は、
  1623. ドライバのオプション <code>'lob_as_string'</code> を使用します。
  1624. 特定のリクエストでだけそうしたい場合は、アダプタあるいはステートメントで
  1625. <code>setLobAsString(boolean)</code> を使用します。
  1626. </para>
  1627. </listitem>
  1628. </itemizedlist>
  1629. </sect3>
  1630. <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
  1631. <title>PDO for IBM DB2 and Informix Dynamic Server (IDS)</title>
  1632. <itemizedlist>
  1633. <listitem>
  1634. <para>
  1635. このアダプタを <code>factory()</code> で指定する場合は、
  1636. 名前を 'Pdo_Ibm' とします。
  1637. </para>
  1638. </listitem>
  1639. <listitem>
  1640. <para>
  1641. このアダプタは、PHP の pdo および pdo_ibm 拡張モジュールを使用します。
  1642. </para>
  1643. </listitem>
  1644. <listitem>
  1645. <para>
  1646. PDO_IBM 拡張モジュールのバージョン 1.2.2 以降が必要です。
  1647. これより古いバージョンを使っている場合は、PDO_IBM
  1648. 拡張モジュールを PECL で更新する必要があります。
  1649. </para>
  1650. </listitem>
  1651. </itemizedlist>
  1652. </sect3>
  1653. <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
  1654. <title>PDO Microsoft SQL Server</title>
  1655. <itemizedlist>
  1656. <listitem>
  1657. <para>
  1658. このアダプタを <code>factory()</code> で指定する場合は、
  1659. 名前を 'Pdo_Mssql' とします。
  1660. </para>
  1661. </listitem>
  1662. <listitem>
  1663. <para>
  1664. このアダプタは、PHP の pdo および pdo_mssql 拡張モジュールを使用します。
  1665. </para>
  1666. </listitem>
  1667. <listitem>
  1668. <para>
  1669. Microsoft SQL Server はシーケンスをサポートしていません。
  1670. したがって、
  1671. <code>lastInsertId()</code> に引数を指定してもそれは無視されます。
  1672. 返り値は、常に自動インクリメントのキーの最後の値となります。
  1673. <code>lastSequenceId()</code> メソッドの返り値は
  1674. <code>null</code> となります。
  1675. </para>
  1676. </listitem>
  1677. <listitem>
  1678. <para>
  1679. unicode 文字列を UCS-2 以外のエンコーディング (UTF-8 など)
  1680. で使用する場合は、アプリケーションのコード内での変換処理
  1681. あるいはバイナリカラムへのデータ格納が必要となります。
  1682. 詳細な情報は
  1683. <ulink url="http://support.microsoft.com/kb/232580">Microsoft's Knowledge Base</ulink>
  1684. を参照ください。
  1685. </para>
  1686. </listitem>
  1687. <listitem>
  1688. <para>
  1689. <classname>Zend_Db_Adapter_Pdo_Mssql</classname> は、SQL Server
  1690. に接続した直後に <code>QUOTED_IDENTIFIER ON</code>
  1691. を設定します。これにより、SQL の識別子をクォートする際に
  1692. 標準の区切り文字 (<code>"</code>) を使用するようになります。
  1693. SQL Server の独自仕様である角括弧によるクォートは使用しません。
  1694. </para>
  1695. </listitem>
  1696. <listitem>
  1697. <para>
  1698. オプションの配列で、キーとして <code>pdoType</code>
  1699. を指定することができます。この値は "mssql" (デフォルト)、
  1700. "dblib"、"freetds" あるいは "sybase" のいずれかとなります。
  1701. このオプションは、DSN 文字列を作成する際に使用する
  1702. DSN プレフィックスに影響を与えます。"freetds" および
  1703. "sybase" を指定した場合のプレフィックスは
  1704. "sybase:" となります。これは
  1705. <ulink url="http://www.freetds.org/">FreeTDS</ulink>
  1706. 系のライブラリで用いられるものです。
  1707. このドライバで使用できる DSN プレフィックスの詳細は
  1708. <ulink url="http://www.php.net/manual/ja/ref.pdo-dblib.connection.php">
  1709. http://www.php.net/manual/ja/ref.pdo-dblib.connection.php</ulink>
  1710. を参照ください。
  1711. </para>
  1712. </listitem>
  1713. </itemizedlist>
  1714. </sect3>
  1715. <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
  1716. <title>PDO MySQL</title>
  1717. <itemizedlist>
  1718. <listitem>
  1719. <para>
  1720. このアダプタを <code>factory()</code> で指定する場合は、
  1721. 名前を 'Pdo_Mysql' とします。
  1722. </para>
  1723. </listitem>
  1724. <listitem>
  1725. <para>
  1726. このアダプタは、PHP の pdo および pdo_mysql 拡張モジュールを使用します。
  1727. </para>
  1728. </listitem>
  1729. <listitem>
  1730. <para>
  1731. MySQL はシーケンスをサポートしていません。したがって、
  1732. <code>lastInsertId()</code> に引数を指定してもそれは無視されます。
  1733. 返り値は、常に自動インクリメントのキーの最後の値となります。
  1734. <code>lastSequenceId()</code> メソッドの返り値は
  1735. <code>null</code> となります。
  1736. </para>
  1737. </listitem>
  1738. </itemizedlist>
  1739. </sect3>
  1740. <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
  1741. <title>PDO Oracle</title>
  1742. <itemizedlist>
  1743. <listitem>
  1744. <para>
  1745. このアダプタを <code>factory()</code> で指定する場合は、
  1746. 名前を 'Pdo_Oci' とします。
  1747. </para>
  1748. </listitem>
  1749. <listitem>
  1750. <para>
  1751. このアダプタは、PHP の pdo および pdo_oci 拡張モジュールを使用します。
  1752. </para>
  1753. </listitem>
  1754. <listitem>
  1755. <para>
  1756. Oracle は自動インクリメントのキーをサポートしていません。
  1757. したがって、<code>lastInsertId()</code> や
  1758. <code>lastSequenceId()</code>
  1759. にはシーケンス名を指定する必要があります。
  1760. </para>
  1761. </listitem>
  1762. </itemizedlist>
  1763. </sect3>
  1764. <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
  1765. <title>PDO PostgreSQL</title>
  1766. <itemizedlist>
  1767. <listitem>
  1768. <para>
  1769. このアダプタを <code>factory()</code> で指定する場合は、
  1770. 名前を 'Pdo_Pgsql' とします。
  1771. </para>
  1772. </listitem>
  1773. <listitem>
  1774. <para>
  1775. このアダプタは、PHP の pdo および pdo_pgsql 拡張モジュールを使用します。
  1776. </para>
  1777. </listitem>
  1778. <listitem>
  1779. <para>
  1780. PostgreSQL は、シーケンスも自動インクリメントのキーも
  1781. 両方サポートしています。
  1782. したがって、<code>lastInsertId()</code>
  1783. への引数は指定してもしなくてもかまいません。引数を省略した場合は、
  1784. 自動インクリメントのキーが最後に生成した値を返します。
  1785. 引数を指定した場合は、
  1786. '<emphasis>テーブル名</emphasis>_<emphasis>カラム名</emphasis>_seq'
  1787. という名前のシーケンスが最後に生成した値を返します。
  1788. </para>
  1789. </listitem>
  1790. </itemizedlist>
  1791. </sect3>
  1792. <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
  1793. <title>PDO SQLite</title>
  1794. <itemizedlist>
  1795. <listitem>
  1796. <para>
  1797. このアダプタを <code>factory()</code> で指定する場合は、
  1798. 名前を 'Pdo_Sqlite' とします。
  1799. </para>
  1800. </listitem>
  1801. <listitem>
  1802. <para>
  1803. このアダプタは、PHP の pdo および pdo_sqlite 拡張モジュールを使用します。
  1804. </para>
  1805. </listitem>
  1806. <listitem>
  1807. <para>
  1808. SQLite はシーケンスをサポートしていません。したがって、
  1809. <code>lastInsertId()</code> に引数を指定してもそれは無視されます。
  1810. 返り値は、常に自動インクリメントのキーの最後の値となります。
  1811. <code>lastSequenceId()</code> メソッドの返り値は
  1812. <code>null</code> となります。
  1813. </para>
  1814. </listitem>
  1815. <listitem>
  1816. <para>
  1817. SQLite2 データベースに接続するには、
  1818. Pdo_Sqlite アダプタのインスタンスを作成する際に
  1819. パラメータの配列で
  1820. <code>'sqlite2'=>true</code> を指定します。
  1821. </para>
  1822. </listitem>
  1823. <listitem>
  1824. <para>
  1825. メモリ上の SQLite データベースに接続するには、
  1826. Pdo_Sqlite アダプタのインスタンスを作成する際に
  1827. パラメータの配列で
  1828. <code>'dbname'=>':memory:'</code> を指定します。
  1829. </para>
  1830. </listitem>
  1831. <listitem>
  1832. <para>
  1833. PHP 用の SQLite ドライバの古いバージョンでは、
  1834. 結果セットで短いカラム名を使用するための
  1835. PRAGMA コマンドがサポートされていないようです。
  1836. join クエリを実行した際の結果セットのカラム名が
  1837. "テーブル名.カラム名" 形式になる場合は、
  1838. PHP のバージョンをアップグレードする必要があります。
  1839. </para>
  1840. </listitem>
  1841. </itemizedlist>
  1842. </sect3>
  1843. <sect3 id="zend.db.adapter.adapter-notes.firebird">
  1844. <title>Firebird/Interbase</title>
  1845. <itemizedlist>
  1846. <listitem>
  1847. <para>
  1848. このアダプタは、PHP の php_interbase 拡張モジュールを使用します。
  1849. </para>
  1850. </listitem>
  1851. <listitem>
  1852. <para>
  1853. Firebird/interbase は自動インクリメントのキーをサポートしていません。
  1854. シーケンスの名前を
  1855. <code>lastInsertId()</code> あるいは
  1856. <code>lastSequenceId()</code> に指定する必要があります。
  1857. </para>
  1858. </listitem>
  1859. <listitem>
  1860. <para>
  1861. 現在、Firebird/interbase アダプタでは <classname>Zend_Db::CASE_FOLDING</classname>
  1862. オプションをサポートしていません。
  1863. クォートしていない識別子は、自動的に大文字で返されます。
  1864. </para>
  1865. </listitem>
  1866. <listitem>
  1867. <para>アダプタ名は ZendX_Db_Adapter_Firebird です。</para>
  1868. <para>パラメータ adapterNamespace の値を ZendX_Db_Adapter とすることを覚えておきましょう。</para>
  1869. <para>php にバンドルされている gds32.dll (あるいは linux 環境でそれに相当するもの) をアップデートし、サーバと同じバージョンにしておくことを推奨します。Firebird で gds32.dll に相当するものは fbclient.dll です。</para>
  1870. <para>デフォルトでは、すべての識別子 (テーブル名やフィールド) は大文字で返されます。</para>
  1871. </listitem>
  1872. </itemizedlist>
  1873. </sect3>
  1874. </sect2>
  1875. </sect1>
  1876. <!--
  1877. vim:se ts=4 sw=4 et:
  1878. -->