Tables have relationships to each other in a relational database. An entity in one table can be linked to one or more entities in another table by using referential integrity constraints defined in the database schema.
The Zend_Db_Table_Row class has methods for querying related rows in other tables.
在關系型數據庫中,表與表之間也會存在關聯關系。一個表中的實體可以關聯另一個表中的一個或者多個實體。可以使用Zend_Db_Table_Row提供的方法進行查詢操作。
dependent table :與父表相關的表被稱為從屬表
RowSets : 記錄集,行結果集
Row Object : Row對象,行對象
rule key : 規則鍵 (或者不做翻譯)
rule: 規則 (或者不做翻譯)
Define classes for each of your tables, extending the abstract classZend_Db_Table_Abstract, as described inthis chapter. Also seethis chapter for a description of the example database for which the following example code is designed.
Below are the PHP class definitions for these tables:
可以通過繼承抽象類Zend_Db_Table_Abstract為每一個表建立一個對應的類。下面是本節用到的相關表以及對應的PHP類
class Accounts extends Zend_Db_Table_Abstract{ protected $_name = 'accounts'; protected $_dependentTables = array('Bugs');} class Products extends Zend_Db_Table_Abstract{ protected $_name = 'products'; protected $_dependentTables = array('BugsProducts');} class Bugs extends Zend_Db_Table_Abstract{ protected $_name = 'bugs'; protected $_dependentTables = array('BugsProducts'); protected $_referenceMap = array( 'Reporter' => array( 'columns' => 'reported_by', 'refTableClass' => 'Accounts', 'refColumns' => 'account_name' ), 'Engineer' => array( 'columns' => 'assigned_to', 'refTableClass' => 'Accounts', 'refColumns' => 'account_name' ), 'Verifier' => array( 'columns' => array('verified_by'), 'refTableClass' => 'Accounts', 'refColumns' => array('account_name') ) );} class BugsProducts extends Zend_Db_Table_Abstract{ protected $_name = 'bugs_products'; protected $_referenceMap = array( 'Bug' => array( 'columns' => array('bug_id'), 'refTableClass' => 'Bugs', 'refColumns' => array('bug_id') ), 'Product' => array( 'columns' => array('product_id'), 'refTableClass' => 'Products', 'refColumns' => array('product_id') ) ); }
If you use Zend_Db_Table to emulate cascadingUPDATE andDELETE operations, declare the$_dependentTables array in the class for the parent table. List the class name for each dependent table. Use the class name, not the physical name of theSQL table.
如果要通過Zend_Db_Table 進行UPDATE 和DELETE 操作。你需要在類的父類中聲明$_dependentTables數組。列出每個從屬表的對應的類名。使用類名而不是數據表的真實名稱
Note: Skip declaration of $_dependentTables if you use referential integrity constraints in theRDBMS server to implement cascading operations. Seethis chapter for more information.
注意:$_dependentTables聲明的具體方法在后續會有詳細介紹
Declare the $_referenceMap array in the class for each dependent table. This is an associative array of reference "rules". A reference rule identifies which table is the parent table in the relationship, and also lists which columns in the dependent table reference which columns in the parent table.
在類中聲明一個$_referenceMap數組。數組中包含每一個從屬表。這個關聯數組稱之為 引用規則( reference " rules")。一個引用規則描述了和附表的關聯關系以及依賴父表的哪些列。
The rule key is a string used as an index to the $_referenceMap array. This rule key is used to identify each reference relationship. Choose a descriptive name for this rule key. It's best to use a string that can be part of aPHP method name, as you will see later.
$_referenceMap array的索引是可以隨意,但是通常是一個可以標識引用關系的名稱,可以使用一個PHP方法名稱的一部分。具體你會在后面看到。
In the example PHP code above, the rule keys in the Bugs table class are:'Reporter','Engineer','Verifier', and'Product'.
例如:Bugs 中$_referenceMap數組的key的名稱為'Reporter', 'Engineer', 'Verifier', and 'Product'.
The value of each rule entry in the $_referenceMap array is also an associative array. The elements of this rule entry are described below:
columns => A string or an array of strings naming the foreign key column names in the dependent table.
It's common for this to be a single column, but some tables have multi-column keys.
refTableClass => The class name of the parent table. Use the class name, not the physical name of theSQL table.
It's common for a dependent table to have only one reference to its parent table, but some tables have multiple references to the same parent table. In the example database, there is one reference from thebugs table to the products table, but three references from thebugs table to theaccounts table. Put each reference in a separate entry in the$_referenceMap array.
refColumns => A string or an array of strings naming the primary key column names in the parent table.
It's common for this to be a single column, but some tables have multi-column keys. If the reference uses a multi-column key, the order of columns in the'columns' entry must match the order of columns in the'refColumns' entry.
It is optional to specify this element. If you don't specify the refColumns, the columns reported as the primary key columns of the parent table are used by default.
onDelete => The rule for an action to execute if a row is deleted in the parent table. Seethis chapter for more information.
onUpdate => The rule for an action to execute if values in primary key columns are updated in the parent table. Seethis chapter for more information.
$_referenceMap數組的值是一個關聯數組。各個元素的功能描述如下:
columns :是一個字符串或者數組。內容是從屬表的外鍵名稱。通常是指定的一列,但是也可以是表中多個列
refTableClass :父表的類的名稱。使用對應的類名,而不是數據表名。
通常,一個表和父表只有一個引用關系。但是有的表和父表之間會有多個引用關系
示例數據庫中,從bugs 表到products 表的存在一個引用關系,從bugs 表到accounts 表存在三個引用關系。 $_referenceMap 數組需要存放他們之間的所有的引用關系
refColumns :一個字符串或者數組。是在父表的主鍵的列名列表
通常,是表的一列。但是有些表會有多列。如果引用關系使用了多列,這些列的實體必須在'refColumns' 中指定,并且順序一致。
選項是可選的。如果不指定refColumns, 默認為父表的主鍵
onDelete :如果要在父表中執行刪除行的操作。需要設置參數。詳情可以參考后續章節
onUpdate :如果要更新父表的主鍵,需要設置此選項。詳情可以參考后續章節
If you have a Row object as the result of a query on a parent table, you can fetch rows from dependent tables that reference the current row. Use the method:
如果把父表的查詢結果作為行對象。你還可以從當前行引用的從屬表中獲取數據 ,使用如下方法:
$row->findDependentRowset($table, [$rule]);
The first argument $table can be a string that specifies the dependent table by its class name. You can also specify the dependent table by using an object of that table class.
此方法返回一個Zend_Db_Table_Rowset_Abstract 對象。 從 引用被$row 對象表示的行的從屬表$table中獲取行結果集
第一個參數$table可以是一個指定的從屬表的類名字符串。你也可以使用該表類的一個對象作為從屬表。
The second argument $rule is optional. It is a string that names the rule key in the$_referenceMap array of the dependent table class.
If you don't specify a rule, the first rule in the array that references the parent table is used. If you need to use a rule other than the first, you need to specify the key.
In the example code above, the rule key is not specified, so the rule used by default is the first one that matches the parent table. This is the rule'Reporter'.
第二個參數$rule 是可選的。通常采用$_referenceMap數組指定的rule key。 如果不指定rule,會使用父表的第一個rule。如果你不想只用第一個,你需要指定指定的key。
Example #1 Fetching a Dependent Rowset獲取一個行結果集
This example shows getting a Row object from the table Accounts, and finding the Bugs reported by that account.
從Accounts表獲取行對象,然后通過該帳戶報告的Bugs 。
上面的示例代碼,沒有指定索引,默認采用父表第一個匹配的列。這里是‘’Reporter‘’
Example #2 Fetching a Dependent Rowset By a Specific Rule通過指定的rule來獲取依賴行結果集
This example shows getting a Row object from the table Accounts, and finding the Bugs assigned to be fixed by the user of that account. The rule key string that corresponds to this reference relationship in this example is'Engineer'.
此舉例中,是從Accounts表中獲取行對象,然后從Bugs 表中獲取指定帳戶已經修復的bug。 rule key 字符串對應的是這個引用關系的 'Engineer'.
You can also add criteria, ordering and limits to your relationships using the parent row's select object.
你可以添加其它處理條件,進行排序或者限制從父表獲取查詢結果集數目
Example #3 Fetching a Dependent Rowset using a Zend_Db_Table_Select 使用Zend_Db_Table_Select 獲取依賴的行結果集
This example shows getting a Row object from the table Accounts, and finding the Bugs assigned to be fixed by the user of that account, limited only to 3 rows and ordered by name.
此舉例是從Accounts表中獲取行結果集,然后獲取用戶已修復Bugs 。按照名稱排序并且僅僅取3條記錄
Alternatively, you can query rows from a dependent table using a special mechanism called a "magic method".Zend_Db_Table_Row_Abstract invokes the method:
findDependentRowset('<TableClass>', '<Rule>') if you invoke a method on the Row object matching either of the following patterns:
另外,你可以使用Zend_Db_Table_Row_Abstract提供的魔術方法 從從屬表查詢行結果集合。
如果你想使用魔術方法獲取行結果集,可以使用:findDependentRowset('<TableClass>', '<Rule>')
$row->find<TableClass>()
$row->find<TableClass>By<Rule>()
In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the dependent table, and the dependent table's rule key that references the parent table.
Note: Some application frameworks, such as Ruby on Rails, use a mechanism called "inflection" to allow the spelling of identifiers to change depending on usage. For simplicity,Zend_Db_Table_Row does not provide any inflection mechanism. The table identity and the rule key named in the method call must match the spelling of the class and rule key exactly.
在上面的模式中,<TableClass>和<Rule>是從屬表對應的類名字符串和 從屬表的父表引用 rule key
注意:在一些框架中,例如 Ruby on Rails,使用“inflection”機制,標識符的拼寫視情況而定。
為簡單起見,Zend_Db_Table_Row對象不提供任何inflection 機制。表的標識和rule key的名稱在方法調用的名字命名的規則必須拼寫完全匹配。
Example #4 Fetching Dependent Rowsets using the Magic Method使用魔術方法獲取依賴行結果集
This example shows finding dependent Rowsets equivalent to those in the previous examples. In this case, the application uses the magic method invocation instead of specifying the table and rule as strings.
舉例中顯示的 依賴行結果集相當于前一個例子的結果集。 在這種情況下,應用程序會采用 魔術方法調用代替指定 table 名和rule key
If you have a Row object as the result of a query on a dependent table, you can fetch the row in the parent to which the dependent row refers. Use the method:
如果有一個從屬表的查詢結果作為 Row對象,你可以從父表中對應的行獲取相應的行結果集。使用如下方法:
There always should be exactly one row in the parent table referenced by a dependent row, therefore this method returns a Row object, not a Rowset object.
The first argument $table can be a string that specifies the parent table by its class name. You can also specify the parent table by using an object of that table class.
這里具體的行是 在父表中被引用的依賴行, 因此,該方法返回一個 Row 對象, 而不是一個 Rowset 對象.
第一個參數 $table是父表對應的類的類名字符串。也可以使用表對應類的對象作為父表。
Example #5 Fetching the Parent Row
This example shows getting a Row object from the table Bugs (for example one of those bugs with status 'NEW'), and finding the row in the Accounts table for the user who reported the bug.
舉例中說明了從Bugs 表獲取(所有狀態為 'NEW' 的bugs)行對象。然后從Accounts 表中獲取報告bug的用戶
The second argument $rule is optional. It is a string that names the rule key in the$_referenceMap array of the dependent table class. If you don't specify a rule, the first rule in the array that references the parent table is used. If you need to use a rule other than the first, you need to specify the key.
In the example above, the rule key is not specified, so the rule used by default is the first one that matches the parent table. This is the rule'Reporter'.
第二個參數 $rule 是可選的。 rule key是一個名稱字符串,在$_referenceMap是從屬表的類的類名數組。如果你不指定rule。默認會采用父表的第一個相匹配的rule 。如果你不想使用父表中第一個相匹配的key。你需要自己指定。在上面的例子中, 沒有指定rule key, 默認情況下使用的rule 是父表中第一個相匹配的。這里的rule是'Reporter“。
Example #6 Fetching a Parent Row By a Specific Rule
This example shows getting a Row object from the table Bugs, and finding the account for the engineer assigned to fix that bug. The rule key string that corresponds to this reference relationship in this example is'Engineer'.
從Bugs表中獲取行對象。然后從account 表中獲取已修復bug的工程師。 rule key 對應的引用關系是'Engineer'
Alternatively, you can query rows from a parent table using a "magic method".Zend_Db_Table_Row_Abstract invokes the method:
另外,可以采用魔術方法從父表中查詢行。Zend_Db_Table_Row_Abstract 調用如下函數:
findParentRow('<TableClass>', '<Rule>')
if you invoke a method on the Row object matching either of the following patterns:
你還可以采用行對象提供的如下方法:
$row->findParent<TableClass>([Zend_Db_Table_Select $select])
$row->findParent<TableClass>By<Rule>([Zend_Db_Table_Select $select])
In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the parent table, and the dependent table's rule key that references the parent table.
Note: The table identity and the rule key named in the method call must match the spelling of the class and rule key exactly.
在上面的模式中,<TableClass>和<Rule>是對應的父表類名,和父表的的rule key。
注:表標識, rule key 名稱必須和調用的方法的類名和rule key匹配
Example #7 Fetching the Parent Row using the Magic Method
This example shows finding parent Rows equivalent to those in the previous examples. In this case, the application uses the magic method invocation instead of specifying the table and rule as strings.
例子中返回的的父類的行結果 。在這種情況下, 應用程序使用魔術方法調用來代替指定表名和rule
If you have a Row object as the result of a query on one table in a many-to-many relationship (for purposes of the example, call this the "origin" table), you can fetch corresponding rows in the other table (call this the "destination" table) via an intersection table. Use the method:
如果有一個行對象, 在一個多對多的關系的表中可以通過一個行對象查詢 (這里指的是 "origin" 表),你可以通過一個交集表,從其它表(這里指的是 "destination" 表) 獲取相應的行結果。使用下面的方法:
This method returns a Zend_Db_Table_Rowset_Abstract containing rows from the table$table, satisfying the many-to-many relationship. The current Row object$row from the origin table is used to find rows in the intersection table, and that is joined to the destination table.
該方法返回一個 Zend_Db_Table_Rowset_Abstract, 既包含了從$table表中獲取的滿足多對多關系的行結果 。當前行對象 $row 是從原表 和對應關聯的目標表中查找行結果集。
The first argument $table can be a string that specifies the destination table in the many-to-many relationship by its class name. You can also specify the destination table by using an object of that table class.
第一個參數 $table 可以是在多對多關系中指定的目標表對應的類名字符串。你也可以通過使用該表的類的對象指定目標表。
The second argument $intersectionTable can be a string that specifies the intersection table between the two tables in the many-to-many relationship by its class name. You can also specify the intersection table by using an object of that table class.
第二個參數$intersectionTable 指的是在多對多關系中兩個之間的交集表對應的類名字符串。你也可以使用交叉表的對象。
Example #8 Fetching a Rowset with the Many-to-many Method 使用多對多關系提供的方法獲取行結果集合
This example shows getting a Row object from the origin table Bugs, and finding rows from the destination table Products, representing products related to that bug.
該例子說明了從原始表 Bugs 表獲取行結果, 和從目標表Products中, 查找指定產品的相關bug的表中獲取行集合
The third and fourth arguments $rule1 and$rule2 are optional. These are strings that name the rule keys in the$_referenceMap array of the intersection table.
第三和第四個參數$rule1和$rule2是可選的。 在交集表$_referenceMap數組中的rule key 作為名稱
The $rule1 key names the rule for the relationship from the intersection table to the origin table. In this example, this is the relationship from BugsProducts to Bugs.
$rule1 鍵名是對應的是從交集表到原始表對應的關系規則。 例如, 從 BugsProducts 到 Bugs 表中的關系.
The $rule2 key names the rule for the relationship from the intersection table to the destination table. In this example, this is the relationship from Bugs to Products.
$rule2 鍵名 the rule for the relationship 從 交集表到目標表的關系規則. 例如, 從 Bugs 到 Products 表的關系.
Similarly to the methods for finding parent and dependent rows, if you don't specify a rule, the method uses the first rule in the$_referenceMap array that matches the tables in the relationship. If you need to use a rule other than the first, you need to specify the key.
同樣類似的方法查找父類和相關的行結果。如果你不特別指定規則。該方法會使用在匹配的表的$_referenceMap 數組中的關系的第一個規則。如果您想要使用其它的規則,你需要指定具體的key。
In the example code above, the rule key is not specified, so the rules used by default are the first ones that match. In this case,$rule1 is'Reporter' and$rule2 is 'Product'.
在上面的示例代碼中,如果不指定規則。默認會采用第一個匹配的規則。在這種情況下,$rule1是Reporter, $rule2是Product
Example #9 Fetching a Rowset with the Many-to-many Method By a Specific Rule 通過指定的規則獲取行結果集
This example shows geting a Row object from the origin table Bugs, and finding rows from the destination table Products, representing products related to that bug.
該例子是 從原始表 Bugs中獲取行對象 ,和從目標表Products中查找指定產品的相關bug的結果集合
Alternatively, you can query rows from the destination table in a many-to-many relationship using a "magic method."Zend_Db_Table_Row_Abstract invokes the method:findManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>') if you invoke a method matching any of the following patterns:
另外, 你還可以使用魔術方法,從多對多關系中從目標表查詢行結果。即可以調用Zend_Db_Table_Row_Abstract提供的方法indManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>')。
如果要使用此方法,可以按照如下規則使用:
$row->find<TableClass>Via<IntersectionTableClass> ([Zend_Db_Table_Select $select])
$row->find<TableClass>Via<IntersectionTableClass>By<Rule1> ([Zend_Db_Table_Select $select])
$row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2> ([Zend_Db_Table_Select $select])
In the patterns above, <TableClass> and <IntersectionTableClass> are strings that correspond to the class names of the destination table and the intersection table, respectively.<Rule1> and <Rule2> are strings that correspond to the rule keys in the intersection table that reference the origin table and the destination table, respectively.
在上面的規則中, <TableClass> 和 <IntersectionTableClass> 分別是目標表的相應的類名和交集表的類名。 <Rule1> and <Rule2> 相應的規則分別是在交集表 的原始表的引用 和 目標表的引用
Note: The table identities and the rule keys named in the method call must match the spelling of the class and rule key exactly.
注意:在方法中使用的表的標識和 rule keys 的名稱必須在拼寫上嚴格與類名和rule key一致
Example #10 Fetching Rowsets using the Magic Many-to-many Method 采用魔術方法獲取結果集
This example shows finding rows in the destination table of a many-to-many relationship representing products related to a given bug.
該例中從多對多的關系的目標表中查找結果集。即bug對應的的相關產品。
Note: Declare DRI in the database: 在數據庫中聲明DRI:
Declaring cascading operations in Zend_Db_Table is intendedonly for RDBMS brands that do not support declarative referential integrity (DRI).
For example, if you use MySQL's or MariaDB's MyISAM storage engine, or SQLite, these solutions do not supportDRI. You may find it helpful to declare the cascading operations withZend_Db_Table.
If your RDBMS implements DRI and the ON DELETE and ON UPDATE clauses, you should declare these clauses in your database schema, instead of using the cascading feature inZend_Db_Table. Declaring cascading DRI rules in the RDBMS is better for database performance, consistency, and integrity.
Most importantly, do not declare cascading operations both in the RDBMS and in your Zend_Db_Table class.
在 Zend_Db_Table中聲明的級聯操作僅僅用于那些不支持聲明引用完整性 (DRI)的RDBMS。
例如 , MySQL , MariaDB 的 MyISAM 存儲引擎, 或者 SQLite, 這些不支持DRI。你可以 通過Zend_Db_Table 實現聲明級聯操作。
如要要實現 RDBMS 的 DRI 接口 和 ON DELETE 和 ON UPDATE 子句, 你應該在數據庫結構設計中聲明這些子句,而不是使用Zend_Db_Table提供的級聯特性。
在RDBMS 中聲明 級聯 的DRI 規則 會有更高效 ,一致性,完整性,
最重要的是不要同時使用Zend_Db_Table 和 RDBMS 提供的 聲明級聯操作
You can declare cascading operations to execute against a dependent table when you apply an UPDATE or a DELETE to a row in a parent table.
當在父表中進行UPDATE 或者DELETE 時,可以對從屬表聲明級聯操作。
Example #11 Example of a Cascading Delete 級聯刪除
This example shows deleting a row in the Products table, which is configured to automatically delete dependent rows in the Bugs table.
例如 在 Products 表中刪除指定一行時會自動刪除在B