ラベル Zend_Db_Table の投稿を表示しています。 すべての投稿を表示
ラベル Zend_Db_Table の投稿を表示しています。 すべての投稿を表示

2010年2月15日月曜日

BootstrapでのZend_Db_Tableにプロファイラの登録方法

Zend_Application_Resource_Dbを利用して、プロファイラを設定することはできなさそうなので、Bootstrapで設定する方法を、なんとなくメモ

Bootstrapから、'db'リソースを取得して、プロファイラを設定するだけ。

コード例)

function _initDbProfile(){
  $this->bootstrap('db');
  $db=$this->getResource('db');
  $profiler=new Zend_Db_Profiler_Firebug("All Querys");
  $profiler->setEnabled(true);
  $db->setProfiler($profiler);
}

ついでにメタデータをキャッシュする方法も追加すると以下のようになる。


コード例)メタデータをキャッシュする場合
function _initDbProfile(){
  $this->bootstrap('db');
  $db=$this->getResource('db');
  $profiler=new Zend_Db_Profiler_Firebug("All Querys");
  $profiler->setEnabled(true);
  $db->setProfiler($profiler);
  // フロントのオプション設定
  $frontendOptions = array(
    'automatic_serialization' => true
  );
  //バックエンドのオプション(ファイルへ吐き出すので、
  //キャッシュファイルを配置するディレクトリを指定
  $backendOptions  = array(
    'cache_dir'                => APPLICATION_PATH . '/data/cache'
  );
  //キャッシュオブジェクトを作成。キャッシュはファイルへ
  $cache = Zend_Cache::factory(
    'Core',
    'File',
    $frontendOptions,
    $backendOptions
  );
  // テーブルオブジェクトで使用するように設定します
  Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
}

Zend Framework1.10からはZend_Application_Resource_Cachemanagerが利用できるので、もう少し記述が簡単になるのと、定義を外部に出せるのでメンテナンスはしやすくなるはず。
Zend_Application_Resource_Cachemanagerはおいおい調査

2010年2月4日木曜日

Zend_Db_Table(その6) 追加、更新、削除、トランザクション

テーブルへのデータ追加、更新、削除とトランザクションについて、とりあえずメモ

(1)データ追加
データの追加は、行を新しく作ってから、保存するやりかたと、直接データを追加する2つの方法がある。

a)空行を作ってから保存
テーブルクラスのcreateRowメソッドを使って、新しく行オブジェクトを作成して、データを設定し、Rowオブジェクトのsave()メソッドを使って保存をする。

コード例)
$table=new Hoge();
$row=$table->createRow();         
$row->name="sample";
$newid=$row->save();


b)直接データ追加
テーブルクラスのinsert()メソッドを使って、データを直接テーブルに追加する。

コード例)
$table=new Hoge();
$newid=.$table->insert(
  array("name"=>"sample")
);


createRow()メソッドで行オブジェクトを作った場合、値を設定した以外の項目はnullが入るため、テーブル定義でデフォルト値を設定するようにしていても意味がなくなる。
SQL発行をProfilerで見ると、createRow()=>save()で追加を行った場合、新しく割り当てられた主キーの値を取得するためにselect文を実行しているので、insert()を使うよりもSQLが1つ多く発行されていることになる。

createRow()メソッドを使う方法の方が、更新とほぼ同じ手順データ操作が行えるので、いい感じだけど、insert()を使ったほうが、デフォルト値などの設定の手間を考えると、問題が少ないかも。



(2)データ更新
データの更新は、更新行を入手してから、値を変更し、テーブルへ更新する方法と、直接条件を指定してデータを更新する2つの方法がある。

a)対象行を入手してから更新
テーブルクラスから、find(),fetchRow(),fetchAll()などのメソッドを使って、更新対象となる行オブジェクト(Zend_Db_Table_Row)を取得し、項目の値を変更したとRowオブジェクトのsave()メソッドを 使って保存をする。

コード例)
$table=new Hoge();

$row=$table->fetchRow($table->select()->where("id=?",1);         
$row->name="sample";
$row->save();

b)条件を指定して直接データ更新
テーブルクラスのupdate()メソッド を使用し、更新データと検索条件を指定し、テーブルのデータを更新する。

コード例)
$table=new Hoge();

$count=.$table->update(
  array("name"=>"sample"),
  $table->getAdapter()->quoteInto("id=?",1)
);
update()の2つ目の引数には、SQLの条件を記入する。
単に文字列を渡すことになるため、クォート処理などは行ってくれない。
このため、テーブルアダプタのquoteInto()やquoute()メソッドなどを利用して、クォート処理をしておくこと。

updateは条件の指定次第で複数行にを一度に更新ができる。全レコード対象とする場合は、update()の2番目の引数にnullを設定する。

update()は更新内容、条件が同じ場合に利用し、Rowオブジェクトのsave()メソッドを利用する場合は、更新内容や、レコードの特定項目の条件あわせて変更するような場合に利用する。

(3)データ削除
データの削除は、更新の場合と同様に、対象行を入手してから、削除する方法と、直接条件を指定して削除する2つの方法がある。

a)対象行を入手してから削除
テーブルクラスから、find(),fetchRow(),fetchAll()などのメソッドを使って、更新対象となる行オブジェクト (Zend_Db_Table_Row)を取得し、項目の値を変更したとRowオブジェクトのdelete()メソッドを 使って削除する。

コード例)
$table=new Hoge();

$row=$table->fetchRow($table->select()->where("id=?",1);
$row->delete();

b)条件を指定してデータ削除
テーブルクラスのdelete()メソッド を使用し、検索条件を指定してデータを削除する。

コード例)
$table=new Hoge();

$count=.$table->delete(
  $table->getAdapter()->quoteInto("id=?",1)
);

delete()の2つ目の引数には、SQLの条件を記入する。
クォート処理などは行わないのは更新の場合と同様

(4)トランザクション
 通常Zend_Db_Tableなどへの更新操作は、自動的に操作単位でコミットされる。
複数の操作に対して、トランザクション制御を行いたい場合は、アダプタークラスのbeginTransaction()、commit()、rollback()メソッドを利用する。

コード例)
$table=new Hoge();
$table->getAdapter()->beginTransaction();
try{
   //テーブルへの操作など
   $table->getAdapter()->commit();
}catch (Exception $e){
  $table->getAdapter()->rollback();
}

2010年2月3日水曜日

Zend_Db_Table(その5) 検索その2

find()メソッドでは、主キーのみにしか条件に設定できないため、他の条件を指定する場合は、fetchAll()メソッドやfetchRow()メソッドで、Zend_Db_Table_Selectクラスを指定する。

Zend_Db_Table_Selectクラスは、テーブルクラスのselect()メソッドを使うと取得できる。

(コード例)
$table=new Hoge();

$select=$table->select();

Zend_Db_Table_Selectクラスに対して、条件を設定する。
SQLで記述するところを
 from() : テーブル名や取得する項目を指定する。
 where():検索条件をANDで指定する。
 orwhere() :検索条件をORで指定する。
 order() :ソート順を指定する
 limit():取得件数を制限する


(コード例)
$table=new Hoge();
$select=$table->select();
//テーブルからidとnameを取得対象とする
%select->from($table->name(),array("id","name");
//id項目に制限を追加
$select->where("id>?", 100);
//name項目に制限を追加(OR)
$select->orwhere("name like ?","%hoge%");
//sort順をidの降順に設定
$select->order("id DESC");
//取得するレコードを11番目から100行取得
$select->limit(100,10);
//検索実行
$rows=$table->fetchAll($select);

Zend_Db_Table_Selectへの条件を指定する順番は意識しなくてもいい。
where()などの戻り値はZend_Db_Table_Selectオブジェクトになるので、以下のような記述もできる。

(コード例)
$table=new Hoge();
$table->fetchAll($select=$table->select()->where("id>?",100)->orwhere("name like"."%hoge%")->limit(100,10)->order("id DESC"));

※2行目は区切りなしで記述している。


他のテーブルとの結合(join)もできる。

(コード例)
$table=new Hoge();
$select=$table->select()->from()->setIntegrityCheck(false)->join("テーブル名","テーブル名.id=hoge.id",array())->where("id>?",100);

leftjoin()メソッドやrightjoin()メソッドを使うと、外部結合の指定も可能。
他のテーブルを結合する場合、取得する項目に他のテーブルの項目を混ぜることができ、joinメソッドの3つ目の引数で指定する。
その場合、setIntegrityCheck(false)としておかないと、例外がスローされる。

他のテーブルの項目を混在して取得したZend_Db_Table_Rowに対してはupdateメソッドを使った更新を行うことができずに例外がスローされる。

2010年2月1日月曜日

Zend_Db_Table利用時のメタデータのキャッシュ設定

Zend_Db_Tableでは、実行するたびにテーブルのメタ情報を作成している。
テーブルメタデータをキャッシュすることで、パフォーマンスをあげることができる。
やり方はマニュアルに書いてあるけど、なんとなくメモ。
 
キャッシュはZend_Cacheを利用。

ファイルへメタデータをキャッシュする場合は、以下のように設定する。

// (1)キャッシュを作成
$cache = Zend_Cache::factory('Core', 'File',
    array('automatic_serialization' => true),
    array('cache_dir' => APPLICATION_PATH . '/data/cache')
);
//(2) すべてのテーブルオブジェクトで上記のキャッシュ設定Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);


メタデータをテーブルクラスに直接記述してさらにパフォーマンスをあげることができるそうです。
テストまでは、キャッシュを使って、運用時は直接メタデータを書いたほうがいいかのな。

2010年1月29日金曜日

Zend_Db_Table(その4) 検索その1

テーブルからデータ取得をするために3つのメソッドが用意されている

find() :主キーを利用して検索
fetchRow() :条件を指定して一行だけ検索
fetchAll() :条件を指定して複数行検索

fetchRow()以外はZend_Db_Table_Rowsetで取得できる。
fetchRow()は条件にマッチしたら、Zend_Db_Table_Row、マッチなかったらnullが取得できる。

--------コード例--------
$table=new Hoge();
//主キーを利用した検索
$rows=$table->find($key);
//条件を指定して検索(一行だけ)
$row=$table->fetchRow($table->select()->where("col=?",$value);
//条件を指定して検索(複数行)
$rows=$table->fetchAll($table->select()->where("col=?",$value);
-------ここまで-------


foreach文で、Zend_Db_Table_Rowを取得できる。
--------コード例--------
$table=new Hoge();
$rows=$table->fetchAll($table->select()->where("col=?",$value);
foreach($rows as $row){
 $row->name;
$row->id;
}
-------ここまで-------
Zend_Db_Table_Rowsetでは、count()メソッドで件数を取得できる。



配列で取得したいなら、toArray()メソッドを使えば、列を連想配列に変換したものの配列を取得できる

--------コード例--------
$table=new Hoge();
$rows=$table->fetchAll($table->select()->where("col=?",$value);

$data_array=$rows->toArray();
foreach($data_array as $key=>$value){
echo "キー=".$key."\n";
echo "値=".$value."\n";
}
-------ここまで-------

current()メソッドを使うと最初の行だけ取得できる。
find()を利用する場合はRowsetが必ずで返るので、以下のようにして、Rowを取得する。
Rowsetが0件の場合、current()の戻り値はnullになる。
--------コード例--------
$table=new Hoge();
$rows=$table->find($key);
$data=$rows->current();
-------ここまで-------

2010年1月27日水曜日

Zend_Db_Table(その3) テーブルクラスの定義

Zend_Db_Tableを継承したクラスを定義する。
対象となるテーブルが規約にクラス名と同じであり、主キーがシーケンスのように自動インクリメントすキーを持つテーブルであれば、クラス定義や具象クラスを利用するだけでで使用できる。

--------テーブル例--------
CREATE TABLE HOGE
(
ID SERIAL NOT NULL UNIQUE,
NAME TEXT,
PRIMARY KEY (ID)
) ;
CREATE TABLE HOGECHILD
(

CID SERIAL NOT NULL UNIQUE,
PARENT_ID INTEGER NOT NULL REFERENCES HOGE,
NAME VARCHAR(10) NOT NULL,
PRIMARY KEY (CID)
)
--------ここまで--------

--------コード例--------
class Hoge extends Zend_Db_Table_abstract{
}
$table=new Hoge();
$result=$table->find(1);//主キーによる検索
-------ここまで---------

(クラスを定義しない方法 1.9以上)
--------コード例--------
$table = new Zend_Db_Table('hoge');
-------ここまで---------

(テーブル名をクラス名と分ける場合)
--------コード例--------
class Hoge extends Zend_Db_Table_Abstract{
protected $_name="hoge";
}
-------ここまで---------

(主キーが自動インクリメントするキーの場合)
--------コード例--------
class Hoge extends Zend_Db_Table_Abstract{
protected $_sequence=true;
}
-------ここまで---------

(主キーが自然キーの場合)
--------コード例--------
class Hoge extends Zend_Db_Table_Abstract{
protected $_sequence=false;
}
-------ここまで---------

(プラリマリーキーを指定する場合)
--------コード例--------
class Hoge extends Zend_Db_Table_Abstract{
protected $_primary="id";
protected $_sequence=true;
}
-------ここまで---------


テーブル間の関係(リレーション)をクラスに定義しておくと、Zend_Db_Rowクラスから、親テーブルや子テーブルへのアクセスが簡単に利用できる。
テーブルに親、子供テーブルが存在する場合は、親、子に対する関係を記述する。

(従属するテーブルが存在する場合)
--------コード例--------
class Hoge extends Zend_Db_Table_Abstract{
protected $_sequence=true;
//テーブル名ではなく、Zend_Db_Tableを継承したクラス名を記述する
protected $_dependentTables=array(
'HogeChild'
);
}
-------ここまで---------

(親テーブルが存在する場合)
--------コード例--------
class HogeChild extends Zend_Db_Table_Abstract{
protected $_sequence=true;
//refTableClassの要素はテーブル名ではなく、Zend_Db_Tableを継承したクラス名を記述する
protected $_referenceMap=array(
'Rule1'=>array(
'columns'=>'parent_id',
'refTableClass'=>'Hoge',
'refColumns'=>'id'
)
);}
-------ここまで---------

2010年1月24日日曜日

Zend_Db_Table(その2) 接続準備編

Zend_Db_Tableに接続先となるDBの情報を指定する必要がある。
※指定するのはZend_Db_Adapterクラス、でZend_Db::Factory()で生成すればいい。


Zend_Db_Tableの継承クラスに指定する方法はいくつかあるので、必要に応じて使い分ける。

a)Zend_Db_Tableのコンストラクタで接続先情報を指定する
b)Zend_Db_Table::_setupDatabaseAdapter()をオーバーライドして、接続先情報を設定する。
c)Zend_Db_Table_Abstract::setDefaultAdapter($db)ですべてZend_Db_Table継承クラスに対して、接続先を指定する。
※a),b)の指定が優先される。
b)は接続先が他のテーブルと異なる、かつ、接続先の設定変更しないような場合に使う。

通常のアプリケーションでは、テーブルがひとつということはほとんどないので、c)の方法でBootstrapで記述しておけばいい。
------コード例-------
$db=Zend_Db::factory('Pdo_Pgsql', array(
 host=>'localhost',//接続先ホスト
 username=>'dbuser',//DBユーザ名
 password=>'dbpass',//DBパスワード
 dbname=>'DB NAME'//DB名
));
Zend_Db_Table_Abstract::setDefaultAdapter($db)
------ここまで-------

Zend_Db::factory()メソッドで指定する場合、配列で直接指定するほかにZend_Configを利用して外部iniファイルに設定を記述することもできる。

Zend_Applicationを利用する場合は、リソースプラグイン(Zend_Application_Resource_Db)を利用できるので、以下のように記述しておけば、勝手にデフォルトアダプターとして設定してくれるので便利

-------application.iniでの記述例---------
resources.db.adapter = pdo_pgsql
resources.db.params.host = localhost
resources.db.params.username = dbuser
resources.db.params.password = dbpassword
resources.db.params.dbname = dbname
resources.db.isDefaultTableAdapter = true
-------ここまで----------

Zend_Db_Table(その1)

Zend Frameworkに用意されているO/Rマッパー。

DBで定義しているテーブルに対して1対1で対応するZend_Db_Tableを継承するクラスを定義する。

hogehogeテーブル<=>hogehogeクラス

(コード例)
$hote=new Hoge_Table();

//主キーによる検索
$hoge->find("値");
//追加
$hoge->insert(array("列名1"=>"値","列名2"=>"値"));
//更新
$hoge->update(
 array("列名1"=>"値","列名2"=>"値"),
 $hoge->select()->where("列名=?"="値")
);
//削除
$hoge->delete($hoge->select()->where("列名=?"="値"));


主キーによる検索などは、Zend_Db_Tableに用意されているメソッドを使い、アプリケーションに必要処理だけコーディングすることで、シンプルなコードにできる。

Zen_Db_Tableの抽象化対象となるテーブルは、主キーとして、自動生成できるシーケンスを前提といる。
このため、DB設計をする際に、そのあたりを考慮しておくとコーディングが楽になる。
#そうでないテーブルも主キーに関する定義をすることで、当然対象にできる。

テーブル間のリレーションをクラス定義する際に、指定することで、検索結果などで取得できるZend_Db_Table_Rowクラスから関連するテーブルの情報を簡単に取得することもできる。