/** * 関数を呼び出す * * 関数名と引数から決定されるキーに対応する値がKVSにキャッシュされていれば * それを返し、なければ関数を呼び出し、結果をKVSにキャッシュする。 * * @param callable $function * @param array $parameters * @return mixed * @throws InvalidArgumentException */ public function invoke($function, array $parameters = array()) { if (!is_callable($function)) { throw new InvalidArgumentException('Non-callable value was given'); } // 関数名 if (is_string($function)) { $name = $function; if (strpos($function, '::') !== false) { $function = explode('::', $function, 2); } } elseif (is_object($function)) { $name = get_class($function) . '->__invoke'; } elseif (is_object($function[0])) { $name = get_class($function[0]) . '->' . $function[1]; } else { $name = $function[0] . '::' . $function[1]; } // キー $key = strtolower($name) . '('; if ($n = count($parameters)) { $key .= $n . ':' . md5(serialize($parameters)); } else { $key .= 'void'; } $key .= ')'; // キャッシュを取得 $record = $this->_kvs->getRaw($key); if ($record && !$record->isExpired($this->_lifeTime)) { return $this->_kvs->getCodec()->decodeValue($record->value); } // なければ関数を実行 if ($n) { if ($n == 1 && !is_array($function)) { $value = $function(reset($parameters)); } else { $value = call_user_func_array($function, $parameters); } } elseif (is_array($function)) { $value = call_user_func($function); } else { $value = $function(); } // キャッシュに保存 if ($record) { $this->_kvs->update($key, $value); } else { $this->_kvs->set($key, $value); } return $value; }