MongoDB をフィルタリングするだけで、次のように簡単に実現できます。
Item::all(array('conditions' =>
array('myfield' => array(
'$nin' => array(1,2,3)
))
));
これが頻繁に行われる場合は、そのためのカスタム ファインダーを作成することもできます。
class MyModel extends \lithium\data\Model {
public static function __init()
{
parent::__init();
static::finder('notin', function($self, $params, $chain) {
// Take all array keys that are not option keys
$array = array_diff_key($params['options'],
array_fill_keys(array('conditions', 'fields','order','limit','page'),0));
// Clean up options leaving only what li3 expects
$params['options'] = array_diff_key($params['options'], $array);
$params['options']['conditions'] = array(
'myfield' => array(
'$nin' => $array
)
);
return $chain->next($self, $params, $chain);
});
}
}
そして、次のように呼び出します:
MyModel::notin(array(1,2,3));
同じ方法で、MySQL ソースのカスタム ファインダーを作成できます。
おそらくわかるようarray('fields'=>$array)
に、オプションを上書きするようなものを渡すと、いくつかの問題が発生します。何が起こるかというと、::notin()
(ファインダー全般) は (array,null) 署名に対して異なる動作をします。その場合、最初の配列はオプションであり、ファインダは引数を取りませんでした。実際の 2 番目の引数 (オプション) が渡されたときに最初の引数が終了するため、使用notin($array,array())
すると前のファインダーが壊れます。$params['notin']
ここでデータ ソースをその場で混合する場合は、\lithium\data\Model を継承しないカスタム モデルを作成し、それ
をさまざまなモデルに委任して、エンド モデルのデータ ソースに基づいて条件を作成します。
class MyFacadeModel {
public static function byNotIn($conditions, $source) {
return ($source == "mongodb")
? $source::find( $rewrittenConditions)
: $source::find( $rewrittenConditionsForMysql );
}
}
(コードはほとんど頭のてっぺんから取ったものなので、少し間違っているかもしれません)