2010年2月15日月曜日

Zend_Registryの使い方

Zend_Registryの使い方をとりあえずメモ

グローバルな値を格納するときに利用できるZend_Registryの利用方法をなんとなくメモ

利用は簡単で、Zend_Registry::set("変数名","値");でセットした値をZend_Registry::get("変数名");で取得する。

Zend_Registry::get('変数名');を実行する前に、Zend_Registry::set("変数名","値");を実行しておかないと、Zend_Exceptionがスローされる。

変数に設定しているクラス名からクラスを生成

Zend_Applicationでは、Bootstrapクラスを外部ソースで指定できるので、クラス名の文字列からクラスが生成できるだろうと思って調べてみたのでなんとなくメモ。


Zend_ApplicationのsetBootstrap()を見ていると、以下の記述があった。
コード例)
 $this->_bootstrap = new $class($this);
 どうやら、クラス名を文字列として指定して、生成できるよう。
ただ、
コード例)
 new 'クラス名'():

ではエラーになる。
一度変数に格納しないとだめなようです。


メソッドも同じように変数に一度格納することによって以下のような書き方できる。

コード例)
$class="aaa";
$method="bbb";
//aaaクラスを生成
$aaa=new $class();

//aaaのbbbメソッドを実行
$aaa->$method();

面白い。

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はおいおい調査

PHPでの処理実行時間取得

PHPで処理時間を知りたくなったので、なんとなくメモ

処理前後の時間をmicrotime()で取得して、差分を取得する。
microtime()は戻りが小数部、半角スペース、整数部の文字列になっているので、explodeで分割して、配列に格納してから、floatに変換しておく。

コード例)
$start=explode(' ',microtime());
sleep(5);
$end=explode(' ',microtime());
$diff=((float)$end[0]+(float)$end[1])-((float)$start[0]+(float)$start[1]);

2010年2月13日土曜日

Zend Framework 1.10.1リリース

Zend Framework 1.10.1リリースがリリースされてました。

変更点はよくわかりませんが、バグフィックスが中心かな?

2010年2月9日火曜日

Zend_View_Helperを自作する

Zend_View_Helperを自作する必要があったので、とりあえずメモ。

ヘルパーはZend_View_Helper_InterfaceかZend_View_Helper_Abstractを継承して作成する。

クラス名には、View_Helperを入れておいたほうがよいと、リファレンスに書いてあった。
クラスのメソッドとして、必ずクラス名からプレフィックスを除いた名称と同じ名前のメソッドを用意する必要がある。
※クラス名ははじめが大文字、メソッド名ははじめは小文字で。

コード例) 引数を大文字にするだけの簡単なHelperクラス
class My_View_Helper_StrUpper extends Zend_View_Helper_Abstract {
    public function strUpper($val){
        return strtoupper($val);
    }
}

配置先は、とりあえず、views/helpers配下あたりに置いておく。
 上のクラスの場合は、以下のようになる。
配置例)
views/helpers/StrUpper.php



このままではZend_Viewはヘルパークラスを認識できず、使えないので、独自のヘルパークラスを探してもらうようにZend_Viewに探し先を登録する必要がある。
パスを追加するには、Zend_ViewのaddHelperPath()を使う。
第一引数に、パス名(絶対パス)、第二引数にクラス名のプレフィックスを指定する。
コード例) コントローラ内でパスを通すときの書き方
$this->view->addHelperPath(APPLICATION_PATH.'/views/helpers','My_View_Helper');

※ヘルパーのクラス名をZend_View_Helper_XXXXとしておくと、ヘルパーのパス追加は必要がない。ただ、Zend_xxxとつけられるのはZendだけなので、めんどくさがらずに設定をしておくこと。

上記を行うことで、テンプレートにおいて、独自ヘルパーを利用できるようになる。

 コード例)テンプレート内での記述
<div>
<?php echo $this->strUpper("aa"); ?>
</div>

ViewHelperは以外に便利。

Zend_Layoutの制御

Zend_Layoutの制御の仕方をなんとくなくメモ

  ・Zend_Layoutオブジェクトを取得
        i)どこでも
            $layout = Zend_Layout::getMvcInstance();
        ii)ActionControllerから(その1)
            $layout=$this->_helper->layout;  
        iii)ActionControllerから(その2)
            $layout=$this->_helper->getHelper('layout');

    ・Zend_Layoutを無効にする
        $layout->disableLayout();
    ・Zend_Layoutを変更
        $layout->setLayout('nomal');

    ViewHelperの中には、LayoutやViewを自動的に無効にしてくれるものもある。
    Zend_View_Helper_Jsonなど



Viewにヘルパーを追加するようなときに必要になると思うので、ついでにZend_Viewの取得方法もついでにメモ。

Zend_Viewを使用しないと明示しない限り、自動的にZend_Viewは生成されているので、生成されているインスタンスを取得する方法をなんとなく列挙。

i)コントローラから
 $this->view
ii)どこでも
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);

iii)Bootstrap内で
$this->bootstrap('view');//一度初期化しておいたほうが間違いがない。
$this->getResource('view');    


他にもあるかも知れないけど、まぁこんなもんで。

Zend_View_Helper_Partial/Zend_View_Helper_PartialLoop/Zend_View_Helper_Action

Zend_Viewヘルパーで使えそうなものがあったので、なんとなくメモ。


(1)Zend_View_Helper_Action
他Actionの戻り値を取得することができる。
フォワードやリダイレクトをするようなものは、空の文字列が変える。
ウィジットのようなものもを作るのに便利。
引数として、アクション名、コントローラ名、モジュール名、引数(array)を渡す。

コード例)VIEWの中で、indexコントローラのsample2アクションを呼び出している
<?php echo $this->action("sample2","index",null,array("count"=>100));?>


(2)Zend_View_Helper_Partial
VIEWの中で他のテンプレートをレンダリングすることができる。
名前空間を気にせずにコーディングできるのと、複雑なレイアウトを使いまわしたいようなときに便利。
通常のVIEWファイルがview/scripts/コントローラ名/ディレクトリの配下を前提としているのに対し、

呼び出すテンプレートファイルは、views/scripts直下を探しにいくので、階層を間違えないように指定する必要がある。コントローラの範囲を超えて使いまわすのを想定しているのかも。
一応他のモジュールのVIEW配下のファイルも指定することができる。
拡張子はVIEWと同じもの。

コード例)
a) 元のビュー内の記述
<?php echo $this->partial("hogechild",array("aa"=>1,"bb"=>2)); ?>

b)呼び出されるテンプレート(hogechild.phtml)内の記述
<?php echo $this->aa ."/".$this->bb;?>


(3)Zend_View_Helper_PartialLoop
Partialヘルパーのループ版で、渡した引数の配列分だけ繰り返す。
テンプレート内では、 partialCounter変数で、繰り返している回数を取得することができるので、テーブルの行で、一行おきに背景色を変えるなども比較的に容易に実現できる。


コード例)
a) 元のビュー内の記述
 <?php echo $this->partialLoop("hogechild.phtml",
         array(
             array("a1"=>"1","a2"=>"2"),
             array("a1"=>"1","a2"=>"2")             
        ));?>

b)呼び出されるテンプレート(hogechild.phtml)内の記述 
(<?php echo $this->partialCounter?>)a1.":".$this->a2?>

2010年2月6日土曜日

ErrorController指定とFrontControllerの取得の仕方

 Zend Frameworkでは、ActionControllerでExceptionが発生した場合、Zend_Controller_Plugin_ErrorHandlerが例外をキャッチし、処理をErrorControllerのerrorメソッドに移動する。

モジュール構成にしている場合でも、何もしないと、必ずDefaultモジュールのErrorContorllerに処理が移るので、モジュール別にエラーページを切り分ける必要がある場合は、移動先を変更する必要がある。

やり方がわかったので、とりあえずメモ。

Zend_Controller_Plugin_ErrorHandlerには、以下の3つのメソッドがあるので、エラーが発生する前に移動先を決めることができる。

  • setErrorHandlerModule() //モジュールを変更する
  • setErrorHandlerController() //コントローラを変更する
  • setErrorHandlerAction() //アクションを変更する

設定の仕方は以下のとおり
  1. FrontControllerのオブジェクトを取得
  2. FrontControllerに設定されているZend_Controller_Plugin_ErrorHandlerをgetPlugin()で取得
  3. 取得したErrorHandlerのオブジェクトに対して、移動先を設定。

(コード例)
$front=Zend_Controller_Front::getInstance();
$plugin=$front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
$plugin->setErrorHandlerAction('errorhoge');


モジュール別や特定の条件で分けることが決まっているならば、BootStrap中か、自前でプラグインを用意し、dispatchLoopStartup($request)で、指定しておけばよい。



ついでに、FrontControllerの取得方法がよくわからなかったのでとりあえずメモ

[FrontControllerの取得方法]
(1)どこからでも
$front=Zend_Controller_Front::getInstance();


(2)ActionControllerの中で
(2-1)ActionControllerのgetFrontController()を利用して
$front=$this->getFrontController();

(2-2)Bootstrapのリソース経由で

$bootstrap=$this->getInvokeArg('bootstrap');
$front=$bootstrap->getResource('frontController');
(2-3)Bootstrapnoコンテナ経由で
$bootstrap=$this->getInvokeArg('bootstrap');
$container=$bootstrap->getContainer();
if(isset($container->frontcontroller)){
$front=$container->frontcontroller;
$plugin=$front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
$plugin->setErrorHandlerAction('errorhoge');
}
(3)Bootstarpの処理の中で
$this->bootstrap('FrontController');
$this->getResource('FrontController');


Zend_Controller_Plugin_ErrorHandlerはFrontControllerでdispatchされたときに自動的に設定されるようになっている。
BootStrapはフロントコントローラのdispatch前なので、Bootstrap中の処理ではフロントコントローラーに何もPluginに設定されていない。
この為、BootStrap中にErrorHandlerの設定を変更したい場合は、自分でErrorHandlerのオブジェクトを生成して、設定する必要がある。

(コード例)
$this->bootstrap('FrontController');
$front=$this->getResource('FrontController');
if($front->hasPlugin('Zend_Controller_Plugin_ErrorHandler')){
$plugin =$front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
}else{
$plugin=new Zend_Controller_Plugin_ErrorHandler();
$front->registerPlugin($plugin, 100);
}
$plugin->setErrorHandlerAction('errorhoge');

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月31日日曜日

Zend Framework1.10.0のZend_Toolを試してみた

Zend Framework 1.10.0でZend_Toolを利用してみたので、とりあえずメモ。

事前にzf.shコマンドをパスに通しておく。

Ubuntu9.10の環境で試しているので、とりあえず以下でパスを通して実行
$export $PATH=$PATH:zf.shが存在するパス
$zf.sh

エラーが出ずに動けばOK.

(1)プロジェクトを作成する。

sampleという名のプロジェクトを作成するには、

$zf.sh create project sample

と指定する。
実行が完了すると以下のディレクトリやファイルが生成される。
[生成されるディレクトリやファイル]
sample/
    application/
        Bootstrap.php    <=メソッドなしのクラス
        configs/
            application.ini
        controllers/
            IndexController.php
            ErrorController.php
        layouts/    <=空
        models/    <=空
        views/
            helpers/
            scripts/
                index/
                    index.phtml
                error/
                    error.phtml  
    public/
        index.php
        .htaccess
  
    tests/    <=PhpUnitの関連ファイル
    library/    <=空


Index、Errorの2つのコントローラが実行できるようになっている。
VIEWは以前のバージョンで試していたときは、ショートタグ形式だったけどがPHPの指定に変更になっていた。
普段ショートタグは使用してなくて、書き換えていたので、この変更はうれしい。


とりえず生成したものをブラウザからアクセスできるように設定する。
自動生成したものには、ZendFrameworkのライブラリ一式は、library配下におくことが前提になっている。
このため、Zend Frameworkのファイルをコピーするか、他にすでに配置されているようならば、シンボリックリンクを張っておく。

次に公開領域にプロジェクトのpublicディレクトリのシンボリックリンクを作成する。
#apacheの設定で、公開領域でシンボリックリンクを利用できるように設定しておく
#個人的にはあまり好きじゃないけど、とりあえず、動かすだけなので。

$cd /var/www
$ln -s ~/sample/public sample

ブラウザからアクセスするとzfで自動生成したファイルが表示される。
http://xxxxxx/sample/


Controllerの追加などは、プロジェクトディレクトリ直下でコマンド操作する。
$cd sample


(2)レイアウトを追加
1.10.0からZend_ToolでLayoutの有効・無効が設定できるようになった。

$zf.sh enable layout

コマンドを実行すると

a)layouts/script/layout.phtmlが作成される
b)application.iniに
 resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
 と追加される。

(3)アクションを追加

$zf.sh create action アクション名 コントローラ名

コマンドを実行すると
a)IndexControllerにsampleAction()が追加される
b)views/scripts/index/sample.phtmlが作成される
viewには、コントローラ名と、アクション名が表示されるようになっている。

※コマンドの説明では、
Action
zf create action name controller-name[=index] view-included[=1] module

とあって、 indexがデフォルトだと思って実行してみたけど、追加するコントローラがないと怒られる。
実はコントローラの指定では、Indexと最 初は大文字で指定しないとNGなようで、ハマッた。


(4)モデルを作成
これも1.10.0から追加されたもの

$zf.sh create model modelsample

コマンド実行すると
a)applications/models/Modelsample.php が作成される

単に空のクラスが作成されるだけ。
ディレクトリによる階層分けを試してみたけど、うまく指定できなかった。



(5)コントローラーの追加
$zf.sh create controller sample

コマンドを実行すると、
a)applications/controllers/SampleController.phpが作成される
メソッドはinit()とindexAction()が空の状態で生成される。
b)views/scripts/db/index.phtmlが作成される

(6)DBアダプターの設定をapplication.iniに追加
これも1.10.0から追加された。

$zf.sh configure dbadapter "host=ホスト名&adapter=Pdo_Pgsql&username=ユーザ名&password=パスワード&dbname=データベース名"

コマンドを実行すると
a)application.iniに指定内容がZend_Application_Resource_Dbが利用できる形で反映される。

DBパラメータ指定箇所は単に展開されるだけなので、正しいパラメータ名を記述する必要がある。

[パラメータ名]
host
adapter
dbname
username
password


※section-nameを指定して、application.ini内の任意のセクションに設定を追加できると思うのだけど、うまくいかなかった。

(7)テーブルクラスを追加
これも1.10.0で追加された。

zf.sh create db-table account account_tb -f

コマンドを実行すると

a)models/DbTable/Acctount.phpが作成される

$_nameにテーブル名が指定される状態でコードが生成される。
テーブル名を指定しないとエラーになる。
テーブル名とクラス名の規約に一致していればいいはずなので、指定なしでもいいような・・・。


マニュアルを見ると、データベースを指定して、データベースの自動生成できるようなことが書いてある。
コマンド例をいろいろ試してみたけど、できなかった。まだ、実装されていないのだろうか?

ついでに、コマンドのヘルプでは、db-tableと指定することになっているけど、リファレンスでは、dbtableになっており、どちらの指定でも生成はされていた。


DbTalbeが自動的にDB内のテーブルをスキャンして生成してくれるようになるとずいぶん楽になるんだけど、もうすこしといったところか。

2010年1月29日金曜日

Zend Framework 1.10.0リリース

Zend Framework 1.10.0リリースがリリースされてました。

気になるのは、
Zend_Application resourcesで、Log, Mailが追加されている
Zend_ToolでModel generation, DbAdapter setup, Layouts and Form Generationが追加されている(っぽい)
ところか。

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クラスから関連するテーブルの情報を簡単に取得することもできる。

2010年1月19日火曜日

FirePHPは便利

FirePHPは、FirefoxのアドオンのFirebugの機能拡張で、インストールすることで、サーバ側の出力をFirebugのコンソールに出力できる。

HTTPヘッダーを利用しているようで、試してませんが、Ajaxの通信などでHTMLをブラウザに出力しない場合でも利用できるそうです。
Zend Frameworkのコンポーネントでは、Zend_logやZend_Db_Profilerなどで、出力先をFireBugのコンソールにできます。

(1)ログを内容を出力する
ログライターにZend_Log_Writer_Firebugを利用する。

$writer=new Zend_Log_Writer_Firebug();
$log=new Zend_Log($writer);
//日本語出力もOK
$log->info("日本語もOK");

日本語の出力も問題なくできました(UTF-8だけしか試してません)

(2)DBのプロファイルを出力する
プロファイラーに Zend_Db_Profiler_Firebugを設定する。

$db=Zend_Db::factory('Pdo_Pgsql', array(
 host=>'hogehoge',
 username=>'dbuser',
 password=>'dbpass',
 dbname=>'sampledb'
));
$profiler=new Zend_Db_Profiler_Firebug('All DB Queries');
$profiler->setEnabled(true);
$db->setProfiler($profiler);
Zend_Db_Table_Abstract::setDefaultAdapter($db);


Firebugのコンソールではテーブル構成で結構見やすい。

自分の環境では、なぜか、ページを出力しただけではコンソールに出力されず、その状態で一度Firebugをオフ/オンして再表示するとコンソールに表示される。
まだ安定してないのか、設定がよくないのか・・・・。
(追記)Firebugを1.50に更新したら直った。

Zend Framework 1.9.7などなどリリース

Zend Framework 1.9.7がリリースされてました。

他にも、1.8.5,1.7.9と古いバージョンのリビジョンがあがっています。
XSS関連の問題の修正がされているようです。

Zend_SessionでCookieを使用しないセッション管理

デフォルトはCookieを使うようになっているので、php.iniもしくは.htaccessで使用しないように設定。
勝手にURLにセッションをつけない様にする。セッションIDの名称変更。

.htaccessの記載例)

php_value session.use_cookies 0 #Cookie利用しない
php_value session.use_only_cookies 0 #Cookie以外も利用
php_value session.use_trans_sid 0 #URLへの自動付与OFF
php_value session.name hogesession #セッションID名称を変更


Zend_Sessionでセッションをスタート

Zend_Session::setOptions(array(use_only_cookies=>'off'));
Zend_Session::start();
$session=new Zend_Session_Namespace('hoge');


Zend_Sessionでは、use_only_cookiesがデフォルトでONに設定されるようで、.htaccessでoffにしていても、ONになってしまうので、Zend_Session::startの引数で必ずオプションを設定しておいたほうがいい。

.htaccessで設定したほうが、プログラム内で設定するよりもいいと思うけど、Zend_Sessionが動作する際に、上書きしてしまうので、すべてZend_Sessionのパラメータで設定するのでもいいかも。

Zend_Sessionを利用する場合は以下は必ず必要なので忘れずに。
php_value session.auto_star 0 #セッション自動開始OFF

そのほか指定しそうなパラメータ

・有効期間
php_value session.gc_maxlifetime 1800 #有効期間を30分

・セッション情報保存先を指定(ファイルに出力する場合)
#/tmp/php/hogeディレクトリへ出力 書き込み権限は必要
php_value session.save_path=/tmp/php/hoge



Zend_Sessionを利用する際にしてはいけないこと。
・session_start関数は使用しない。
・Zend_Session::start()使用やZend_Session_Namaspaces()の生成などは、Zend_Session関連のそのほかの操作の前には必ず処理をさせておく


view部分で、セッション名称やセッションIDをを取得するには、以下の関数から取得する。
セッション名:session_name();
セッションID:session_id();

2010年1月8日金曜日

ひさびさにフリーのER図作成ツール

以前からEclpiseで利用していたDBモデリングツールのClay(1.4.2)をEclipse3.5で使おうとしたら動かなかったので、別のものを探してみました。

とりあえず、PostgreSQLに対応していて、DDLが出力できるもの。
さらにER図の画像出力や、テーブル定義をドキュメント出力してくれるとうれしい。

[Clay MarkII]
http://www.azzurri.co.jp/ja/clay/index.html

Clayが2009/8くらいにMarkIIになってました。#ガンダムか?
試しに、旧バージョンのファイルを読み込ませてみたら、テーブルの配置がすべて左上になってました。
PostgreSQLの対応は7.3,7.4で旧版と変わらず。このあたり8.x対応になったりしないのかな?
見た目は前よりもリッチ感(?)があるように思えました

有償版はライセンスの形態が変更になっていて、従来のインストールベースから、プロジェクトベースになっており、お値段も8万4千円とお高くなってます。
前バージョンは会社でライセンスを買っていましたが(確か3万円弱だったような?)、1人か2人くらいで開発することが多いので、前バージョンよりも割高感があります。

前バージョンは直接ダウンロードできず、プラグインの入手方法は「注文番号を添えて問い合わせてください」って書いてありました。


[ERMaster]
http://ermaster.sourceforge.net/index_ja.html

使い方はClayとほとんど変わらず、迷わず使えました。

Entityの色やデザインを変更できたり、Entityに表示するレベルを変更できたりします。
ExcelやHTMLでテーブル定義書っぽいものを出力できるので、体裁を整えるにはいいかも。
あと、辞書機能は便利でした。
ClayMarkIIよりも好みにあっているので、とりあえずERMasterを使ってみようと思います。

本当はNetbeans6で利用できるものがあればよかったんだけど、見つからず。
知っている人がいたら教えてほしい。

2010年1月6日水曜日

ExtJS3.1がリリースされてました

IE6のメモリリークに関する対応がなされた模様。
その他、新しいUIも追加されているようです。

Zend Framework 1.9.6リリース

Zend Framework 1.9.6リリースがリリースされてました。
次は1.10.1になりそうです。