| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table">
- <title>Zend_Db_Table</title>
- <sect2 id="zend.db.table.introduction">
- <title>Introduction</title>
- <para>
- The <classname>Zend_Db_Table</classname> class is an object-oriented interface to
- database tables. It provides methods for many common operations on tables. The base
- class is extensible, so you can add custom logic.
- </para>
- <para>
- The <classname>Zend_Db_Table</classname> solution is an implementation of the
- <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
- Gateway</ulink> pattern. The solution also includes a class that implements the
- <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
- Gateway</ulink> pattern.
- </para>
- </sect2>
- <sect2 id="zend.db.table.concrete">
- <title>Using Zend_Db_Table as a concrete class</title>
- <para>
- As of Zend Framework 1.9, you can instantiate <classname>Zend_Db_Table</classname>. This
- added benefit is that you do not have to extend a base class and configure it to do
- simple operations such as selecting, inserting, updating and deleteing on a single
- table. below is an example of the simplest of use cases.
- </para>
- <example id="zend.db.table.defining.concrete-instantiation.example1">
- <title>Declaring a table class with just the string name</title>
- <programlisting language="php"><![CDATA[
- Zend_Db_Table::setDefaultAdapter($dbAdapter);
- $bugTable = new Zend_Db_Table('bug');
- ]]></programlisting>
- </example>
- <para>
- The above example represents the simplest of use cases. Make not of all the
- options describe below for configuring <classname>Zend_Db_Table</classname> tables. If
- you want to be able to use the concrete usage case, in addition to the more complex
- relationhip features, see the <classname>Zend_Db_Table_Definition</classname>
- documentation.
- </para>
- </sect2>
- <sect2 id="zend.db.table.defining">
- <title>Defining a Table Class</title>
- <para>
- For each table in your database that you want to access, define a class that extends
- <classname>Zend_Db_Table_Abstract</classname>.
- </para>
- <sect3 id="zend.db.table.defining.table-schema">
- <title>Defining the Table Name and Schema</title>
- <para>
- Declare the database table for which this class is defined, using the protected
- variable <varname>$_name</varname>. This is a string, and must contain the name of
- the table spelled as it appears in the database.
- </para>
- <example id="zend.db.table.defining.table-schema.example1">
- <title>Declaring a table class with explicit table name</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- }
- ]]></programlisting>
- </example>
- <para>
- If you don't specify the table name, it defaults to the name of the class. If you
- rely on this default, the class name must match the spelling of the table name as
- it appears in the database.
- </para>
- <example id="zend.db.table.defining.table-schema.example">
- <title>Declaring a table class with implicit table name</title>
- <programlisting language="php"><![CDATA[
- class bugs extends Zend_Db_Table_Abstract
- {
- // table name matches class name
- }
- ]]></programlisting>
- </example>
- <para>
- You can also declare the schema for the table, either with the protected variable
- <varname>$_schema</varname>, or with the schema prepended to the table name in the
- <varname>$_name</varname> property. Any schema specified with the
- <varname>$_name</varname> property takes precedence over a schema specified with the
- <varname>$_schema</varname> property. In some <acronym>RDBMS</acronym> brands, the
- term for schema is "database" or "tablespace," but it is used similarly.
- </para>
- <example id="zend.db.table.defining.table-schema.example3">
- <title>Declaring a table class with schema</title>
- <programlisting language="php"><![CDATA[
- // First alternative:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_schema = 'bug_db';
- protected $_name = 'bugs';
- }
- // Second alternative:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- }
- // If schemas are specified in both $_name and $_schema, the one
- // specified in $_name takes precedence:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- protected $_schema = 'ignored';
- }
- ]]></programlisting>
- </example>
- <para>
- The schema and table names may also be specified via constructor configuration
- directives, which override any default values specified with the
- <varname>$_name</varname> and <varname>$_schema</varname> properties. A schema
- specification given with the <code>name</code> directive overrides any value
- provided with the <code>schema</code> option.
- </para>
- <example id="zend.db.table.defining.table-schema.example.constructor">
- <title>Declaring table and schema names upon instantiation</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- }
- // First alternative:
- $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
- // Second alternative:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
- // If schemas are specified in both 'name' and 'schema', the one
- // specified in 'name' takes precedence:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
- 'schema' => 'ignored'));
- ]]></programlisting>
- </example>
- <para>
- If you don't specify the schema name, it defaults to the schema to which your
- database adapter instance is connected.
- </para>
- </sect3>
- <sect3 id="zend.db.table.defining.primary-key">
- <title>Defining the Table Primary Key</title>
- <para>
- Every table must have a primary key. You can declare the column for the primary key
- using the protected variable <varname>$_primary</varname>. This is either a string
- that names the single column for the primary key, or else it is an array of column
- names if your primary key is a compound key.
- </para>
- <example id="zend.db.table.defining.primary-key.example">
- <title>Example of specifying the primary key</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_primary = 'bug_id';
- }
- ]]></programlisting>
- </example>
- <para>
- If you don't specify the primary key, <classname>Zend_Db_Table_Abstract</classname>
- tries to discover the primary key based on the information provided by the
- <methodname>describeTable()</methodname>´ method.
- </para>
- <note>
- <para>
- Every table class must know which column(s) can be used to address rows
- uniquely. If no primary key column(s) are specified in the table class
- definition or the table constructor arguments, or discovered in the table
- metadata provided by <methodname>describeTable()</methodname>, then the table
- cannot be used with <classname>Zend_Db_Table</classname>.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.defining.setup">
- <title>Overriding Table Setup Methods</title>
- <para>
- When you create an instance of a Table class, the constructor calls a set of
- protected methods that initialize metadata for the table. You can extend any of
- these methods to define metadata explicitly. Remember to call the method of the
- same name in the parent class at the end of your method.
- </para>
- <example id="zend.db.table.defining.setup.example">
- <title>Example of overriding the _setupTableName() method</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- $this->_name = 'bugs';
- parent::_setupTableName();
- }
- }
- ]]></programlisting>
- </example>
- <para>
- The setup methods you can override are the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>_setupDatabaseAdapter()</methodname> checks that an adapter has
- been provided; gets a default adapter from the registry if needed. By
- overriding this method, you can set a database adapter from some other
- source.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>_setupTableName()</methodname> defaults the table name to the
- name of the class. By overriding this method, you can set the table name
- before this default behavior runs.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>_setupMetadata()</methodname> sets the schema if the table name
- contains the pattern "schema.table"; calls
- <methodname>describeTable()</methodname> to get metadata information;
- defaults the <varname>$_cols</varname> array to the columns reported by
- <methodname>describeTable()</methodname>. By overriding this method, you can
- specify the columns.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>_setupPrimaryKey()</methodname> defaults the primary key columns
- to those reported by <methodname>describeTable()</methodname>; checks that
- the primary key columns are included in the <varname>$_cols</varname> array.
- By overriding this method, you can specify the primary key columns.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.table.initialization">
- <title>Table initialization</title>
- <para>
- If application-specific logic needs to be initialized when a Table class is
- constructed, you can select to move your tasks to the
- <methodname>init()</methodname> method, which is called after all Table metadata has
- been processed. This is recommended over the <code>__construct</code> method if you
- do not need to alter the metadata in any programmatic way.
- </para>
- <example id="zend.db.table.defining.init.usage.example">
- <title>Example usage of init() method</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- public function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.constructing">
- <title>Creating an Instance of a Table</title>
- <para>
- Before you use a Table class, create an instance using its constructor. The
- constructor's argument is an array of options. The most important option to a Table
- constructor is the database adapter instance, representing a live connection to an
- <acronym>RDBMS</acronym>. There are three ways of specifying the database adapter to a
- Table class, and these three ways are described below:
- </para>
- <sect3 id="zend.db.table.constructing.adapter">
- <title>Specifying a Database Adapter</title>
- <para>
- The first way to provide a database adapter to a Table class is by passing it as an
- object of type <classname>Zend_Db_Adapter_Abstract</classname> in the options array,
- identified by the key <code>'db'</code>.
- </para>
- <example id="zend.db.table.constructing.adapter.example">
- <title>Example of constructing a Table using an Adapter object</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- $table = new Bugs(array('db' => $db));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.constructing.default-adapter">
- <title>Setting a Default Database Adapter</title>
- <para>
- The second way to provide a database adapter to a Table class is by declaring an
- object of type <classname>Zend_Db_Adapter_Abstract</classname> to be a default
- database adapter for all subsequent instances of Tables in your application. You can
- do this with the static method
- <methodname>Zend_Db_Table_Abstract::setDefaultAdapter()</methodname>. The argument
- is an object of type <classname>Zend_Db_Adapter_Abstract</classname>.
- </para>
- <example id="zend.db.table.constructing.default-adapter.example">
- <title>Example of constructing a Table using a the Default Adapter</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Db_Table_Abstract::setDefaultAdapter($db);
- // Later...
- $table = new Bugs();
- ]]></programlisting>
- </example>
- <para>
- It can be convenient to create the database adapter object in a central place of
- your application, such as the bootstrap, and then store it as the default adapter.
- This gives you a means to ensure that the adapter instance is the same throughout
- your application. However, setting a default adapter is limited to a single adapter
- instance.
- </para>
- </sect3>
- <sect3 id="zend.db.table.constructing.registry">
- <title>Storing a Database Adapter in the Registry</title>
- <para>
- The third way to provide a database adapter to a Table class is by passing a string
- in the options array, also identified by the <code>'db'</code> key. The string is
- used as a key to the static <classname>Zend_Registry</classname> instance, where the
- entry at that key is an object of type
- <classname>Zend_Db_Adapter_Abstract</classname>.
- </para>
- <example id="zend.db.table.constructing.registry.example">
- <title>Example of constructing a Table using a Registry key</title>
- <programlisting language="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Registry::set('my_db', $db);
- // Later...
- $table = new Bugs(array('db' => 'my_db'));
- ]]></programlisting>
- </example>
- <para>
- Like setting the default adapter, this gives you the means to ensure that the same
- adapter instance is used throughout your application. Using the registry is more
- flexible, because you can store more than one adapter instance. A given adapter
- instance is specific to a certain <acronym>RDBMS</acronym> brand and database
- instance. If your application needs access to multiple databases or even multiple
- database brands, then you need to use multiple adapters.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.insert">
- <title>Inserting Rows to a Table</title>
- <para>
- You can use the Table object to insert rows into the database table on which the Table
- object is based. Use the <methodname>insert()</methodname> method of your Table object.
- The argument is an associative array, mapping column names to values.
- </para>
- <example id="zend.db.table.insert.example">
- <title>Example of inserting to a Table</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- $table->insert($data);
- ]]></programlisting>
- </example>
- <para>
- By default, the values in your data array are inserted as literal values, using
- parameters. If you need them to be treated as <acronym>SQL</acronym> expressions, you
- must make sure they are distinct from plain strings. Use an object of type
- <classname>Zend_Db_Expr</classname> to do this.
- </para>
- <example id="zend.db.table.insert.example-expr">
- <title>Example of inserting expressions to a Table</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Something wrong',
- 'bug_status' => 'NEW'
- );
- ]]></programlisting>
- </example>
- <para>
- In the examples of inserting rows above, it is assumed that the table has an
- auto-incrementing primary key. This is the default behavior of
- <classname>Zend_Db_Table_Abstract</classname>, but there are other types of primary keys
- as well. The following sections describe how to support different types of primary keys.
- </para>
- <sect3 id="zend.db.table.insert.key-auto">
- <title>Using a Table with an Auto-incrementing Key</title>
- <para>
- An auto-incrementing primary key generates a unique integer value for you if you
- omit the primary key column from your <acronym>SQL</acronym>
- <constant>INSERT</constant> statement.
- </para>
- <para>
- In <classname>Zend_Db_Table_Abstract</classname>, if you define the protected
- variable <varname>$_sequence</varname> to be the Boolean value
- <constant>TRUE</constant>, then the class assumes that the table has an
- auto-incrementing primary key.
- </para>
- <example id="zend.db.table.insert.key-auto.example">
- <title>Example of declaring a Table with auto-incrementing primary key</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- // This is the default in the Zend_Db_Table_Abstract class;
- // you do not need to define this.
- protected $_sequence = true;
- }
- ]]></programlisting>
- </example>
- <para>
- MySQL, Microsoft <acronym>SQL</acronym> Server, and SQLite are examples of
- <acronym>RDBMS</acronym> brands that support auto-incrementing primary keys.
- </para>
- <para>
- PostgreSQL has a <constant>SERIAL</constant> notation that implicitly defines a
- sequence based on the table and column name, and uses the sequence to generate key
- values for new rows. IBM DB2 has an <constant>IDENTITY</constant> notation that
- works similarly. If you use either of these notations, treat your
- <classname>Zend_Db_Table</classname> class as having an auto-incrementing column
- with respect to declaring the <varname>$_sequence</varname> member as
- <constant>TRUE</constant>.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-sequence">
- <title>Using a Table with a Sequence</title>
- <para>
- A sequence is a database object that generates a unique value, which can be used
- as a primary key value in one or more tables of the database.
- </para>
- <para>
- If you define <varname>$_sequence</varname> to be a string, then
- <classname>Zend_Db_Table_Abstract</classname> assumes the string to name a sequence
- object in the database. The sequence is invoked to generate a new value, and this
- value is used in the <constant>INSERT</constant> operation.
- </para>
- <example id="zend.db.table.insert.key-sequence.example">
- <title>Example of declaring a Table with a sequence</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]></programlisting>
- </example>
- <para>
- Oracle, PostgreSQL, and IBM DB2 are examples of <acronym>RDBMS</acronym> brands that
- support sequence objects in the database.
- </para>
- <para>
- PostgreSQL and IBM DB2 also have syntax that defines sequences implicitly and
- associated with columns. If you use this notation, treat the table as having an
- auto-incrementing key column. Define the sequence name as a string only in cases
- where you would invoke the sequence explicitly to get the next key value.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-natural">
- <title>Using a Table with a Natural Key</title>
- <para>
- Some tables have a natural key. This means that the key is not automatically
- generated by the table or by a sequence. You must specify the value for the primary
- key in this case.
- </para>
- <para>
- If you define the <varname>$_sequence</varname> to be the Boolean value
- <constant>FALSE</constant>, then <classname>Zend_Db_Table_Abstract</classname>
- assumes that the table has a natural primary key. You must provide values for the
- primary key columns in the array of data to the <methodname>insert()</methodname>
- method, or else this method throws a <classname>Zend_Db_Table_Exception</classname>.
- </para>
- <example id="zend.db.table.insert.key-natural.example">
- <title>Example of declaring a Table with a natural key</title>
- <programlisting language="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]></programlisting>
- </example>
- <note>
- <para>
- All <acronym>RDBMS</acronym> brands support tables with natural keys. Examples
- of tables that are often declared as having natural keys are lookup tables,
- intersection tables in many-to-many relationships, or most tables with compound
- primary keys.
- </para>
- </note>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.update">
- <title>Updating Rows in a Table</title>
- <para>
- You can update rows in a database table using the <code>update</code> method of a Table
- class. This method takes two arguments: an associative array of columns to change and
- new values to assign to these columns; and an <acronym>SQL</acronym> expression that is
- used in a <constant>WHERE</constant> clause, as criteria for the rows to change in the
- <constant>UPDATE</constant> operation.
- </para>
- <example id="zend.db.table.update.example">
- <title>Example of updating rows in a Table</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
- $table->update($data, $where);
- ]]></programlisting>
- </example>
- <para>
- Since the table <methodname>update()</methodname> method proxies to the database adapter
- <link linkend="zend.db.adapter.write.update"><methodname>update()</methodname></link>
- method, the second argument can be an array of <acronym>SQL</acronym> expressions. The
- expressions are combined as Boolean terms using an <constant>AND</constant> operator.
- </para>
- <note>
- <para>
- The values and identifiers in the <acronym>SQL</acronym> expression are not quoted
- for you. If you have values or identifiers that require quoting, you are responsible
- for doing this. Use the <methodname>quote()</methodname>,
- <methodname>quoteInto()</methodname>, and <methodname>quoteIdentifier()</methodname>
- methods of the database adapter.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.delete">
- <title>Deleting Rows from a Table</title>
- <para>
- You can delete rows from a database table using the <methodname>delete()</methodname>
- method. This method takes one argument, which is an <acronym>SQL</acronym> expression
- that is used in a <constant>WHERE</constant> clause, as criteria for the rows to delete.
- </para>
- <example id="zend.db.table.delete.example">
- <title>Example of deleting rows from a Table</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]></programlisting>
- </example>
- <para>
- Since the table <methodname>delete()</methodname> method proxies to the database adapter
- <link linkend="zend.db.adapter.write.delete"><methodname>delete()</methodname></link>
- method, the argument can also be an array of <acronym>SQL</acronym> expressions. The
- expressions are combined as Boolean terms using an <constant>AND</constant> operator.
- </para>
- <note>
- <para>
- The values and identifiers in the <acronym>SQL</acronym> expression are not quoted
- for you. If you have values or identifiers that require quoting, you are responsible
- for doing this. Use the <methodname>quote()</methodname>,
- <methodname>quoteInto()</methodname>, and <methodname>quoteIdentifier()</methodname>
- methods of the database adapter.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.find">
- <title>Finding Rows by Primary Key</title>
- <para>
- You can query the database table for rows matching specific values in the primary key,
- using the <methodname>find()</methodname> method. The first argument of this method is
- either a single value or an array of values to match against the primary key of the
- table.
- </para>
- <example id="zend.db.table.find.example">
- <title>Example of finding rows by primary key values</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- // Find a single row
- // Returns a Rowset
- $rows = $table->find(1234);
- // Find multiple rows
- // Also returns a Rowset
- $rows = $table->find(array(1234, 5678));
- ]]></programlisting>
- </example>
- <para>
- If you specify a single value, the method returns at most one row, because a primary
- key cannot have duplicate values and there is at most one row in the database table
- matching the value you specify. If you specify multiple values in an array, the method
- returns at most as many rows as the number of distinct values you specify.
- </para>
- <para>
- The <methodname>find()</methodname> method might return fewer rows than the number of
- values you specify for the primary key, if some of the values don't match any rows in
- the database table. The method even may return zero rows. Because the number of rows
- returned is variable, the <methodname>find()</methodname> method returns an object of
- type <classname>Zend_Db_Table_Rowset_Abstract</classname>.
- </para>
- <para>
- If the primary key is a compound key, that is, it consists of multiple columns, you can
- specify the additional columns as additional arguments to the
- <methodname>find()</methodname> method. You must provide as many arguments as the number
- of columns in the table's primary key.
- </para>
- <para>
- To find multiple rows from a table with a compound primary key, provide an array for
- each of the arguments. All of these arrays must have the same number of elements. The
- values in each array are formed into tuples in order; for example, the first element
- in all the array arguments define the first compound primary key value, then the second
- elements of all the arrays define the second compound primary key value, and so on.
- </para>
- <example id="zend.db.table.find.example-compound">
- <title>Example of finding rows by compound primary key values</title>
- <para>
- The call to <methodname>find()</methodname> below to match multiple rows can match
- two rows in the database. The first row must have primary key value (1234, 'ABC'),
- and the second row must have primary key value (5678, 'DEF').
- </para>
- <programlisting language="php"><![CDATA[
- class BugsProducts extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs_products';
- protected $_primary = array('bug_id', 'product_id');
- }
- $table = new BugsProducts();
- // Find a single row with a compound primary key
- // Returns a Rowset
- $rows = $table->find(1234, 'ABC');
- // Find multiple rows with compound primary keys
- // Also returns a Rowset
- $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.fetch-all">
- <title>Querying for a Set of Rows</title>
- <sect3 id="zend.db.table.fetch-all.select">
- <title>Select API</title>
- <para>
- <warning>
- <para>
- The <acronym>API</acronym> for fetch operations has been superseded to allow
- a <classname>Zend_Db_Table_Select</classname> object to modify the query.
- However, the deprecated usage of the <methodname>fetchRow()</methodname> and
- <methodname>fetchAll()</methodname> methods will continue to work without
- modification.
- </para>
- <para>
- The following statements are all legal and functionally identical, however
- it is recommended to update your code to take advantage of the new usage
- where possible.
- </para>
- <para>
- <programlisting language="php"><![CDATA[
- /**
- * Fetching a rowset
- */
- $rows = $table->fetchAll(
- 'bug_status = "NEW"',
- 'bug_id ASC',
- 10,
- 0
- );
- $rows = $table->fetchAll(
- $table->select()
- ->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- ->limit(10, 0)
- );
- // or with binding
- $rows = $table->fetchAll(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':status'=>'NEW')
- ->order('bug_id ASC')
- ->limit(10, 0)
- );
- /**
- * Fetching a single row
- */
- $row = $table->fetchRow(
- 'bug_status = "NEW"',
- 'bug_id ASC'
- );
- $row = $table->fetchRow(
- $table->select()
- ->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- );
- // or with binding
- $row = $table->fetchRow(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':status'=>'NEW')
- ->order('bug_id ASC')
- );
- ]]></programlisting>
- </para>
- </warning>
- </para>
- <para>
- The <classname>Zend_Db_Table_Select</classname> object is an extension of the
- <classname>Zend_Db_Select</classname> object that applies specific restrictions to
- a query. The enhancements and restrictions are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- You <emphasis>can</emphasis> elect to return a subset of columns within a
- fetchRow or fetchAll query. This can provide optimization benefits where
- returning a large set of results for all columns is not desirable.
- </para>
- </listitem>
- <listitem>
- <para>
- You <emphasis>can</emphasis> specify columns that evaluate expressions from
- within the selected table. However this will mean that the returned row or
- rowset will be <property>readOnly</property> and cannot be used for save()
- operations. A <classname>Zend_Db_Table_Row</classname> with
- <property>readOnly</property> status will throw an exception if a
- <methodname>save()</methodname> operation is attempted.
- </para>
- </listitem>
- <listitem>
- <para>
- You <emphasis>can</emphasis> allow JOIN clauses on a select to allow
- multi-table lookups.
- </para>
- </listitem>
- <listitem>
- <para>
- You <emphasis>can not</emphasis> specify columns from a JOINed tabled to be
- returned in a row/rowset. Doing so will trigger a <acronym>PHP</acronym>
- error. This was done to ensure the integrity of the
- <classname>Zend_Db_Table</classname> is retained. i.e. A
- <classname>Zend_Db_Table_Row</classname> should only reference columns
- derived from its parent table.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- <example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Simple usage</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- Fluent interfaces are implemented across the component, so this can be rewritten
- this in a more abbreviated form.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Example of fluent interface</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $rows =
- $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.fetch-all.usage">
- <title>Fetching a rowset</title>
- <para>
- You can query for a set of rows using any criteria other than the primary key
- values, using the <methodname>fetchAll()</methodname> method of the Table class.
- This method returns an object of type
- <classname>Zend_Db_Table_Rowset_Abstract</classname>.
- </para>
- <example id="zend.db.table.qry.rows.set.finding.row.example">
- <title>Example of finding rows by an expression</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- You may also pass sorting criteria in an <code>ORDER BY</code> clause, as well as
- count and offset integer values, used to make the query return a specific subset of
- rows. These values are used in a <constant>LIMIT</constant> clause, or in equivalent
- logic for <acronym>RDBMS</acronym> brands that do not support the
- <constant>LIMIT</constant> syntax.
- </para>
- <example id="zend.db.table.fetch-all.example2">
- <title>Example of finding rows by an expression</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $order = 'bug_id';
- // Return the 21st through 30th rows
- $count = 10;
- $offset = 20;
- $select = $table->select()->where('bug_status = ?', 'NEW')
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- All of the arguments above are optional. If you omit the ORDER clause, the result
- set includes rows from the table in an unpredictable order. If no LIMIT clause is
- set, you retrieve every row in the table that matches the WHERE clause.
- </para>
- </sect3>
- <sect3 id="zend.db.table.advanced.usage">
- <title>Advanced usage</title>
- <para>
- For more specific and optimized requests, you may wish to limit the number of
- columns returned in a row/rowset. This can be achieved by passing a FROM clause to
- the select object. The first argument in the FROM clause is identical to that of a
- <classname>Zend_Db_Select</classname> object with the addition of being able to pass
- an instance of <classname>Zend_Db_Table_Abstract</classname> and have it
- automatically determine the table name.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Retrieving specific columns</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table, array('bug_id', 'bug_description'))
- ->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- <important>
- <para>
- The rowset contains rows that are still 'valid' - they simply contain a
- subset of the columns of a table. If a save() method is called on a partial
- row then only the fields available will be modified.
- </para>
- </important>
- You can also specify expressions within a FROM clause and have these returned as a
- readOnly row/rowset. In this example we will return a rows from the bugs table that
- show an aggregate of the number of new bugs reported by individuals. Note the GROUP
- clause. The 'count' column will be made available to the row for evaluation and can
- be accessed as if it were part of the schema.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Retrieving expressions as columns</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table,
- array('COUNT(reported_by) as `count`', 'reported_by'))
- ->where('bug_status = ?', 'NEW')
- ->group('reported_by');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- You can also use a lookup as part of your query to further refine your fetch
- operations. In this example the accounts table is queried as part of a search for
- all new bugs reported by 'Bob'.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.refine.example">
- <title>Using a lookup table to refine the results of fetchAll()</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- // retrieve with from part set, important when joining
- $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
- $select->setIntegrityCheck(false)
- ->where('bug_status = ?', 'NEW')
- ->join('accounts', 'accounts.account_name = bugs.reported_by')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- The <classname>Zend_Db_Table_Select</classname> is primarily used to constrain and
- validate so that it may enforce the criteria for a legal SELECT query. However
- there may be certain cases where you require the flexibility of the
- <classname>Zend_Db_Table_Row</classname> component and do not require a writable or
- deletable row. for this specific user case, it is possible to retrieve a row/rowset
- by passing a <constant>FALSE</constant> value to setIntegrityCheck. The resulting
- row/rowset will be returned as a 'locked' row (meaning the save(), delete() and any
- field-setting methods will throw an exception).
- </para>
- <example id="zend.db.table.qry.rows.set.integrity.example">
- <title>
- Removing the integrity check on Zend_Db_Table_Select to allow JOINed rows
- </title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
- ->setIntegrityCheck(false);
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts',
- 'accounts.account_name = bugs.reported_by',
- 'account_name')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.fetch-row">
- <title>Querying for a Single Row</title>
- <para>
- You can query for a single row using criteria similar to that of the
- <methodname>fetchAll()</methodname> method.
- </para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Example of finding a single row by an expression</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id');
- $row = $table->fetchRow($select);
- ]]></programlisting>
- </example>
- <para>
- This method returns an object of type <classname>Zend_Db_Table_Row_Abstract</classname>.
- If the search criteria you specified match no rows in the database table, then
- <methodname>fetchRow()</methodname> returns <acronym>PHP</acronym>'s
- <constant>NULL</constant> value.
- </para>
- </sect2>
- <sect2 id="zend.db.table.info">
- <title>Retrieving Table Metadata Information</title>
- <para>
- The <classname>Zend_Db_Table_Abstract</classname> class provides some information about
- its metadata. The <methodname>info()</methodname> method returns an array structure with
- information about the table, its columns and primary key, and other metadata.
- </para>
- <example id="zend.db.table.info.example">
- <title>Example of getting the table name</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $info = $table->info();
- echo "The table name is " . $info['name'] . "\n";
- ]]></programlisting>
- </example>
- <para>
- The keys of the array returned by the <methodname>info()</methodname> method are
- described below:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>name</emphasis> => the name of the table.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>cols</emphasis> => an array, naming the column(s) of
- the table.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>primary</emphasis> => an array, naming the column(s) in
- the primary key.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>metadata</emphasis> => an associative array, mapping
- column names to information about the columns. This is the information returned
- by the <methodname>describeTable()</methodname> method.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>rowClass</emphasis> => the name of the concrete class
- used for Row objects returned by methods of this table instance. This defaults
- to <classname>Zend_Db_Table_Row</classname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>rowsetClass</emphasis> => the name of the concrete
- class used for Rowset objects returned by methods of this table instance. This
- defaults to <classname>Zend_Db_Table_Rowset</classname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>referenceMap</emphasis> => an associative array, with
- information about references from this table to any parent tables. See
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dependentTables</emphasis> => an array of class names
- of tables that reference this table. See
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>schema</emphasis> => the name of the schema (or
- database or tablespace) for this table.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.db.table.metadata.caching">
- <title>Caching Table Metadata</title>
- <para>
- By default, <classname>Zend_Db_Table_Abstract</classname> queries the
- underlying database for <link linkend="zend.db.table.info">table
- metadata</link> whenever that data is needed to perform table
- operations. The table object fetches the table metadata from the
- database using the adapter's <methodname>describeTable()</methodname> method.
- Operations requiring this introspection include:
- </para>
- <itemizedlist>
- <listitem><para><methodname>insert()</methodname></para></listitem>
- <listitem><para><methodname>find()</methodname></para></listitem>
- <listitem><para><methodname>info()</methodname></para></listitem>
- </itemizedlist>
- <para>
- In some circumstances, particularly when many table objects are instantiated against
- the same database table, querying the database for the table metadata for each instance
- may be undesirable from a performance standpoint. In such cases, users may benefit by
- caching the table metadata retrieved from the database.
- </para>
- <para>
- There are two primary ways in which a user may take advantage of table metadata
- caching:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Call
- <methodname>Zend_Db_Table_Abstract::setDefaultMetadataCache()</methodname></emphasis>
- - This allows a developer to once set the default cache object to be used
- for all table classes.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Configure
- <methodname>Zend_Db_Table_Abstract::__construct()</methodname></emphasis> -
- This allows a developer to set the cache object to be used for a particular
- table class instance.
- </para>
- </listitem>
- </itemizedlist>
- In both cases, the cache specification must be either <constant>NULL</constant> (i.e.,
- no cache used) or an instance of
- <link linkend="zend.cache.frontends.core"><classname>Zend_Cache_Core</classname></link>.
- The methods may be used in conjunction when it is desirable to have both a default
- metadata cache and the ability to change the cache for individual table objects.
- </para>
- <example id="zend.db.table.metadata.caching-default">
- <title>Using a Default Metadata Cache for all Table Objects</title>
- <para>
- The following code demonstrates how to set a default metadata cache to be used for
- all table objects:
- </para>
- <programlisting language="php"><![CDATA[
- // First, set up the Cache
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Next, set the cache to be used with all table objects
- Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
- // A table class is also needed
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Each instance of Bugs now uses the default metadata cache
- $bugs = new Bugs();
- ]]></programlisting>
- </example>
- <example id="zend.db.table.metadata.caching-instance">
- <title>Using a Metadata Cache for a Specific Table Object</title>
- <para>
- The following code demonstrates how to set a metadata cache for a specific table
- object instance:
- </para>
- <programlisting language="php"><![CDATA[
- // First, set up the Cache
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // A table class is also needed
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Configure an instance upon instantiation
- $bugs = new Bugs(array('metadataCache' => $cache));
- ]]></programlisting>
- </example>
- <note>
- <title>Automatic Serialization with the Cache Frontend</title>
- <para>
- Since the information returned from the adapter's describeTable() method is an
- array, ensure that the <code>automatic_serialization</code> option is set to
- <constant>TRUE</constant> for the <classname>Zend_Cache_Core</classname> frontend.
- </para>
- </note>
- <para>
- Though the above examples use <classname>Zend_Cache_Backend_File</classname>, developers
- may use whatever cache backend is appropriate for the situation. Please see
- <link linkend="zend.cache">Zend_Cache</link> for more information.
- </para>
- <sect3 id="zend.db.table.metadata.caching.hardcoding">
- <title>Hardcoding Table Metadata</title>
- <para>
- To take metadata caching a step further, you can also choose to
- hardcode metadata. In this particular case, however, any changes
- to the table schema will require a change in your code. As such,
- it is only recommended for those who are optimizing for
- production usage.
- </para>
- <para>
- The metadata structure is as follows:
- </para>
- <programlisting language="php"><![CDATA[
- protected $_metadata = array(
- '<column_name>' => array(
- 'SCHEMA_NAME' => <string>,
- 'TABLE_NAME' => <string>,
- 'COLUMN_NAME' => <string>,
- 'COLUMN_POSITION' => <int>,
- 'DATA_TYPE' => <string>,
- 'DEFAULT' => NULL|<value>,
- 'NULLABLE' => <bool>,
- 'LENGTH' => <string - length>,
- 'SCALE' => NULL|<value>,
- 'PRECISION' => NULL|<value>,
- 'UNSIGNED' => NULL|<bool>,
- 'PRIMARY' => <bool>,
- 'PRIMARY_POSITION' => <int>,
- 'IDENTITY' => <bool>,
- ),
- // additional columns...
- );
- ]]></programlisting>
- <para>
- An easy way to get the appropriate values is to use the metadata
- cache, and then to deserialize values stored in the cache.
- </para>
- <para>
- You can disable this optimization by turning of the
- <code>metadataCacheInClass</code> flag:
- </para>
- <programlisting language="php"><![CDATA[
- // At instantiation:
- $bugs = new Bugs(array('metadataCacheInClass' => false));
- // Or later:
- $bugs->setMetadataCacheInClass(false);
- ]]></programlisting>
- <para>
- The flag is enabled by default, which ensures that the
- <varname>$_metadata</varname> array is only populated once per
- instance.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.extending">
- <title>Customizing and Extending a Table Class</title>
- <sect3 id="zend.db.table.extending.row-rowset">
- <title>Using Custom Row or Rowset Classes</title>
- <para>
- By default, methods of the Table class return a Rowset in instances of the concrete
- class <classname>Zend_Db_Table_Rowset</classname>, and Rowsets contain a collection
- of instances of the concrete class <classname>Zend_Db_Table_Row</classname> You can
- specify an alternative class to use for either of these, but they must be classes
- that extend <classname>Zend_Db_Table_Rowset_Abstract</classname> and
- <classname>Zend_Db_Table_Row_Abstract</classname>, respectively.
- </para>
- <para>
- You can specify Row and Rowset classes using the Table constructor's options array,
- in keys <code>'rowClass'</code> and <code>'rowsetClass'</code> respectively.
- Specify the names of the classes using strings.
- </para>
- <example id="zend.db.table.extending.row-rowset.example">
- <title>Example of specifying the Row and Rowset classes</title>
- <programlisting language="php"><![CDATA[
- class My_Row extends Zend_Db_Table_Row_Abstract
- {
- ...
- }
- class My_Rowset extends Zend_Db_Table_Rowset_Abstract
- {
- ...
- }
- $table = new Bugs(
- array(
- 'rowClass' => 'My_Row',
- 'rowsetClass' => 'My_Rowset'
- )
- );
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Returns an object of type My_Rowset,
- // containing an array of objects of type My_Row.
- $rows = $table->fetchAll($where);
- ]]></programlisting>
- </example>
- <para>
- You can change the classes by specifying them with the
- <methodname>setRowClass()</methodname> and <methodname>setRowsetClass()</methodname>
- methods. This applies to rows and rowsets created subsequently; it does not change
- the class of any row or rowset objects you have created previously.
- </para>
- <example id="zend.db.table.extending.row-rowset.example2">
- <title>Example of changing the Row and Rowset classes</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Returns an object of type Zend_Db_Table_Rowset
- // containing an array of objects of type Zend_Db_Table_Row.
- $rowsStandard = $table->fetchAll($where);
- $table->setRowClass('My_Row');
- $table->setRowsetClass('My_Rowset');
- // Returns an object of type My_Rowset,
- // containing an array of objects of type My_Row.
- $rowsCustom = $table->fetchAll($where);
- // The $rowsStandard object still exists, and it is unchanged.
- ]]></programlisting>
- </example>
- <para>
- For more information on the Row and Rowset classes, see
- <xref linkend="zend.db.table.row" /> and <xref linkend="zend.db.table.rowset" />.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.insert-update">
- <title>Defining Custom Logic for Insert, Update, and Delete</title>
- <para>
- You can override the <methodname>insert()</methodname> and
- <methodname>update()</methodname> methods in your Table class. This gives you the
- opportunity to implement custom code that is executed before performing the database
- operation. Be sure to call the parent class method when you are done.
- </para>
- <example id="zend.db.table.extending.insert-update.example">
- <title>Custom logic to manage timestamps</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function insert(array $data)
- {
- // add a timestamp
- if (empty($data['created_on'])) {
- $data['created_on'] = time();
- }
- return parent::insert($data);
- }
- public function update(array $data, $where)
- {
- // add a timestamp
- if (empty($data['updated_on'])) {
- $data['updated_on'] = time();
- }
- return parent::update($data, $where);
- }
- }
- ]]></programlisting>
- </example>
- <para>
- You can also override the <methodname>delete()</methodname> method.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.finders">
- <title>Define Custom Search Methods in Zend_Db_Table</title>
- <para>
- You can implement custom query methods in your Table class, if you have frequent
- need to do queries against this table with specific criteria. Most queries can be
- written using <methodname>fetchAll()</methodname>, but this requires that you
- duplicate code to form the query conditions if you need to run the query in several
- places in your application. Therefore it can be convenient to implement a method in
- the Table class to perform frequently-used queries against this table.
- </para>
- <example id="zend.db.table.extending.finders.example">
- <title>Custom method to find bugs by status</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function findByStatus($status)
- {
- $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
- return $this->fetchAll($where, 'bug_id');
- }
- }
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.extending.inflection">
- <title>Define Inflection in Zend_Db_Table</title>
- <para>
- Some people prefer that the table class name match a table name in the
- <acronym>RDBMS</acronym> by using a string transformation called
- <emphasis>inflection</emphasis>.
- </para>
- <para>
- For example, if your table class name is "<code>BugsProducts</code>", it would
- match the physical table in the database called "<code>bugs_products</code>," if
- you omit the explicit declaration of the <varname>$_name</varname> class property.
- In this inflection mapping, the class name spelled in "CamelCase" format would be
- transformed to lower case, and words are separated with an underscore.
- </para>
- <para>
- You can specify the database table name independently from the class name by
- declaring the table name with the <varname>$_name</varname> class property in each
- of your table classes.
- </para>
- <para>
- <classname>Zend_Db_Table_Abstract</classname> performs no inflection to map the
- class name to the table name. If you omit the declaration of
- <varname>$_name</varname> in your table class, the class maps to a database table
- that matches the spelling of the class name exactly.
- </para>
- <para>
- It is inappropriate to transform identifiers from the database, because this can
- lead to ambiguity or make some identifiers inaccessible. Using the
- <acronym>SQL</acronym> identifiers exactly as they appear in the database makes
- <classname>Zend_Db_Table_Abstract</classname> both simpler and more flexible.
- </para>
- <para>
- If you prefer to use inflection, then you must implement the transformation
- yourself, by overriding the <methodname>_setupTableName()</methodname> method in
- your Table classes. One way to do this is to define an abstract class that extends
- <classname>Zend_Db_Table_Abstract</classname>, and then the rest of your tables
- extend your new abstract class.
- </para>
- <example id="zend.db.table.extending.inflection.example">
- <title>Example of an abstract table class that implements inflection</title>
- <programlisting language="php"><![CDATA[
- abstract class MyAbstractTable extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- if (!$this->_name) {
- $this->_name = myCustomInflector(get_class($this));
- }
- parent::_setupTableName();
- }
- }
- class BugsProducts extends MyAbstractTable
- {
- }
- ]]></programlisting>
- </example>
- <para>
- You are responsible for writing the functions to perform inflection transformation.
- Zend Framework does not provide such a function.
- </para>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|