特定のタイプのオブジェクトを扱っていることがわかっている場合と$obj();
は対照的に、本当に呼び出すべきではありません。$obj->function();
とはいえ、同僚に頭を悩ませたくない場合を除きます。
この__invoke
方法は、さまざまな状況で活気づきます。特に、ジェネリック呼び出し可能オブジェクトを引数として提供することが期待される場合。
引数として callable のみを取るクラス (使用する必要があり、変更できない) にメソッドがあるとします。
$obj->setProcessor(function ($arg) {
// do something costly with the arguments
});
ここで、時間のかかる操作の結果をキャッシュして再利用したり、以前に使用したその関数の引数にアクセスしたりしたいとします。分厚いことができる通常の閉鎖で。
// say what? what is it for?
$argList = [];
$obj->setProcessor(function ($arg) use (&$argList) {
static $cache;
// check if there is a cached result...
// do something costly with the arguments
// remember used arguments
$argList[] = $arg;
// save result to a cache
return $cache[$arg] = $result;
});
他の場所からにアクセスする必要がある場合$argList
、または停止したエントリのキャッシュを単純に消去する必要がある場合は、問題が発生します。
ここで__invoke
救助に来ます:
class CachableSpecificWorker
{
private $cache = [];
private $argList = [];
public function __invoke($arg)
{
// check if there is a cached result...
// remember used arguments
$this->argList[] = $arg;
// do something costly with the arguments
// save result to a cache
return $this->cache[$arg] = $result;
}
public function removeFromCache($arg)
{
// purge an outdated result from the cache
unset($this->cache[$arg]);
}
public function countArgs()
{
// do the counting
return $resultOfCounting;
}
}
上記のクラスを使用すると、キャッシュされたデータを簡単に操作できます。
$worker = new CachableSpecificWorker();
// from the POV of $obj our $worker looks like a regular closure
$obj->setProcessor($worker);
// hey ho! we have a new data for this argument
$worker->removeFromCache($argWithNewData);
// pass it on somewhere else for future use
$logger->gatherStatsLater($worker);
これは、概念を説明するための単純な例です。さらに進んで、一般的なラッパーとキャッシング クラスを作成することもできます。そして、はるかに。