Zend_Db_Tableの使いやすさ

この驚くべきクラスをフル活用する人はほとんどいません。 この瞬間まで私がしたように、その隠れた可能性のいくつかについて推測した人はほとんどいませんでした。



ご存知のように、リレーショナルデータベースのテーブルは、1対多および多対多の関係によってリンクされています。 おそらく誰かがさらにいくつかのリンクを提供するでしょうが、この記事はこれについて議論するためではなく、必要な方向にアイデアを提案し、指示するためのものです。 Zend Frameworkの実装では、1対多の関係を検討します。



ご存知のように、Zend_Db_Tableクラスは、データベーステーブルへのオブジェクト指向インターフェイスです。 最初の有用な発見は、Zend_Db_Tableが接続レコードのカスケード削除とカスケード更新が可能であることでした。そのため、参照値を削除/更新するときに、依存テーブルのレコードが削除/更新されます。 たとえば、MyISAMデータストレージエンジンでMySQLデータベースを使用しますが、これは宣言的な参照整合性をサポートしていません。



ちょっとした余談です。 たとえば、製品、ユニット、グループのテーブルで構成される小さなデータベースが必要です。 食品(製品)、測定単位(単位)、および製品グループ(グループ)について説明します。



以下は、テーブルを作成および設定するためのSQLクエリです。

 #製品単位表
 「ユニット」が存在する場合のドロップテーブル;
 CREATE TABLE `ユニット`(
   `unit_id` INT(10)UNSIGNED NOT NULL AUTO_INCREMENT、
   `unit_name` VARCHAR(256)NOT NULL DEFAULT ''、
  主キー( `unit_id`)
 )エンジン= MYISAM AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

 INSERT INTO `units` SET` unit_name` = 'gram';
 INSERT INTO `units` SET` unit_name` = 'milliliter';

 #製品グループ表
 `groups`が存在する場合はドロップテーブル。
 CREATE TABLE `groups`(
   `group_id` INT(10)UNSIGNED NOT NULL AUTO_INCREMENT、
   `group_name` VARCHAR(256)NOT NULL DEFAULT ''、
  主キー( `group_id`)
 )エンジン= MYISAM AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

 INSERT INTO `groups` SET` group_name` = 'Vegetables';
 INSERT INTO `groups` SET` group_name` = 'Fruit';
 INSERT INTO `groups` SET` group_name` = 'Dairy';
 INSERT INTO `groups` SET` group_name` = 'Meat';

 #製品表
 `products`が存在する場合はドロップテーブル;
 CREATE TABLE `products`(
   `product_id` INT(10)UNSIGNED NOT NULL AUTO_INCREMENT、
   `group_id` INT(10)DEFAULT NULL、
   `unit_id` INT(10)DEFAULT NULL、
   `product_name` VARCHAR(256)NOT NULL DEFAULT ''、
  主キー( `product_id`)
 )エンジン= MYISAM DEFAULT CHARSET = utf8;

 #野菜
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(1、1、 'Potato');
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(1、1、 'Tomato');
 #フルーツ
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(2、1、 'Apricot');
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(2、1、 'Apple');
 #デイリー
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(3、1、 'Brynza');
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(3、2、 'Milk');
 #肉
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(4、1、 'Veal');
 INSERT INTO `products`(` group_id`、 `unit_id`、` product_name`)VALUES(4、1、 'Pork');


テーブルが作成され、テストデータが入力されたので、テーブルのクラスを作成します。



クラスProductsはZend_Db_Table_Abstractを拡張します
 {
    保護された$ _name = 'products';
     protected $ _primary = array( 'product_id');
 }
        
クラスUnitsはZend_Db_Table_Abstractを拡張します
 {
     protected $ _name = 'units';
     protected $ _primary = array( 'unit_id');
 }
 
クラスGroupsはZend_Db_Table_Abstractを拡張します
 {
    保護された$ _name = 'groups';
     protected $ _primary = array( 'group_id');
 }


簡単にするために、これらのクラスをコントローラーに配置しますが、実際のプロジェクトではこれを強くお勧めします。 製品表のデータは次のように取得できます。



 $ productsTable =新しい製品;
 $ productsRowset = $ productsTable-> fetchAll();
 foreach($ productsRowset as $ row){
    エコー '<pre>'。  print_r($ row-> toArray()、true)。  「</ pre>」。  PHP_EOL;
 }


ご覧のとおり、fetchAllメソッドは行セットを返します。各行はテーブルの行に対応しています。 次のコードをforeachに追加すると、特定のレコードを変更できます。



 if($ row-> product_name == 'Pork'){
     $ row-> product_name = 'Pork BBQ';
     $ row-> save();
 }


foreachは、Zend_Db_Table_Row_Abstractから継承されたZend_Db_Table_Rowsetクラスのインスタンスである行セットを個別の$行に解析するため、$ row行に対して、抽象クラスZend_Db_Table_Row_Abstractからsaveメソッドを適用します。 $行自体は、Zend_Db_Table_Rowクラスのインスタンスにすぎません。 Zend_Db_Table_Rowクラスのインスタンスを使用した操作には、深い知識は必要ありません。したがって、それらについては詳しく説明しませんが、次のことについて説明します。



グループテーブルの主キーの順序が気に入らず、たとえば100から始めて、問題ではなく、これを実装するためにいくつのアクションを実行する必要があるとしますか? 頭が回転し始めます。 製品テーブルを見て、group_idキーによってグループテーブルへの外部接続を提供しました。 そして、変更後、製品はグループに適合しなければなりません。 おそらく、これは見たい例ではなく、スタンディングオベーションのふりをしていませんが、Zend FrameworkのZend_Db_Tableクラス間の相互作用のメカニズムがどのように実装されているかを示すことができます。

それでは始めましょう。 親テーブルのオブジェクトモデルでは、依存テーブルを指定する必要があります。 Groupsクラスでは、次のプロパティを追加して、依存クラスProductsを指定する必要があります



 protected $ _dependentTables = array( 'Products');


また、Unitsクラスで行う必要があります。 これらは、親が変更されたときに依存テーブルのレコードが考慮されることを示しています。 ただし、このためには、ProductsクラスのUnitsおよびGroupsテーブルにリンクを追加する必要があります。 これを実装する方法はいくつかあります。たとえば、$ _referenceMapプロパティをProductsクラスに追加します。



 protected $ _referenceMap = array(
     'refUnits' =>配列(
         self :: COLUMNS => 'unit_id'、
         self :: REF_TABLE_CLASS => 'Units'、
         self :: REF_COLUMNS => 'unit_id'、
         self :: ON_DELETE => self :: CASCADE、
         self :: ON_UPDATE => self :: CASCADE
     )、
     'refGroups' =>配列(
         self :: COLUMNS => 'group_id'、
         self :: REF_TABLE_CLASS => 'グループ'、
         self :: REF_COLUMNS => 'group_id'、
         self :: ON_DELETE => self :: CASCADE、
         self :: ON_UPDATE => self :: CASCADE
     )
 );


$ _referenceMapプロパティを使用すると、外部テーブルへのリンクを追加できるため、多対1の関係が得られます。 次のパラメータを決定する必要があります



1.連想キー

2.参照テーブルの外部キーフィールドの名前

3.参照するテーブルのクラス名

4.参照するテーブル内のフィールドの名前

5.削除すると発生するアクション

6.更新時に発生するアクション



全体としてのコード:

クラスProductsはZend_Db_Table_Abstractを拡張します
 {
    保護された$ _name = 'products';
     protected $ _primary = array( 'product_id');

     protected $ _referenceMap = array(
         'refUnits' =>配列(
             self :: COLUMNS => 'unit_id'、
             self :: REF_TABLE_CLASS => 'Units'、
             self :: REF_COLUMNS => 'unit_id'、
             self :: ON_DELETE => self :: CASCADE、
             self :: ON_UPDATE => self :: CASCADE
         )、
         'refGroups' =>配列(
             self :: COLUMNS => 'group_id'、
             self :: REF_TABLE_CLASS => 'グループ'、
             self :: REF_COLUMNS => 'group_id'、
             self :: ON_DELETE => self :: CASCADE、
             self :: ON_UPDATE => self :: CASCADE
         )
     );
 }

クラスUnitsはZend_Db_Table_Abstractを拡張します
 {
     protected $ _name = 'units';
     protected $ _primary = array( 'unit_id');

     protected $ _dependentTables = array( 'Products');
 }

クラスGroupsはZend_Db_Table_Abstractを拡張します
 {
    保護された$ _name = 'groups';
     protected $ _primary = array( 'group_id');

     protected $ _dependentTables = array( 'Products');
 }


これで関連テーブルができたので、IDキーを心配せずに落ち着いて更新できます。

ところで、製品グループを削除すると、これらのグループに対応する製品自体も削除されることを忘れていました。 どれでも試して削除できます。 興味がある場合は、抽象クラスZend_Db_Table_Abstractの_cascadeUpdateメソッドと_cascadeDeleteメソッドが更新と削除を行い、それぞれ$ row-> save()と$ row-> delete()が呼び出されたときに呼び出されます。 findParentRowメソッドを呼び出して、親レコード(行)を取得することもできます



 $ productsTable =新しい製品;
 $ productsRowset = $ productsTable-> fetchAll();
 foreach($ productsRowset as $ row){
     echo '-----------------------'。  PHP_EOL;
    エコー '<pre>'。  print_r($ row-> toArray()、true)。  「</ pre>」。  PHP_EOL;
    エコー '<pre>'。  print_r($ row-> findParentRow( 'Units')-> toArray()、true)。  「</ pre>」。  PHP_EOL;
    エコー '<pre>'。  print_r($ row-> findParentRow( 'Groups')-> toArray()、true)。  「</ pre>」。  PHP_EOL;
     echo '-----------------------'。  PHP_EOL;
 }


findDependentRowsetメソッドを呼び出して、すべての依存レコード(行)を取得します



 $ groupsRowset = $ groupsTable-> fetchAll();
 foreach($ groupsRowset as $ row){
     echo '-----------------------'。  PHP_EOL;
    エコー '<pre>'。  print_r($ row-> toArray()、true)。  「</ pre>」。  PHP_EOL;
    エコー '<pre>'。  print_r($ row-> findDependentRowset( 'Products')-> toArray()、true)。  「</ pre>」。  PHP_EOL;
     echo '-----------------------'。  PHP_EOL;
 }


受信した行を使用して、Zend_Db_Table_Rowクラスのインスタンスと同様に自由に作業することもできます。 頑張って



psこんにちはJos、あなたのすべての願いが考慮されました。



All Articles