Zend_Db_Table_Rowクラスの小さなハック

最新の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 .






今では動作します!



All Articles