最新のWebアプリケーションの中核は、データベースとの対話です。 アプリケーションを実装するためにZend Frameworkを選択した場合、Zend_Db_Table_Abstractクラスの使用に必ず遭遇します。 このクラスは、データベースの操作に必要なCRUD関数を正常に実装しますが、それでもこの設計には1つの欠点があります。
次のデータベース構造を考慮してください。

このデータベースには、ニュースとニュースの解説という2つのエンティティが含まれています。 明らかに、1つのニュース項目に多くのコメントを残すことができます。
すべてのニュースとコメントを選択し、情報をプレゼンテーションに転送するというタスクを設定します。 Zend_Db_Table_Abstractの観点からアプローチする方法は? 適切なモデル(ニュースとコメント)があるとします。
すべてのニュースを選択するのは非常に簡単です。
$News= new News();
$news=$News->fetchAll();
* This source code was highlighted with Source Code Highlighter .
次に、ロジックに従って、サイクル内のすべてのニュースを巡回し、各ニュースに属するすべてのコメントを選択する必要があります。 これは主な疑問を提起します-コメント付きのオブジェクトの配列をどこに書くべきでしょうか?
私は本当にこれをやりたい:
foreach ($news as $record)
{
$comments=$Comments->fetchAll(“news_id=”.$record->news_id);
$record->comments=$comments;
}
$ this ->view->news=$news;
* This source code was highlighted with Source Code Highlighter .
ただし、
指定された列「comments」が行にないことを示す例外が発生します。 実際には、各変数$レコードはZend_Db_Table_Row_Abstract型のオブジェクトです。 コメントプロパティ(実際にはZend_Db_Table_Rowset_Abstract型のオブジェクト)に配列を割り当てようとして、__set()メソッドを呼び出します。 調べてみましょう。
public function __set($columnName, $ value )
{
$columnName = $ this ->_transformColumn($columnName);
if (!array_key_exists($columnName, $ this ->_data)) {
require_once 'Zend/Db/Table/Row/Exception.php' ;
throw new Zend_Db_Table_Row_Exception( "Specified column \"$columnName\" is not in the row" );
}
$ this ->_data[$columnName] = $ value ;
$ this ->_modifiedFields[$columnName] = true ;
}
* This source code was highlighted with Source Code Highlighter .
このプロパティが$ _data配列に登録されている場合にのみ、割り当てが可能であることが明らかになります。 さて、クエリに関係するテーブルのメタ情報を調べることにより、日付配列に到達します。 明らかに、私たちの場合、コメントフィールドは決してありません。
最後に、問題の解決策を見つけました。 最も恐ろしいことは、Zend_Db_Table_Row_Abstractクラスのコードで問題を直接修正し、そこから$ _data配列の登録チェックを破棄することです。 当然、これは行いません。OOPを優先します。 必要なのは、独自のRowクラスとRowsetクラスを作成することだけです。
新しいRowクラスのコードは次の
とおりです(ファイル
/library/Main/Db/Table/Row.phpに入れて
ください ):
<?php
class Main_Db_Table_Row extends Zend_Db_Table_Row
{
public function newDataProperty($ value )
{
if (!array_key_exists($ value ,$ this ->_data))
$ this ->_data[$ value ]= "" ;
}
}
* This source code was highlighted with Source Code Highlighter .
新しいRowsetクラス(ファイル
/library/Main/Db/Table/Rowset.php )のコードは次の
とおりです。
<?php
class Main_Db_Table_Rowset extends Zend_Db_Table_Rowset
{
function init()
{
$ this ->_rowClass= 'Main_Db_Table_Row' ;
}
}
* This source code was highlighted with Source Code Highlighter .
これだけではありません。モデルにこれらのクラスを使用するように強制します。 ニュースモデルの例:
<?php
class News extends Zend_Db_Table_Abstract
{
protected $_name= 'news' ;
protected $_primary= 'news_id' ;
function init()
{
$ this ->setRowClass( 'Main_Db_Table_Row' );
$ this ->setRowsetClass( 'Main_Db_Table_Rowset' );
}
}
* This source code was highlighted with Source Code Highlighter .
すべてがほぼ準備完了です。 最後に、ニュースオブジェクトにコメントを追加するためのコードを変更します。
foreach ($news as $record)
{
$comments=$Comments->fetchAll(“news_id=”.$record->news_id);
$record->newDataProperty('comments');
$record->comments=$comments;
}
$ this ->view->news=$news;
* This source code was highlighted with Source Code Highlighter .
今では動作します!