| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <!-- EN-Revision: 24249 -->
- <sect1 id="zend.db.adapter">
- <title>Zend_Db_Adapter(日本語)</title>
- <!-- Skip-EN-Revisions: 21358 -->
- <para>注意:このドキュメントでは、英語版のリビジョン 21358 の更新内容をスキップしています。</para>
- <para>
- <classname>Zend_Db</classname> とその関連クラス群は、Zend Framework
- において <acronym>SQL</acronym> データベースとのインターフェイスを担当します。
- <classname>Zend_Db_Adapter</classname> は、<acronym>PHP</acronym> アプリケーションから <acronym>RDBMS</acronym>
- に接続する際に使用する基本クラスです。
- <acronym>RDBMS</acronym> の種類に応じて、それぞれ個別のアダプタクラスがあります。
- </para>
- <para>
- <classname>Zend_Db</classname> のアダプタは、
- ベンダ固有の <acronym>PHP</acronym> 拡張モジュールを共通インターフェイスにとりまとめる役割を果たします。
- これにより、いちど書いた <acronym>PHP</acronym> アプリケーションが
- ほんの少しの手間で複数 <acronym>RDBMS</acronym> に対応するようになります。
- </para>
- <para>
- アダプタクラスのインターフェイスは、
- <ulink url="http://jp.php.net/pdo">PHP Data Objects</ulink>
- 拡張モジュールのインターフェイスと似ています。
- <classname>Zend_Db</classname> では、次の <acronym>RDBMS</acronym> 用の <acronym>PDO</acronym> ドライバに対するアダプタクラスを用意しています。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <acronym>IBM</acronym> <acronym>DB2</acronym> および Informix Dynamic Server (<acronym>IDS</acronym>) (<ulink url="http://jp.php.net/pdo-ibm">pdo_ibm</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- MariaDB (<ulink url="http://jp.php.net/pdo-mysql">pdo_mysql</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL (<ulink url="http://jp.php.net/pdo-mysql">pdo_mysql</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server (<ulink url="http://jp.php.net/pdo-dblib">pdo_dblib</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle (<ulink url="http://jp.php.net/pdo-oci">pdo_oci</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL (<ulink url="http://jp.php.net/pdo-pgsql">pdo_pgsql</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite (<ulink url="http://jp.php.net/pdo-sqlite">pdo_sqlite</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- </itemizedlist>
- <para>
- さらに、<classname>Zend_Db</classname> では、
- 以下の <acronym>RDBMS</acronym> 用の拡張モジュールを使用するアダプタクラスも用意しています。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- MariaDB (<ulink url="http://jp.php.net/mysqli">mysqli</ulink> <acronym>PHP</acronym> 拡張モジュールを使用)
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL (<ulink url="http://jp.php.net/mysqli">mysqli</ulink> を使用します)
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle (<ulink url="http://jp.php.net/oci8">oci8</ulink> を使用します)
- </para>
- </listitem>
- <listitem>
- <para>
- <acronym>IBM</acronym> <acronym>DB2</acronym> および <acronym>DB2</acronym> i5 (<ulink url="http://jp.php.net/ibm_db2">ibm_db2</ulink> を使用します)
- </para>
- </listitem>
- <listitem>
- <para>
- Firebird (Interbase) (<ulink url="http://jp.php.net/ibase">php_interbase</ulink> を使用します)
- </para>
- </listitem>
- </itemizedlist>
- <note>
- <para>
- <classname>Zend_Db</classname> のアダプタは、どれも <acronym>PHP</acronym> の拡張モジュールを使用しています。
- <classname>Zend_Db</classname> のアダプタを使用するには、
- 対応する <acronym>PHP</acronym> 拡張モジュールが使用できる環境でなければなりません。
- たとえば、<acronym>PDO</acronym> 系の Zend_Db アダプタを使用するのなら、
- <acronym>PDO</acronym> 拡張モジュールが必要で、
- また使用する <acronym>RDBMS</acronym> 用の <acronym>PDO</acronym> ドライバも必要となります。
- </para>
- </note>
- <sect2 id="zend.db.adapter.connecting">
- <title>アダプタを使用したデータベース接続</title>
- <para>
- ここでは、データベースアダプタのインスタンスを作成する方法を説明します。
- これは、<acronym>PHP</acronym> アプリケーションから <acronym>RDBMS</acronym>
- サーバへの接続を確立することに対応します。
- </para>
- <sect3 id="zend.db.adapter.connecting.constructor">
- <title>Zend_Db アダプタのコンストラクタの使用</title>
- <para>
- コンストラクタを使用して、アダプタのインスタンスを作成できます。
- アダプタのコンストラクタが受け取る引数はひとつで、
- 接続を確立するために必要なパラメータを配列で渡します。
- </para>
- <example id="zend.db.adapter.connecting.constructor.example">
- <title>アダプタのコンストラクタの使用</title>
- <programlisting language="php"><![CDATA[
- $db = new Zend_Db_Adapter_Pdo_Mysql(array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory">
- <title>Zend_Db のファクトリの使用</title>
- <para>
- コンストラクタを直接使用する以外の方法として、静的メソッド
- <methodname>Zend_Db::factory()</methodname> を使用することもできます。
- このメソッドは、必要に応じて
- <link linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>
- を使用して動的にアダプタクラスを読み込みます。
- </para>
- <para>
- 最初の引数には、アダプタクラスのベース名を文字列で指定します。
- たとえば、文字列 '<classname>Pdo_Mysql</classname>' は <classname>Zend_Db_Adapter_Pdo_Mysql</classname>
- クラスに対応します。その次の引数は、
- アダプタのコンストラクタに指定するのと同じ形式の配列となります。
- </para>
- <example id="zend.db.adapter.connecting.factory.example">
- <title>ファクトリメソッドの使用</title>
- <programlisting language="php"><![CDATA[
- // 次の文は不要です。Zend_Db_Adapter_Pdo_Mysql ファイルは
- // Zend_Db の factory メソッドが読み込みます。
- // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
- // 自動的に Zend_Db_Adapter_Pdo_Mysql クラスを読み込み、
- // そのインスタンスを作成します
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- <para>
- 独自に <classname>Zend_Db_Adapter_Abstract</classname>
- の派生クラスを作成し、そのクラス名のプレフィックスが
- "<classname>Zend_Db_Adapter</classname>" でない場合に <methodname>factory()</methodname>
- でそのアダプタを読み込むには、
- 作成したクラス名の先頭の部分をパラメータ配列のキー
- 'adapterNamespace' で指定します。
- </para>
- <example id="zend.db.adapter.connecting.factory.example2">
- <title>自作のアダプタクラスをアダプタのファクトリメソッドで使用する方法</title>
- <programlisting language="php"><![CDATA[
- // アダプタのクラスファイルの読み込みは不要です
- // Zend_Db の factory メソッドが読み込みます
- // 自動的に MyProject_Db_Adapter_Pdo_Mysql クラスを読み込み、
- // インスタンスを作成します
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'adapterNamespace' => 'MyProject_Db_Adapter'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory-config">
- <title>Zend_Db ファクトリでの Zend_Config の使用</title>
- <para>
- <methodname>factory()</methodname> メソッドの引数として、
- <link linkend="zend.config">Zend_Config</link>
- のオブジェクトを渡すこともできます。
- </para>
- <para>
- 最初の引数に config オブジェクトを渡す場合は、そのプロパティに
- <property>adapter</property> が含まれているものとします。
- そこに、アダプタクラス名を表す文字列を指定します。
- また、オプションで <property>params</property> というプロパティも指定することができ、
- その配下のサブプロパティとしてアダプタのパラメータ名を指定します。
- これは、<methodname>factory()</methodname> メソッドの
- 2 番目のパラメータを省略した場合にのみ読み込まれます。
- </para>
- <example id="zend.db.adapter.connecting.factory.example1">
- <title>アダプタのファクトリメソッドでの Zend_Config オブジェクトの使用</title>
- <para>
- 次の例では、配列から <classname>Zend_Config</classname> オブジェクトを作成します。
- それ以外にも、
- <link linkend="zend.config.adapters.ini">Zend_Config_Ini</link>
- や <link linkend="zend.config.adapters.xml">Zend_Config_Xml</link>
- などを用いて外部ファイルからデータを読み込むこともできます。
- </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config(
- array(
- 'database' => array(
- 'adapter' => 'Mysqli',
- 'params' => array(
- 'host' => '127.0.0.1',
- 'dbname' => 'test',
- 'username' => 'webuser',
- 'password' => 'secret',
- )
- )
- )
- );
- $db = Zend_Db::factory($config->database);
- ]]></programlisting>
- </example>
- <para>
- <methodname>factory()</methodname> メソッドの 2 番目の引数には、
- アダプタのパラメータに対応するエントリをもつ連想配列となります。
- この引数はオプションです。最初の引数が <classname>Zend_Config</classname>
- である場合は、そこにすべてのパラメータが含まれているものとみなし、
- 2 番目の引数は無視されます。
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.parameters">
- <title>アダプタのパラメータ</title>
- <para>
- <classname>Zend_Db</classname> のアダプタクラスで使用できるパラメータを以下にまとめます。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>host</emphasis>:
- データベースサーバのホスト名あるいは IP アドレス。
- データベースが <acronym>PHP</acronym> アプリケーションと同じホスト上で動いている場合は、
- 'localhost' あるいは '127.0.0.1' を指定します。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>username</emphasis>:
- <acronym>RDBMS</acronym> サーバへの接続時に使用する認証用アカウントの ID。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>password</emphasis>:
- <acronym>RDBMS</acronym> サーバへの接続時に使用する認証用パスワード。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dbname</emphasis>:
- <acronym>RDBMS</acronym> サーバ上のデータベースインスタンス名。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>port</emphasis>:
- <acronym>RDBMS</acronym> サーバによっては、管理者が指定した
- ポート番号によるネットワーク接続を許可しているものもあります。
- このパラメータを使用すると、<acronym>PHP</acronym>
- アプリケーションが接続時に使用するポート番号を指定できます。
- これは <acronym>RDBMS</acronym> サーバの設定にあわせなければなりません。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>charset</emphasis>:
- 接続に使用する文字セットを指定します。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>options</emphasis>:
- このパラメータは、すべての <classname>Zend_Db_Adapter</classname>
- クラスで共通のオプションを連想配列で指定します。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>driver_options</emphasis>:
- このパラメータは、各データベース拡張モジュールに固有の
- 追加オプションを連想配列で指定します。
- 典型的な使用例としては、<acronym>PDO</acronym> ドライバの属性などがあります。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>adapterNamespace</emphasis>:
- アダプタクラスの名前の先頭が '<classname>Zend_Db_Adapter</classname>'
- 以外である場合に、それを指定します。これは、
- Zend 以外が作成したアダプタクラスを
- <methodname>factory()</methodname> メソッドで使いたい場合に指定します。
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.connecting.parameters.example1">
- <title>ファクトリでの大文字小文字変換オプションの指定</title>
- <para>
- このオプションは、定数
- <constant>Zend_Db::CASE_FOLDING</constant> で指定します。
- これは、<acronym>PDO</acronym> や <acronym>IBM</acronym> <acronym>DB2</acronym> データベースドライバにおける
- <constant>ATTR_CASE</constant> 属性に対応するもので、
- 結果セットの文字列キーの大文字小文字変換を指定します。
- 設定できる値は
- <constant>Zend_Db::CASE_NATURAL</constant> (デフォルト)、
- <constant>Zend_Db::CASE_UPPER</constant> および
- <constant>Zend_Db::CASE_LOWER</constant> のいずれかです。
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Db2', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example2">
- <title>ファクトリでの自動クォートオプションの指定</title>
- <para>
- このオプションは、定数
- <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant> で指定します。
- この値が <constant>TRUE</constant> (デフォルト) の場合は、
- アダプタが生成する <acronym>SQL</acronym> 文中のテーブル名やカラム名、
- エイリアスといった識別子をすべてクォートします。これにより、
- <acronym>SQL</acronym> のキーワードや特殊文字を含む識別子を使用できるようになります。
- この値が <constant>FALSE</constant> の場合は、
- 識別子の自動クォートは行いません。
- クォートすべき文字を使用している場合は、自分で
- <methodname>quoteIdentifier()</methodname> メソッドをコールする必要があります。
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example3">
- <title>ファクトリでの PDO ドライバのオプションの指定</title>
- <programlisting language="php"><![CDATA[
- $pdoParams = array(
- PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'driver_options' => $pdoParams
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- echo $db->getConnection()
- ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example4">
- <title>ファクトリでのシリアライズオプションの指定</title>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::ALLOW_SERIALIZATION => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.getconnection">
- <title>遅延接続の管理</title>
- <para>
- アダプタクラスのインスタンスを作成した時点では、
- まだ <acronym>RDBMS</acronym> サーバへの接続は行われません。
- 接続用のパラメータを内部で保持しておき、
- 実際にクエリを実行することになった時点で初めて接続を確立します。
- これにより、アダプタオブジェクトをすばやく作成できるようになっています。
- つまり、そのリクエストの中で
- 実際にデータベースクエリを発行するかどうかが確定していなくても、
- とりあえずアダプタのインスタンスを作成しておくということもできます。
- </para>
- <para>
- 強制的に <acronym>RDBMS</acronym> との接続を確立する必要がある場合は、
- <methodname>getConnection()</methodname> メソッドを使用します。
- このメソッドは、対応する <acronym>PHP</acronym> 拡張モジュール用の接続オブジェクトを返します。
- たとえば、<acronym>PDO</acronym> ドライバ系のアダプタクラスを使った場合は、
- <methodname>getConnection()</methodname> は
- データベースとの接続を確立してから <acronym>PDO</acronym> オブジェクトを返します。
- </para>
- <para>
- データベースへの接続時に発生する例外、
- すなわち ID やパスワードの間違いなどを捕捉したい場合に、
- これは役立つでしょう。
- 実際に接続を行うまで例外はスローされないので、
- どこか一か所に例外処理をまとめておいたほうが
- アプリケーションがシンプルになって便利でしょう。
- </para>
- <para>
- さらに、アダプタをシリアライズしてたとえばセッション変数などに格納することもできます。
- これは、アダプタだけでなくアダプタを利用する側
- (<classname>Zend_Db_Select</classname> オブジェクトなど) にとっても有用です。
- デフォルトではアダプタのシリアライズが許可されています。
- シリアライズをしたくない場合は、上の例のように
- <constant>Zend_Db::ALLOW_SERIALIZATION</constant> オプションに <constant>FALSE</constant> を渡します。
- 遅延接続の理念を尊重し、アンシリアライズされたアダプタの
- 自動再接続は行いません。つまり、自分で
- <methodname>getConnection()</methodname> をコールしなければなりません。
- 自動再接続を有効にするには、アダプタのオプションとして
- <constant>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE</constant> に <constant>TRUE</constant>
- を渡します。
- </para>
- <example id="zend.db.adapter.connecting.getconnection.example">
- <title>接続時の例外処理</title>
- <programlisting language="php"><![CDATA[
- try {
- $db = Zend_Db::factory('Pdo_Mysql', $parameters);
- $db->getConnection();
- } catch (Zend_Db_Adapter_Exception $e) {
- // ID かパスワードが間違っている、あるいは RDBMS が起動していないなど……
- } catch (Zend_Exception $e) {
- // factory() が指定したアダプタクラスを読み込めなかったなど……
- }
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.example-database">
- <title>サンプルデータベース</title>
- <para>
- <classname>Zend_Db</classname> クラスのドキュメントでは、
- クラスやメソッドの使用法を説明するために単純なデータベースを使用します。
- これは、とあるソフトウェア開発プロジェクトにおけるバグ管理を想定したものです。
- 次の 4 つのテーブルで構成されています。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>accounts</emphasis> テーブルには、
- バグ管理データベースを使用するユーザについての情報を格納します。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>products</emphasis> テーブルには、
- バグを記録する対象となる製品についての情報を格納します。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs</emphasis> テーブルには、
- バグについての情報を格納します。
- バグの状態や報告者、修正担当者、検証担当者などの情報が含まれます。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs_products</emphasis> テーブルには、
- バグと製品の関連付け情報を格納します。
- これは、いわゆる多対多のリレーションシップを実装するものです。
- ひとつのバグが複数の製品に関連するものであることもあれば、
- 当然ひとつの製品には複数のバグが存在するからです。
- </para>
- </listitem>
- </itemizedlist>
- <para>
- このサンプルデータベースを作成するための <acronym>SQL</acronym>
- の擬似コードは、次のようになります。
- これらのテーブルは、<classname>Zend_Db</classname> 自体のユニットテストでも使用します。
- </para>
- <programlisting language="sql"><![CDATA[
- CREATE TABLE accounts (
- account_name VARCHAR(100) NOT NULL PRIMARY KEY
- );
- CREATE TABLE products (
- product_id INTEGER NOT NULL PRIMARY KEY,
- product_name VARCHAR(100)
- );
- CREATE TABLE bugs (
- bug_id INTEGER NOT NULL PRIMARY KEY,
- bug_description VARCHAR(100),
- bug_status VARCHAR(20),
- reported_by VARCHAR(100) REFERENCES accounts(account_name),
- assigned_to VARCHAR(100) REFERENCES accounts(account_name),
- verified_by VARCHAR(100) REFERENCES accounts(account_name)
- );
- CREATE TABLE bugs_products (
- bug_id INTEGER NOT NULL REFERENCES bugs,
- product_id INTEGER NOT NULL REFERENCES products,
- PRIMARY KEY (bug_id, product_id)
- );
- ]]></programlisting>
- <para>
- また、'bugs' テーブルには 'accounts'
- テーブルを指す外部キー参照が複数含まれることにも注意しましょう。
- それぞれの外部キーは、そのバグに対して
- 'accounts' テーブルの別々の行を参照することもあります。
- </para>
- <para>
- サンプルデータベースの物理データモデルは、次の図のようになります。
- </para>
- <para>
- <inlinegraphic width="387" scale="100" align="center" valign="middle"
- fileref="figures/zend.db.adapter.example-database.png" format="PNG" />
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.select">
- <title>クエリ結果の読み込み</title>
- <para>
- ここでは、 <acronym>SELECT</acronym> クエリを実行してその結果を取得するための
- アダプタのメソッドについて説明します。
- </para>
- <sect3 id="zend.db.adapter.select.fetchall">
- <title>結果セット全体の取得</title>
- <para>
- <acronym>SQL</acronym> の <acronym>SELECT</acronym> クエリの実行とその結果の取得を一度に行うには
- <methodname>fetchAll()</methodname> メソッドを使用します。
- </para>
- <para>
- このメソッドの最初の引数には、 <acronym>SELECT</acronym> 文を文字列で指定します。
- あるいは、文字列ではなく
- <link linkend="zend.db.select">Zend_Db_Select</link>
- クラスのオブジェクトを指定することもできます。
- オブジェクトを渡した場合は、アダプタの内部でそれを自動的に
- <acronym>SELECT</acronym> 文の文字列に変換します。
- </para>
- <para>
- <methodname>fetchAll()</methodname> でその次に指定する引数は、
- <acronym>SQL</acronym> 文中のパラメータプレースホルダを置換する値の配列となります。
- </para>
- <example id="zend.db.adapter.select.fetchall.example">
- <title>fetchAll() の使用</title>
- <programlisting language="php"><![CDATA[
- $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
- $result = $db->fetchAll($sql, 2);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetch-mode">
- <title>フェッチモードの変更</title>
- <para>
- デフォルトでは、<methodname>fetchAll()</methodname>
- は行の配列を返します。各行のデータは連想配列となります。
- 連想配列のキーは、列名かあるいは SELECT
- クエリで指定した列の別名となります。
- </para>
- <para>
- 返り値の形式を別のものにするには
- <methodname>setFetchMode()</methodname> メソッドを使用します。
- 対応しているモードは、以下の定数で表されるものです。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis><constant>Zend_Db::FETCH_ASSOC</constant></emphasis>:
- データを、連想配列の配列として返します。
- 配列のキーは、カラム名を文字列で表したものとなります。
- これは、<classname>Zend_Db_Adapter</classname> クラスのデフォルトのフェッチモードです。
- </para>
- <para>
- select で取得する一覧の中に同名のカラムが含まれている場合
- (たとえば複数テーブルを <acronym>JOIN</acronym> した場合など)
- は、その名前のエントリはひとつしか含まれません。
- <constant>FETCH_ASSOC</constant> モードを使用する場合は、
- <acronym>SELECT</acronym> クエリでカラムの別名を指定するなどして、
- 結果の配列におけるキーが一意になるようにしなければなりません。
- </para>
- <para>
- デフォルトでは、これらの文字列はデータベースドライバから返されるものをそのまま使用します。
- 通常は、これは <acronym>RDBMS</acronym> サーバでのカラム名となるでしょう。
- 大文字小文字を指定するには、<constant>Zend_Db::CASE_FOLDING</constant>
- オプションを使用します。これは、
- アダプタのインスタンスを作成する際に使用します。
- <link linkend="zend.db.adapter.connecting.parameters.example1">この例</link>
- を参照ください。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_NUM</emphasis>:
- データを、配列の配列で返します。
- 配列は数値添字形式となり、クエリで指定した順番での位置がキーとなります。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_BOTH</emphasis>:
- データを、配列の配列で返します。
- 配列のキーは、FETCH_ASSOC モードで用いる文字列と
- FETCH_NUM モードで用いる数値の両方を含んだものとなります。
- 配列の要素数が、FETCH_ASSOC や FETCH_NUM
- の場合の倍になることに注意しましょう。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_COLUMN</emphasis>:
- データを、値の配列で返します。
- 配列の各要素の値は、結果セットのあるひとつのカラムの値となります。
- デフォルトでは、これは最初の (0 番目の) カラムとなります。
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_OBJ</emphasis>:
- データを、オブジェクトの配列で返します。
- デフォルトのクラスは、<acronym>PHP</acronym> の組み込みクラス stdClass
- となります。結果セットのカラムは、このクラスのプロパティとしてアクセスできます。
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.select.fetch-mode.example">
- <title>setFetchMode() の使用</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
- // $result はオブジェクトの配列となります
- echo $result[0]->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchassoc">
- <title>連想配列形式での結果セットの取得</title>
- <para>
- <methodname>fetchAssoc()</methodname> メソッドは、
- フェッチモードの設定にかかわらず、
- 最初のカラムを配列のインデックスとして使って、
- 結果のデータを連想配列の配列で返します。
- </para>
- <example id="zend.db.adapter.select.fetchassoc.example">
- <title>fetchAssoc() の使用</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAssoc('SELECT bug_id, bug_description, bug_status FROM bugs');
- // $result は、フェッチモードの指定とは関係なく連想配列の配列となります
- echo $result[2]['bug_description']; // Description of Bug #2
- echo $result[1]['bug_description']; // Description of Bug #1
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchcol">
- <title>結果セットの単一のカラムの取得</title>
- <para>
- <methodname>fetchCol()</methodname> メソッドは、
- フェッチモードの設定にかかわらず、
- 結果のデータを値の配列で返します。
- これは、クエリの最初のカラムのみを返します。
- それ以外のカラムの内容は破棄されます。
- 別のカラムが必要な場合は
- <xref linkend="zend.db.statement.fetching.fetchcolumn" />
- を参照ください。
- </para>
- <example id="zend.db.adapter.select.fetchcol.example">
- <title>fetchCol() の使用</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchCol(
- 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
- // bug_description を含み、bug_id は含みません
- echo $result[0];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchpairs">
- <title>結果セットからの キー/値 のペアの取得</title>
- <para>
- <methodname>fetchPairs()</methodname> メソッドは、データを キー/値
- のペア (連想配列) の配列で返します。
- この連想配列のキーは、 <acronym>SELECT</acronym> クエリが返す最初のカラムの値となります。
- また、連想配列の値は、 <acronym>SELECT</acronym> クエリが返す二番目のカラムの値となります。
- クエリから返されるその他のカラムは破棄されます。
- </para>
- <para>
- <acronym>SELECT</acronym> クエリをうまく設計し、最初のカラムの値が一意になるようにしなければなりません。
- もし最初のカラムに重複する値があれば、連想配列のエントリが上書きされてしまいます。
- </para>
- <example id="zend.db.adapter.select.fetchpairs.example">
- <title>fetchPairs() の例</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchPairs('SELECT bug_id, bug_status FROM bugs');
- echo $result[2];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchrow">
- <title>結果セットからの単一の行の取得</title>
- <para>
- <methodname>fetchRow()</methodname> メソッドは、
- 結果のデータを現在のフェッチモードで返します。
- ただ、返すのは結果セットから取得した最初の行のみです。
- </para>
- <example id="zend.db.adapter.select.fetchrow.example">
- <title>fetchRow() の使用</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
- // $result はオブジェクトの配列ではなく、単なるオブジェクトとなります
- echo $result->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchone">
- <title>結果セットからの単一のスカラー値の取得</title>
- <para>
- <methodname>fetchOne()</methodname> メソッドは
- <methodname>fetchRow()</methodname> と <methodname>fetchCol()</methodname>
- を組み合わせたようなものです。
- 結果セットからの最初の行から、最初のカラムの値のみを返します。
- したがって、このメソッドの返り値は配列やオブジェクトではなく単一のスカラー値となります。
- </para>
- <example id="zend.db.adapter.select.fetchone.example">
- <title>fetchOne() の使用法</title>
- <programlisting language="php"><![CDATA[
- $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
- // これは単なる文字列となります
- echo $result;
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.write">
- <title>データベースへの変更の書き出し</title>
- <para>
- アダプタクラスを使用して、
- 新しいデータをデータベースに書き込んだり
- 既存のデータに変更を加えたりできます。
- ここでは、そのためのメソッドについて説明します。
- </para>
- <sect3 id="zend.db.adapter.write.insert">
- <title>データの挿入</title>
- <para>
- データベースのテーブルに新しい行を追加するには、
- <methodname>insert()</methodname> メソッドを使用します。
- 最初の引数はテーブル名を表す文字列で、
- その次の引数はカラム名とデータの値を関連付けた連想配列となります。
- </para>
- <example id="zend.db.adapter.write.insert.example">
- <title>テーブルへのデータの挿入</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- <para>
- データの配列で指定しなかったカラムについてはデータベースに対して何も指示しません。
- つまり、<acronym>SQL</acronym> の <acronym>INSERT</acronym> 文で列を指定しなかった場合と同じ挙動となります。
- <acronym>DEFAULT</acronym> 句が設定されていればその値が追加され、
- 設定されていなければ <constant>NULL</constant> のままとなります。
- </para>
- <para>
- デフォルトでは、データ配列の値を挿入する際にはパラメータを使用します。
- これにより、ある種のセキュリティ問題が発生する可能性を軽減します。
- データ配列で指定するデータについては、
- エスケープやクォート処理を考慮する必要はありません。
- </para>
- <para>
- データ配列の中の値を <acronym>SQL</acronym> の式として扱い、
- クォートしたくない場合もあるかもしれません。
- デフォルトでは、文字列として渡した値はすべて文字列リテラルとして扱われます。
- その値が <acronym>SQL</acronym> の式であること、つまりクォートしてはいけないということを指定するには、
- 文字列ではなく <classname>Zend_Db_Expr</classname> 型のオブジェクトをデータ配列に渡します。
- </para>
- <example id="zend.db.adapter.write.insert.example2">
- <title>テーブルへの式の挿入</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.lastinsertid">
- <title>生成された値の取得</title>
- <para>
- <acronym>RDBMS</acronym> によっては、主キーの自動インクリメントをサポートしているものもあります。
- この方法で定義したテーブルに新しい行を <acronym>INSERT</acronym> すると、
- 主キーの値が自動的に生成されます。
- <methodname>insert()</methodname> メソッドの返り値は、最後に追加された ID
- では<emphasis>ありません</emphasis>。
- そのテーブルには自動インクリメントのカラムがないかもしれないからです。
- 返り値は、変更された行数 (通常は 1 です) となります。
- </para>
- <para>
- そのテーブルで自動インクリメントの主キーを定義している場合は、
- データを追加した後で <methodname>lastInsertId()</methodname>
- メソッドを使用できます。このメソッドは、
- 現在のデータベース接続において最後に自動生成された値を返します。
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-1">
- <title>自動インクリメントのキーにおける lastInsertId() の使用法</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // 自動インクリメントのカラムで最後に生成された値を返します
- $id = $db->lastInsertId();
- ]]></programlisting>
- </example>
- <para>
- <acronym>RDBMS</acronym> によっては、シーケンスをサポートしているものもあります。
- シーケンスを使用して、主キー用の一意な値を生成できます。
- シーケンスをサポートするために、<methodname>lastInsertId()</methodname>
- ではオプションの文字列引数を 2 つ受け取れるようにしています。
- これらの引数には、それぞれテーブル名とカラム名を指定します。
- シーケンスの名前は、このテーブル名とカラム名をつなげたものの後に
- "_seq" を付加したものとなります。これは、PostgreSQL
- が SERIAL 型のカラムに対して自動生成するシーケンス名の規約にもとづいています。
- たとえば、"bugs" テーブルの主キーカラムが
- "bug_id" である場合は、"bugs_bug_id_seq"
- という名前のシーケンスを使用することになります。
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-2">
- <title>シーケンスにおける lastInsertId() の使用法</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // シーケンス 'bugs_bug_id_seq' が最後に生成した値を返します
- $id = $db->lastInsertId('bugs', 'bug_id');
- // これは、シーケンス 'bugs_seq' が最後に生成した値を返します
- $id = $db->lastInsertId('bugs');
- ]]></programlisting>
- </example>
- <para>
- もしこの命名規約とは異なる名前のシーケンスを使用している場合は、代わりに
- <methodname>lastSequenceId()</methodname> メソッドを使用します。
- このメソッドの引数には、シーケンスの名前を直接指定します。
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-3">
- <title>lastSequenceId() の使用法</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // シーケンス 'bugs_id_gen' が最後に生成した値を返します
- $id = $db->lastSequenceId('bugs_id_gen');
- ]]></programlisting>
- </example>
- <para>
- シーケンスをサポートしていない <acronym>RDBMS</acronym>、たとえば MariaDB や MySQL、
- Microsoft <acronym>SQL</acronym> Server、SQLite などの場合、
- <methodname>lastInsertId()</methodname> メソッドの引数は無視されます。
- このメソッドの返り値は、現在の接続で最後に実行された
- <acronym>INSERT</acronym> 操作が生成した値となります。また、これらの <acronym>RDBMS</acronym> では
- <methodname>lastSequenceId()</methodname> メソッドの返り値は常に <constant>NULL</constant>
- となります。
- </para>
- <note>
- <title>"SELECT MAX(id) FROM table" じゃあダメなんですか?</title>
- <para>
- たしかにこのクエリは、最後にテーブルに追加された主キーの値を返すこともあります。
- しかしこれは、複数のクライアントがデータベースにレコードを追加するという環境では
- 安全ではありません。
- つまり、データを追加してから <methodname>MAX(id)</methodname> の値を取得するまでの間に
- 他のクライアントが別のデータを追加する可能性があるということです。
- この場合、クエリが返す結果はあなたが実際に追加した行の ID とは異なり、
- 誰か他の人が追加した行の ID となってしまいます。
- しかも、もしそのような状況になっていたとしても
- あなたにはそれを知ることはできません。
- </para>
- <para>
- たとえば "repeatable read" のようなトランザクション分離モードを使用すれば、
- この危険性を減らせます。しかし、
- このレベルのトランザクション分離をサポートしていない <acronym>RDBMS</acronym>
- もあります。また、そのアプリケーション自体がもっと緩いレベルの
- トランザクション分離モードを想定して作成されているかもしれません。
- </para>
- <para>
- さらに、新しい主キーの値を生成する際に "MAX(id)+1"
- のような式を使うのも同様に危険です。ふたつのクライアントから同時にこのクエリを実行すると、
- どちらも同じ値を取得することになり、同じ値で <acronym>INSERT</acronym>
- を行なうことになってしまいます。
- </para>
- <para>
- どんな <acronym>RDBMS</acronym> でも、一意な値を生成する機能や
- 最後に生成した値を返す機能は持っています。
- この機能はトランザクション分離レベルとは無関係に機能するはずなので、
- ふたつのクライアントで同じ値が重複してしまうことはありません。
- また、他のクライアントで作成した値が
- あなたの接続で「最後に生成した値」として返されることもありません。
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.adapter.write.update">
- <title>データの更新</title>
- <para>
- データベースのテーブルの行を更新するには、アダプタの
- <methodname>update()</methodname> メソッドを使用します。このメソッドへの引数は
- 3 つです。まず最初はテーブルの名前、
- その次はカラム名と新しい値を関連づけた連想配列となります。
- </para>
- <para>
- 配列で指定した値は、文字列リテラルとして扱われます。
- データ配列で <acronym>SQL</acronym> の式を扱う方法については
- <xref linkend="zend.db.adapter.write.insert" />
- を参照ください。
- </para>
- <para>
- 三番目の引数は、<acronym>SQL</acronym> の式を文字列で指定します。
- これが、変更する行を絞り込むための条件となります。
- ここで指定した値や識別子に対しては、クォートやエスケープは行ないません。
- 何らかの動的な値を使用する場合は、その内容が安全であることを確認するようにしましょう。
- <xref linkend="zend.db.adapter.quoting" />
- で説明しているメソッドを使用するといいでしょう。
- </para>
- <para>
- このメソッドの返り値は、更新操作によって変更された行の数となります。
- </para>
- <example id="zend.db.adapter.write.update.example">
- <title>行の更新</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $n = $db->update('bugs', $data, 'bug_id = 2');
- ]]></programlisting>
- </example>
- <para>
- 三番目の引数を省略した場合は、テーブルのすべての行が指定した値で更新されます。
- </para>
- <para>
- 三番目の引数に文字列の配列を指定すると、各要素の内容を
- <constant>AND</constant> 演算子で連結して使用します。
- </para>
- <para>
- 三番目の引数に配列の配列を提示すると、
- 値は自動的に引用符で囲まれてキーに入れられます。
- そしてこれらは条件として結合され、
- <constant>AND</constant> 演算子で区切られます。
- </para>
- <example id="zend.db.adapter.write.update.example-array">
- <title>式の配列を指定することによる行の更新</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where[] = "reported_by = 'goofy'";
- $where[] = "bug_status = 'OPEN'";
- $n = $db->update('bugs', $data, $where);
- // 実行される SQL は、このようになります
- // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
- // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.write.update.example-arrayofarrays">
- <title>配列の配列を使う行の更新</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where['reported_by = ?'] = 'goofy';
- $where['bug_status = ?'] = 'OPEN';
- $n = $db->update('bugs', $data, $where);
- // 実行される SQL は、このようになります
- // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
- // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.delete">
- <title>行の削除</title>
- <para>
- データベースのテーブルから行を削除するには
- <methodname>delete()</methodname> メソッドを使用します。このメソッドに渡す引数は 2 つで、
- 最初の引数はテーブル名を表す文字列です。
- </para>
- <para>
- 二番目の引数は、<acronym>SQL</acronym> の式を文字列で指定します。
- これが、削除する行を絞り込むための条件となります。
- ここで指定した値や識別子に対しては、クォートやエスケープは行ないません。
- 何らかの動的な値を使用する場合は、その内容が安全であることを確認するようにしましょう。
- <xref linkend="zend.db.adapter.quoting" />
- で説明しているメソッドを使用するといいでしょう。
- </para>
- <para>
- このメソッドの返り値は、削除操作によって変更された行の数となります。
- </para>
- <example id="zend.db.adapter.write.delete.example">
- <title>行の削除</title>
- <programlisting language="php"><![CDATA[
- $n = $db->delete('bugs', 'bug_id = 3');
- ]]></programlisting>
- </example>
- <para>
- 二番目の引数を省略した場合は、テーブルのすべての行を削除します。
- </para>
- <para>
- 二番目の引数に文字列の配列を指定すると、各要素の内容を
- <constant>AND</constant> 演算子で連結して使用します。
- </para>
- <para>
- 二番目の引数に配列の配列を提示すると、
- 値は自動的に引用符で囲まれてキーに入れられます。
- そしてこれらは条件として結合され、
- <constant>AND</constant> 演算子で区切られます。
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.quoting">
- <title>値や識別子のクォート</title>
- <para>
- <acronym>SQL</acronym> を作成する際には、<acronym>PHP</acronym> の変数の値を
- <acronym>SQL</acronym> の式で使用しなければならないこともあるでしょう。
- これは危険な処理です。なぜなら、<acronym>PHP</acronym> の文字列の中には
- たとえばクォート記号のような特殊文字が含まれていることがあり、
- できあがる <acronym>SQL</acronym> がおかしなものになってしまう可能性があるからです。
- たとえば、以下のコードで作成した <acronym>SQL</acronym> は、クォート文字の対応がおかしいものになります。
- <programlisting language="php"><![CDATA[
- $name = "O'Reilly";
- $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
- ]]></programlisting>
- </para>
- <para>
- さらに悪いことに、このようなコードを悪用されると
- あなたのアプリケーションが攻撃の被害を受けることになるかもしれません。
- <acronym>PHP</acronym> の変数の値を HTTP パラメータなどで指定することができれば、
- <acronym>SQL</acronym> クエリを操作して予期せぬことをされてしまう可能性があります
- (たとえば、その人の権限では見えないはずのデータを見られてしまうなど)。
- これは、アプリケーションのセキュリティ問題としては非常に有名な手法で、
- "<acronym>SQL</acronym> インジェクション" と呼ばれています
- (<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">
- 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>
- を参照ください)。
- </para>
- <para>
- <classname>Zend_Db</classname> Adapter クラスの提供する便利な関数を使用すると、
- あなたの <acronym>PHP</acronym> コードが <acronym>SQL</acronym> インジェクション攻撃を受ける危険性を軽減できます。
- この攻撃を回避する方法は、<acronym>PHP</acronym> のクォート文字のような特殊文字を
- 正しくエスケープしてから <acronym>SQL</acronym> に使用することです。
- これにより、不意に (あるいは故意に)
- <acronym>SQL</acronym> に特殊文字が埋め込まれてしまうことを防ぎます。
- </para>
- <sect3 id="zend.db.adapter.quoting.quote">
- <title>quote() の使用法</title>
- <para>
- <methodname>quote()</methodname> メソッドは、引数として文字列を受け取ります。
- そしてその文字列の中の特殊文字をエスケープした上で、
- 両端を区切り文字で囲んだものを返します。
- エスケープ処理は、使用している <acronym>RDBMS</acronym>
- にあわせて適切に行われます。
- 文字列の両端に使用する区切り文字は、標準の <acronym>SQL</acronym>
- ではシングルクォート (') となります。
- </para>
- <example id="zend.db.adapter.quoting.quote.example">
- <title>quote() の使用法</title>
- <programlisting language="php"><![CDATA[
- $name = $db->quote("O'Reilly");
- echo $name;
- // 'O\'Reilly'
- $sql = "SELECT * FROM bugs WHERE reported_by = $name";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- <methodname>quote()</methodname> の返り値には、文字列の両端に区切り文字が追加されていることに注意しましょう。
- これは、たとえば
- <ulink url="http://jp.php.net/mysqli_real_escape_string">mysql_real_escape_string()</ulink>
- のようなエスケープ用関数の挙動とは異なります。
- </para>
- <para>
- 値をクォートするかしないかは、<acronym>SQL</acronym> のデータ型によって異なります。
- たとえば、整数値をクォートしてしまうと
- 数値型カラムや計算式で利用できなくなってしまうという
- <acronym>RDBMS</acronym> もあります。つまり、次のような <acronym>SQL</acronym>
- がエラーになってしまう実装があるということです。
- ここで、 <property>intColumn</property> のデータ型は
- <constant>INTEGER</constant> であるものとします。
- <programlisting language="php"><![CDATA[
- SELECT * FROM atable WHERE intColumn = '123'
- ]]></programlisting>
- </para>
- <para>
- <methodname>quote()</methodname> メソッドでオプションの
- 2 番目の引数を使用すると、
- <acronym>SQL</acronym> のデータ型に応じてクォートするかどうかを選択できます。
- </para>
- <example id="zend.db.adapter.quoting.quote.example-2">
- <title>quote() での SQL データ型の指定</title>
- <programlisting language="php"><![CDATA[
- $value = '1234';
- $sql = 'SELECT * FROM atable WHERE intColumn = '
- . $db->quote($value, 'INTEGER');
- ]]></programlisting>
- </example>
- <para>
- 各 <classname>Zend_Db_Adapter</classname> クラスでは、その <acronym>RDBMS</acronym>
- 用の <acronym>SQL</acronym> 数値データ型の名前がコード化されています。
- それら以外にも
- <constant>Zend_Db::INT_TYPE</constant> や
- <constant>Zend_Db::BIGINT_TYPE</constant>、そして
- <constant>Zend_Db::FLOAT_TYPE</constant>
- といった定数が用意されており、
- これらを使用すると <acronym>RDBMS</acronym> に依存しないコードを書くことができます。
- </para>
- <para>
- <classname>Zend_Db_Table</classname> は、テーブルのキーとなるカラムを使用する際には
- 自動的に <acronym>SQL</acronym> データ型を <methodname>quote()</methodname> に指定します。
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-into">
- <title>quoteInto() の使用法</title>
- <para>
- クォートを使用する場面としていちばんよくあるのが、
- <acronym>PHP</acronym> の変数の値を <acronym>SQL</acronym> の式や文中で使用するということです。
- <methodname>quoteInto()</methodname> メソッドを使用すると、この処理を一度でできるようになります。
- このメソッドが受け取る引数はふたつです。
- まず最初の引数としてプレースホルダ記号 (?)
- を含む文字列を指定し、次の引数で <acronym>PHP</acronym> の変数などの値を指定します。
- ここで指定した値で、プレースホルダの部分を置き換えます。
- </para>
- <para>
- プレースホルダ用の記号は、多くの <acronym>RDBMS</acronym>
- でパラメータとして使用している記号と同じです。しかし、
- <methodname>quoteInto()</methodname> メソッドはあくまでパラメータをエミュレートしているだけです。
- このメソッドは単純に文字列の中に値を放り込み、
- 特殊文字をエスケープして両端をクォートするという処理だけを行います。
- <acronym>RDBMS</acronym> におけるパラメータのように、
- <acronym>SQL</acronym> 文字列と値を分離して <acronym>SQL</acronym> だけを事前に <acronym>RDBMS</acronym>
- サーバでパースするといったことは行いません。
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example">
- <title>quoteInto() の使用法</title>
- <programlisting language="php"><![CDATA[
- $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- <methodname>quoteInto()</methodname> のオプションの
- 3 番目のパラメータを使用すると、<acronym>SQL</acronym> のデータ型を指定できます。
- 数値型はクォートをせず、それ以外の型についてはクォートを行います。
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example-2">
- <title>quoteInto() での SQL データ型の指定</title>
- <programlisting language="php"><![CDATA[
- $sql = $db
- ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 1234
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-identifier">
- <title>quoteIdentifier() の使用法</title>
- <para>
- 変数を使用する可能性があるのは、<acronym>SQL</acronym> 文中の値だけとは限りません。
- <acronym>SQL</acronym> 文中でのテーブル名やカラム名などの識別子として
- <acronym>PHP</acronym> の変数を使用する場合も、同様にクォートする必要があります。
- デフォルトでは、<acronym>SQL</acronym> の識別子に使用できる文字は
- <acronym>PHP</acronym> などのプログラミング言語の規則と似ています。
- たとえば、識別子には空白文字や記号を使用することはできませんし、
- またアルファベット以外の文字も使えません。
- <acronym>SQL</acronym> の文法上特別な意味を持つ単語として予約されているものも、
- そのままでは識別子として使用できません。
- </para>
- <para>
- しかし、適切な区切り文字でクォートすれば、
- 識別子として使用できる文字の幅が広がります。
- 本来識別子として使用できない文字を含んでいても、
- 適切な形式でクォートすることで <acronym>SQL</acronym> の識別子として使用できるようになります。
- たとえば、空白や記号などを使うこともできますし、
- <acronym>SQL</acronym> で予約語として指定されている単語であっても使用可能です。
- </para>
- <para>
- <methodname>quoteIdentifier()</methodname> メソッドの働きは
- <methodname>quote()</methodname> と似ていますが、
- このメソッドは使用しているアダプタの型に応じた識別子区切り文字を付加します。
- たとえば、標準 <acronym>SQL</acronym> ではダブルクォート
- (") を区切り文字として使用します。
- 多くの <acronym>RDBMS</acronym> がこれにしたがっています。
- MySQL の場合は、デフォルトではバッククォート
- (`) を使用します。
- <methodname>quoteIdentifier()</methodname> メソッドはまた、
- 文字列引数内の特殊文字のエスケープも行います。
- </para>
- <example id="zend.db.adapter.quoting.quote-identifier.example">
- <title>quoteIdentifier() の使用法</title>
- <programlisting language="php"><![CDATA[
- // テーブル名に、SQL の予約語を使用します
- $tableName = $db->quoteIdentifier("order");
- $sql = "SELECT * FROM $tableName";
- echo $sql
- // SELECT * FROM "order"
- ]]></programlisting>
- </example>
- <para>
- クォートしていない場合とは異なり、
- クォートした識別子は大文字小文字を区別するようになります。
- したがって、クォートした識別子を使用する場合は
- 大文字小文字の指定も含めて識別子をきちんと記述する必要があります。
- </para>
- <para>
- たいていの場合は <classname>Zend_Db</classname> クラスで自動的に <acronym>SQL</acronym>
- を生成することになるでしょう。デフォルトでは、
- すべての識別子が自動的にクォートされます。
- この挙動を変更するには、オプション
- <constant>Zend_Db::AUTO_QUOTE_IDENTIFIERS</constant>
- を変更します。これは、アダプタのインスタンスを作成する際に指定します。
- <xref linkend="zend.db.adapter.connecting.parameters.example2" />
- を参照ください。
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.transactions">
- <title>データベースのトランザクションの制御</title>
- <para>
- データベースには「トランザクション」と呼ばれる論理的な作業単位があります。
- 複数のテーブルにまたがる操作などを一括して更新 (コミット) したり、
- 一括して取消 (ロールバック) したりできるようになります。
- データベースドライバがトランザクションを暗黙的にサポートしている場合は、
- すべてのクエリがトランザクション内で実行されます。
- これを<emphasis>自動コミット</emphasis>モードといいます。
- このモードでは、あらゆるクエリを実行する前に
- ドライバが自動的にトランザクションを開始し、
- 実行が完了したら自動的にトランザクションをコミットします。
- デフォルトでは、すべての <classname>Zend_Db</classname>
- アダプタクラスは自動コミットモードで動作します。
- </para>
- <para>
- 一方、トランザクションの始点と終点を自分で指定することにより、
- 複数の <acronym>SQL</acronym> クエリをひとつのトランザクション内ですることもできます。
- トランザクションを開始する際には <methodname>beginTransaction()</methodname>
- メソッドを使用します。それ以降に実行した <acronym>SQL</acronym>
- 文は、明示的に指定するまではすべて同じトランザクション内で動作します。
- </para>
- <para>
- トランザクションを終了するには、<methodname>commit()</methodname>
- あるいは <methodname>rollBack()</methodname> のいずれかを使用します。
- <methodname>commit()</methodname> メソッドは、
- そのトランザクションでの変更内容をコミットします。
- つまり、そのトランザクションで行った変更が、
- 他のトランザクションからも見えるようにするということです。
- </para>
- <para>
- <methodname>rollBack()</methodname> メソッドはその反対の動作をします。
- このメソッドは、そのトランザクションでの変更内容をすべて破棄します。
- 変更は一切なかったことになり、トランザクションを開始する前の状態にデータを戻します。
- しかし、あるトランザクションをロールバックしたとしても、
- その間に他のトランザクションで行った変更には何の影響も与えません。
- </para>
- <para>
- トランザクションを終了すると、<classname>Zend_Db_Adapter</classname>
- は再び自動コミットモードに戻ります。
- 手動でのトランザクション管理を使用したい場合は、
- <methodname>beginTransaction()</methodname> をもう一度コールします。
- </para>
- <example id="zend.db.adapter.transactions.example">
- <title>一貫性を保持するためのトランザクション管理</title>
- <programlisting language="php"><![CDATA[
- // トランザクションを明示的に開始します
- $db->beginTransaction();
- try {
- // いくつかクエリを実行します
- $db->query(...);
- $db->query(...);
- $db->query(...);
- // すべて成功したら、トランザクションをコミットして
- // すべての変更を一度に適用します
- $db->commit();
- } catch (Exception $e) {
- // いずれかのクエリが失敗して例外が発生したら、
- // もし他に成功しているクエリがあったとしても
- // それも含めてすべての処理をロールバックします。
- // すべて適用されるか、ひとつも適用されないかのいずれかです。
- $db->rollBack();
- echo $e->getMessage();
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.list-describe">
- <title>テーブルの情報の取得</title>
- <para>
- <methodname>listTables()</methodname> メソッドは文字列の配列を返します。
- この配列には、データベース内のすべてのテーブルの名前が格納されています。
- </para>
- <para>
- <methodname>describeTable()</methodname> メソッドは、
- テーブルのメタデータを格納した連想配列を返します。
- このメソッドの最初の引数に、テーブル名を文字列で指定します。
- 二番目の引数はオプションで、そのテーブルが存在するスキーマの名前を指定します。
- </para>
- <para>
- 連想配列のキーは、テーブルのカラムの名前となります。
- 各キーに関連付けられた値も連想配列で、以下のキーが存在します。
- </para>
- <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
- <title>describeTable() が返す連想配列のフィールド</title>
- <tgroup cols="3" align="left" colsep="1" rowsep="1">
- <thead>
- <row>
- <entry>キー</entry>
- <entry>型</entry>
- <entry>説明</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><constant>SCHEMA_NAME</constant></entry>
- <entry>(string)</entry>
- <entry>このテーブルが属するデータベーススキーマの名前。</entry>
- </row>
- <row>
- <entry><constant>TABLE_NAME</constant></entry>
- <entry>(string)</entry>
- <entry>このカラムが属するテーブルの名前。</entry>
- </row>
- <row>
- <entry><constant>COLUMN_NAME</constant></entry>
- <entry>(string)</entry>
- <entry>カラム名。</entry>
- </row>
- <row>
- <entry><constant>COLUMN_POSITION</constant></entry>
- <entry>(integer)</entry>
- <entry>テーブル内でのそのカラムの位置。</entry>
- </row>
- <row>
- <entry><constant>DATA_TYPE</constant></entry>
- <entry>(string)</entry>
- <entry>RDBMS で定義されている、そのカラムのデータ型。</entry>
- </row>
- <row>
- <entry><constant>DEFAULT</constant></entry>
- <entry>(string)</entry>
- <entry>もし存在すれば、そのカラムのデフォルト値。</entry>
- </row>
- <row>
- <entry><constant>NULLABLE</constant></entry>
- <entry>(boolean)</entry>
- <entry>そのカラムが <acronym>SQL</acronym> の <constant>NULL</constant> を許可している場合は <constant>TRUE</constant> 、
- <constant>NOT</constant> <constant>NULL</constant> 制約が指定されている場合は <constant>FALSE</constant>。</entry>
- </row>
- <row>
- <entry><constant>LENGTH</constant></entry>
- <entry>(integer)</entry>
- <entry><acronym>RDBMS</acronym> で定義されている、そのカラムの長さ (サイズ)。</entry>
- </row>
- <row>
- <entry><constant>SCALE</constant></entry>
- <entry>(integer)</entry>
- <entry><acronym>SQL</acronym> の NUMERIC 型あるいは <constant>DECIMAL</constant> 型での桁数。</entry>
- </row>
- <row>
- <entry><constant>PRECISION</constant></entry>
- <entry>(integer)</entry>
- <entry><acronym>SQL</acronym> の NUMERIC 型あるいは <constant>DECIMAL</constant> 型での精度。</entry>
- </row>
- <row>
- <entry><constant>UNSIGNED</constant></entry>
- <entry>(boolean)</entry>
- <entry>整数系の型で、符号なし (<constant>UNSIGNED</constant>) である場合に <constant>TRUE</constant>。</entry>
- </row>
- <row>
- <entry><constant>PRIMARY</constant></entry>
- <entry>(boolean)</entry>
- <entry>そのカラムが主キーの一部である場合に <constant>TRUE</constant>。</entry>
- </row>
- <row>
- <entry><constant>PRIMARY_POSITION</constant></entry>
- <entry>(integer)</entry>
- <entry>主キーカラムの中での順序 (最初は 1)。</entry>
- </row>
- <row>
- <entry><constant>IDENTITY</constant></entry>
- <entry>(boolean)</entry>
- <entry>そのカラムが自動生成の値を使用している場合に <constant>TRUE</constant>。</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <title>各 RDBMS における IDENTITY メタデータフィールドの対応</title>
- <para>
- IDENTITY メタデータフィールドの名前は、サロゲートキーを表す
- '慣用的な' 名前として選択されたものです。
- このフィールドは、それぞれの <acronym>RDBMS</acronym> においては以下のような名前で知られています。
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <constant>IDENTITY</constant> - DB2, MSSQL
- </para>
- </listitem>
- <listitem>
- <para>
- <constant>AUTO_INCREMENT</constant> - MySQL/MariaDB
- </para>
- </listitem>
- <listitem>
- <para>
- <constant>SERIAL</constant> - PostgreSQL
- </para>
- </listitem>
- <listitem>
- <para>
- <constant>SEQUENCE</constant> - Oracle
- </para>
- </listitem>
- </itemizedlist>
- </note>
- <para>
- 指定したテーブル名とスキーマ名に対応するテーブルが存在しない場合は、
- <methodname>describeTable()</methodname> は空の配列を返します。
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.closing">
- <title>接続の終了</title>
- <para>
- 通常は、データベースとの接続を閉じる必要はありません。
- リクエストの処理が終了した時点で、<acronym>PHP</acronym>
- が自動的にリソースの後始末を行うからです。
- データベース関連の拡張モジュールは、
- リソースオブジェクトへの参照がなくなった時点で接続を閉じるように設計されています。
- </para>
- <para>
- しかし、実行時間が長くかかり、
- 多くのデータベース接続を扱うような <acronym>PHP</acronym>
- スクリプトの場合は、自分で接続を閉じる必要があるかもしれません。
- これにより、<acronym>RDBMS</acronym> サーバが限界に達してしまうことを防ぎます。
- データベース接続を明示的に閉じるには、アダプタの
- <methodname>closeConnection()</methodname> メソッドを使用します。
- </para>
- <para>
- リリース 1.7.2 以降では、現在 <acronym>RDBMS</acronym> に接続しているかどうかを
- <methodname>isConnected()</methodname> メソッドで取得できます。
- これは、コネクションリソースが初期化されたまままだ閉じられていないことを確認します。
- 現在のところ、たとえばサーバ側で接続が切断された場合などは検出することができません。
- 内部的に、接続を閉じる際にこれを使用しています。
- 接続を複数回閉じてもエラーにはなりません。
- 1.7.2 より前でも <acronym>PDO</acronym> アダプタは同じ挙動でしたが、それ以外のアダプタは違いました。
- </para>
- <example id="zend.db.adapter.closing.example">
- <title>データベースとの接続の解除</title>
- <programlisting language="php"><![CDATA[
- $db->closeConnection();
- ]]></programlisting>
- </example>
- <note>
- <title>Zend_Db は持続的な接続をサポートしていますか?</title>
- <para>
- はい。<classname>Zend_Db</classname> のアダプタの設定
- (driver_configuration ではありません) で、
- <property>persistent</property> フラグを <constant>TRUE</constant> に設定することで対応します。
- </para>
- <example id="zend.db.adapter.connecting.persistence.example">
- <title>Oracle アダプタでの持続的接続の使用</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory('Oracle', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'persistent' => true
- ));
- ]]></programlisting>
- </example>
- <para>
- 持続的な接続を使用すると、<acronym>RDBMS</acronym> サーバに余計な接続がたまってしまうことに注意しましょう。
- 接続作成時のオーバーヘッドが減ることによるパフォーマンスの向上よりも、
- それによって引き起こされる問題のほうが多くなりえます。
- </para>
- <para>
- データベース接続は、その状態を管理しています。
- つまり、<acronym>RDBMS</acronym> サーバのオブジェクトの中には
- セッションスコープで存在するものがあるということです。
- セッションスコープで管理される情報の例としては、
- ロックやユーザ変数、一時テーブル、直近に実行したクエリの情報
- (変更された行数、自動生成された ID) などが挙げられます。
- 持続的な接続を使用すると、
- 別の <acronym>PHP</acronym> リクエストが作成したデータに
- 誤ってアクセスしてしまう危険が生じてしまいます。
- </para>
- <para>
- 現在、<classname>Zend_Db</classname> が持続的接続をサポートしているのは
- Oracle、DB2 そして <acronym>PDO</acronym> アダプタ
- (<acronym>PHP</acronym> が指定します) のみです。
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.adapter.other-statements">
- <title>その他のステートメントの実行</title>
- <para>
- <acronym>PHP</acronym> のデータベース関連拡張モジュールが提供する接続オブジェクトを、
- 直接操作したくなることがあるかもしれません。
- <classname>Zend_Db_Adapter_Abstract</classname> が対応していないような
- そのデータベース固有の機能を使用したい場合などです。
- </para>
- <para>
- <classname>Zend_Db</classname> で <acronym>SQL</acronym> 文を実行する場合は、
- 常にプリペア/実行の二段階に分けて処理されます。
- しかし、データベースの機能の中には
- プリペアドステートメントに対応していないようなものもあります。
- たとえば、CREATE や ALTER のような DDL は、
- MySQL ではプリペアドステートメントとすることができません。
- また、MySQL 5.1.17 より前のバージョンでは
- <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">MySQL
- クエリキャッシュ</ulink>
- の機能を活用することができません。
- </para>
- <para>
- たいていの拡張モジュールには、
- プリペアドステートメントではなく直接 <acronym>SQL</acronym>
- を実行するためのメソッドが用意されています。
- たとえば <acronym>PDO</acronym> なら <methodname>exec()</methodname> がそれにあたります。
- 接続オブジェクトに直接アクセスするには、
- <methodname>getConnection()</methodname> を使用します。
- </para>
- <example id="zend.db.adapter.other-statements.example">
- <title>PDO アダプタによる、プリペアド形式ではないクエリの実行</title>
- <programlisting language="php"><![CDATA[
- $result = $db->getConnection()->exec('DROP TABLE bugs');
- ]]></programlisting>
- </example>
- <para>
- 同様にして、
- 拡張モジュールが提供するその他のメソッドやプロパティにも
- アクセスできます。ただ、注意が必要です。
- このようなことをすると、あなたの作成したアプリケーションが特定の
- <acronym>RDBMS</acronym> 用の拡張モジュールに依存してしまうようになります。
- </para>
- <para>
- 将来のバージョンの <classname>Zend_Db</classname> では、
- データベースの拡張モジュールがサポートする機能への
- メソッドエントリポイントを追加できるようにする予定です。
- これは、過去のバージョンとの互換性を損なうことはありません。
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.server-version">
- <title>サーバのバージョンの取得</title>
- <para>
- リリース 1.7.2 以降では、サーバのバージョンを取得できます。これは、
- <acronym>PHP</acronym> の <methodname>version_compare()</methodname> で使用できる形式となります。
- 情報が取得できない場合は <constant>NULL</constant> が返されます。
- </para>
- <example id="zend.db.adapter.server-version.example">
- <title>サーバのバージョンを取得してからクエリを実行する</title>
- <programlisting language="php"><![CDATA[
- $version = $db->getServerVersion();
- if (!is_null($version)) {
- if (version_compare($version, '5.0.0', '>=')) {
- // 何かを行います
- } else {
- // 何か別のことを行います
- }
- } else {
- // サーバのバージョンを取得できませんでした
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.adapter-notes">
- <title>各アダプタ固有の注意点</title>
- <para>
- ここでは、使用するアダプタごとに
- 注意すべき点をまとめます。
- </para>
- <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
- <title>IBM DB2</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、名前を
- 'Db2' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の ibm_db2 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- <acronym>IBM</acronym> <acronym>DB2</acronym> は、シーケンスも自動インクリメントのキーも
- 両方サポートしています。
- したがって、<methodname>lastInsertId()</methodname>
- への引数は指定してもしなくてもかまいません。引数を省略した場合は、
- 自動インクリメントのキーが最後に生成した値を返します。
- 引数を指定した場合は、
- '<emphasis>テーブル名</emphasis>_<emphasis>カラム名</emphasis>_seq'
- という名前のシーケンスが最後に生成した値を返します。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.mysqli">
- <title>MySQLi</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を 'Mysqli' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の mysqli 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL 及び MariaDB はシーケンスをサポートしていません。したがって、
- <methodname>lastInsertId()</methodname> に引数を指定してもそれは無視されます。
- 返り値は、常に自動インクリメントのキーの最後の値となります。
- <methodname>lastSequenceId()</methodname> メソッドの返り値は
- <constant>NULL</constant> となります。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.oracle">
- <title>Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を 'Oracle' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の oci8 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle は自動インクリメントのキーをサポートしていません。
- したがって、<methodname>lastInsertId()</methodname> や
- <methodname>lastSequenceId()</methodname>
- にはシーケンス名を指定する必要があります。
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle 拡張モジュールは位置指定によるパラメータをサポートしていません。
- 名前つきパラメータを使用する必要があります。
- </para>
- </listitem>
- <listitem>
- <para>
- 現在、Oracle アダプタでは <constant>Zend_Db::CASE_FOLDING</constant>
- オプションをサポートしていません。Oracle
- でこの機能を使用したい場合は、<acronym>PDO</acronym> OCI
- アダプタを使用する必要があります。
- </para>
- </listitem>
- <listitem>
- <para>
- デフォルトでは、LOB フィールドは OCI-Lob オブジェクトで返されます。
- すべてのリクエストでこれを文字列として取得したい場合は、
- ドライバのオプション '<property>lob_as_string</property>' を使用します。
- 特定のリクエストでだけそうしたい場合は、アダプタあるいはステートメントで
- <methodname>setLobAsString(boolean)</methodname> を使用します。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.sqlsrv">
- <title>Microsoft SQL Server</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を 'Sqlsrv' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の sqlsrv 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server 2005 以降のみサポートされます。
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server はシーケンスをサポートしていません。
- したがって、<methodname>lastInsertId()</methodname> に指定した主キー引数は無視されます。
- テーブル名を指定した場合は自動インクリメントキーで最後に生成した値を返し、
- そうでない場合は最後に実行した挿入クエリが返した ID を返します。
- <methodname>lastSequenceId()</methodname> メソッドの返り値は
- <constant>NULL</constant> となります。
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Db_Adapter_Sqlsrv</classname> は、
- <acronym>SQL</acronym> Server データベースに接続した直後に
- <constant>QUOTED_IDENTIFIER ON</constant> を設定します。
- これは、ドライバで使用する識別子区切り文字を、標準
- <acronym>SQL</acronym> 形式 (<emphasis>"</emphasis>)
- に設定するものです。<acronym>SQL</acronym> Server
- は独自形式の角括弧構文を使用していますが、
- それは使わないようになります。
- </para>
- </listitem>
- <listitem>
- <para>
- オプション配列のキーに <property>driver_options</property>
- を指定できます。この値は <ulink
- url="http://msdn.microsoft.com/ja-jp/library/cc296161(SQL.90).aspx">http://msdn.microsoft.com/ja-jp/library/cc296161(SQL.90).aspx</ulink>
- に書かれているものとなります。
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>setTransactionIsolationLevel()</methodname>
- で、現在の接続の分離レベルを設定できます。値は
- <constant>SQLSRV_TXN_READ_UNCOMMITTED</constant>、
- <constant>SQLSRV_TXN_READ_COMMITTED</constant>、
- <constant>SQLSRV_TXN_REPEATABLE_READ</constant>、
- <constant>SQLSRV_TXN_SNAPSHOT</constant> あるいは
- <constant>SQLSRV_TXN_SERIALIZABLE</constant> のいずれかとなります。
- </para>
- </listitem>
- <listitem>
- <para>
- Zend Framework 1.9 以降は、Microsoft の
- <acronym>PHP</acronym> <acronym>SQL</acronym> Server 拡張モジュール
- 1.0.1924.0 以降と <acronym>MSSQL</acronym> Server Native
- Client バージョン 9.00.3042.00 以降をサポートします。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
- <title>PDO for IBM DB2 and Informix Dynamic Server (IDS)</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Ibm</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_ibm 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- PDO_IBM 拡張モジュールのバージョン 1.2.2 以降が必要です。
- これより古いバージョンを使っている場合は、PDO_IBM
- 拡張モジュールを <acronym>PECL</acronym> で更新する必要があります。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
- <title>PDO Microsoft SQL Server</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Mssql</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_dblib 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft <acronym>SQL</acronym> Server はシーケンスをサポートしていません。
- したがって、
- <methodname>lastInsertId()</methodname> に引数を指定してもそれは無視されます。
- 返り値は、常に自動インクリメントのキーの最後の値となります。
- <methodname>lastSequenceId()</methodname> メソッドの返り値は
- <constant>NULL</constant> となります。
- </para>
- </listitem>
- <listitem>
- <para>
- unicode 文字列を UCS-2 以外のエンコーディング (UTF-8 など)
- で使用する場合は、アプリケーションのコード内での変換処理
- あるいはバイナリカラムへのデータ格納が必要となります。
- 詳細な情報は
- <ulink url="http://support.microsoft.com/kb/232580">Microsoft's Knowledge Base</ulink>
- を参照ください。
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Db_Adapter_Pdo_Mssql</classname> は、SQL Server
- に接続した直後に <constant>QUOTED_IDENTIFIER ON</constant>
- を設定します。これにより、<acronym>SQL</acronym> の識別子をクォートする際に
- 標準の区切り文字 (") を使用するようになります。
- <acronym>SQL</acronym> Server の独自仕様である角括弧によるクォートは使用しません。
- </para>
- </listitem>
- <listitem>
- <para>
- オプションの配列で、キーとして <property>pdoType</property>
- を指定できます。この値は "mssql" (デフォルト)、
- "dblib"、"freetds" あるいは "sybase" のいずれかとなります。
- このオプションは、 <acronym>DSN</acronym> 文字列を作成する際に使用する
- <acronym>DSN</acronym> プレフィックスに影響を与えます。"freetds" および
- "sybase" を指定した場合のプレフィックスは
- "sybase:" となります。これは
- <ulink url="http://www.freetds.org/">FreeTDS</ulink>
- 系のライブラリで用いられるものです。
- このドライバで使用できる <acronym>DSN</acronym> プレフィックスの詳細は
- <ulink url="http://jp.php.net/manual/ja/ref.pdo-dblib.connection.php">
- http://jp.php.net/manual/ja/ref.pdo-dblib.connection.php</ulink>
- を参照ください。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
- <title>PDO MySQL</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Mysql</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_mysql 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL 及び MariaDB はシーケンスをサポートしていません。したがって、
- <methodname>lastInsertId()</methodname> に引数を指定してもそれは無視されます。
- 返り値は、常に自動インクリメントのキーの最後の値となります。
- <methodname>lastSequenceId()</methodname> メソッドの返り値は
- <constant>NULL</constant> となります。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
- <title>PDO Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Oci</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_oci 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle は自動インクリメントのキーをサポートしていません。
- したがって、<methodname>lastInsertId()</methodname> や
- <methodname>lastSequenceId()</methodname>
- にはシーケンス名を指定する必要があります。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
- <title>PDO PostgreSQL</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Pgsql</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_pgsql 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL は、シーケンスも自動インクリメントのキーも
- 両方サポートしています。
- したがって、<methodname>lastInsertId()</methodname>
- への引数は指定してもしなくてもかまいません。引数を省略した場合は、
- 自動インクリメントのキーが最後に生成した値を返します。
- 引数を指定した場合は、
- '<emphasis>テーブル名</emphasis>_<emphasis>カラム名</emphasis>_seq'
- という名前のシーケンスが最後に生成した値を返します。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
- <title>PDO SQLite</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタを <methodname>factory()</methodname> で指定する場合は、
- 名前を '<classname>Pdo_Sqlite</classname>' とします。
- </para>
- </listitem>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の pdo および pdo_sqlite 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite はシーケンスをサポートしていません。したがって、
- <methodname>lastInsertId()</methodname> に引数を指定してもそれは無視されます。
- 返り値は、常に自動インクリメントのキーの最後の値となります。
- <methodname>lastSequenceId()</methodname> メソッドの返り値は
- <constant>NULL</constant> となります。
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite2 データベースに接続するには、
- <classname>Pdo_Sqlite</classname> アダプタのインスタンスを作成する際に
- パラメータの配列で
- <command>'sqlite2' => true</command> を指定します。
- </para>
- </listitem>
- <listitem>
- <para>
- メモリ上の SQLite データベースに接続するには、
- <classname>Pdo_Sqlite</classname> アダプタのインスタンスを作成する際に
- パラメータの配列で
- <command>'dbname' => ':memory:'</command> を指定します。
- </para>
- </listitem>
- <listitem>
- <para>
- <acronym>PHP</acronym> 用の SQLite ドライバの古いバージョンでは、
- 結果セットで短いカラム名を使用するための
- PRAGMA コマンドがサポートされていないようです。
- join クエリを実行した際の結果セットのカラム名が
- "テーブル名.カラム名" 形式になる場合は、
- <acronym>PHP</acronym> のバージョンをアップグレードする必要があります。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.firebird">
- <title>Firebird/Interbase</title>
- <itemizedlist>
- <listitem>
- <para>
- このアダプタは、<acronym>PHP</acronym> の php_interbase 拡張モジュールを使用します。
- </para>
- </listitem>
- <listitem>
- <para>
- Firebird (interbase) は自動インクリメントのキーをサポートしていません。
- シーケンスの名前を
- <methodname>lastInsertId()</methodname> あるいは
- <methodname>lastSequenceId()</methodname> に指定する必要があります。
- </para>
- </listitem>
- <listitem>
- <para>
- 現在、Firebird (interbase) アダプタでは <constant>Zend_Db::CASE_FOLDING</constant>
- オプションをサポートしていません。
- クォートしていない識別子は、自動的に大文字で返されます。
- </para>
- </listitem>
- <listitem>
- <para>
- アダプタ名は <classname>ZendX_Db_Adapter_Firebird</classname> です。
- </para>
- <para>
- パラメータ adapterNamespace の値を <classname>ZendX_Db_Adapter</classname> とすることを覚えておきましょう。
- </para>
- <para>
- <acronym>PHP</acronym> にバンドルされている <filename>gds32.dll</filename> (あるいは linux 環境でそれに相当するもの) をアップデートし、
- サーバと同じバージョンにしておくことを推奨します。
- Firebird で <filename>gds32.dll</filename> に相当するものは <filename>fbclient.dll</filename> です。
- </para>
- <para>
- デフォルトでは、すべての識別子 (テーブル名やフィールド) は大文字で返されます。
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|