filterに使えるarray_intersect_key

第一パラメタの配列の中で、第2パラメタ以降の配列全てに存在するキーのものだけ取得してくれる。

詳しい説明はこちらで。
http://php.net/manual/ja/function.array-intersect-key.php

今まで、Zend_Db_Table_RowのsetFromArrayの存在を知らなかったので、自分でこんなやりかたでfilterしてました。

$tmp = array();     
$table = new Zend_Db_Table_Abstractを継承したクラス();
$cols = $table->info('cols');
foreach ($params as $key => $value) {
    if (in_array($key, $cols)) { $columns[$key] = $value; }
}

これが、

$table = new Zend_Db_Table_Abstractを継承したクラス();
$cols = $table->info('cols');
$tmp = array_intersect_key($params, array_flip($cols));

と書けます。これ便利ですね。

ZendFrameworkのソースに書いてありました。
なんで今まで見つけれなかったんだろう。必要としてなかったからなのか。
もっと楽な方法がないのかって思えてなかったことに反省。

phpのautoloadメソッドはスタック

Zend_Loader_Autoloaderってどういう手順で、__autoloadを設定しているのかが気になってみてみたら、spl_autoload_registerを使っていました。apl_autoload_registerの説明を見てみたら、以下の文が。

指定した関数を、spl が提供する __autoload スタックに登録します。
スタックがまだアクティブになっていない場合は、まずアクティブにします。

もしあなたのコード中に __autoload 関数が存在するのなら、 それを明示的に __autoload スタックに登録しなければなりません。 なぜなら、spl_autoload_register() は、 spl_autoload() あるいは spl_autoload_call() によって __autoload 関数のエンジンキャッシュを効率的に置き換えるからです。

スタックってことは、複数のautoloadロジックを使えるってことですよね。
これはいつか覚えててよかったと思いそうだったので、メモがわりに残します。

動的にクラスを定義する方法ないかなと思ってるんです。
Zend_Db_Table_Rowをテーブル毎に名前を変えて定義したい場合、名前とprotectedの変数の値しか変わらないのに、毎回書くのは面倒に感じてしまって。

Doctrineは、自動生成っていう方法で面倒さを回避していますが、Zend_Db_Table_Rowの拡張の場合、自動生成するような分量でもないし、自動生成のやり方を説明するところで、時間をくいそうなので、自動的ができたらなと考えています。現時点でいいアイデアは浮かんでいません。

http://www.php.net/manual/ja/function.spl-autoload-functions.php
http://www.php.net/manual/ja/function.spl-autoload-register.php
http://www.php.net/manual/ja/function.spl-autoload.php
http://www.php.net/manual/ja/function.spl-autoload-call.php

【Zend】処理中にbootstrapを取得する方法

controllerの中なら、

$bootstrap = $this->getInvokeArg('bootstrap');

で取得できる。

modelとかの中でも

$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');

で取得できる

bootstrap取得して何をするかというと、application.iniで設定したリソースを取得できる。
例えば、multidbリソースを使ってたとすると

$bootstrap->getPluginResource('multidb')->getDb('hoge1');

みたいに、hoge1 DBへのDBアダプターが取得できる。

このアダプターを、各テーブルクラスのコンストラクタで、テーブルのアダプターとして設定してあげると、普段Default_Adapterを設定しているときのように、どのアダプタを使うとかを、プログラムを作るときに意識しなくていい。

== その後1 ==
生成されたPluginリソース(Zend/Application/Resourceとかにあるやつ)は、
BootstrapのContainer(中身はZend_Registryインスタンス)に入ってたので。

$boostrap->getContainer()->multidb->getDb('hoge1');

でも同様のDBアダプターが取得できる。

getPluginResource()だと、インスタンスがなかった場合作ってくれるが、
Container経由だと、なかったらnullが返ってくるはず。

どっちもpublicメソッドなので、どちらでも使える。
処理数でいうと、getContainerが少ない(チェックとかないため)ので、
最初からインスタンスがあるってわかってるものについては、getContainer()経由がいいのかも。

== その後2 ==
ソース見ても、getPluginResource()は、bootstrapの中からしか呼ばれてないし、
protectedでいいと思うんだけど、なんでだろう?

自前のBootstrap作るときも、Bootstrapクラス継承するから問題ないし。
クラス外から呼ばれることを想定していたとして、どういう場合かがわからん。

getContainer()一本でいいのに。