php 5.6+ callback
Для удобности работы с callback функциями напишем небольшой класс.
- <?php
- class Callback
- {
- /**
- * @var \Closure|array|string
- */
- private $callback;
- /**
- * @param \Closure|object|string $name
- * @param string $method
- */
- public function __construct($name, $method = false) {
- if ($name instanceof \Closure) {
- $this->callback = $name;
- } else if (is_object($name)) {
- $this->callback = array($name,
- $method);
- } else if ($method) {
- $this->callback = $name . '::' . $method;
- } else {
- $this->callback = $name;
- }
- if (!is_callable($this->callback)) {
- throw new \InvalidArgumentException('...');
- }
- }
- /**
- * @return mixed
- */
- public function __invoke() {
- return call_user_func_array($this->callback, func_get_args());
- }
- /**
- * @param array $args
- *
- * @return mixed
- */
- public function call(array $args = []) {
- $callback = [
- $this, '__invoke'
- ];
- return call_user_func_array($callback, $args);
- }
- /**
- * @return boolean
- */
- public function isClosure() {
- return $this->callback instanceof \Closure;
- }
- /**
- * @return boolean
- */
- public function isDynamicMethod() {
- return is_array($this->callback);
- }
- /**
- * @return boolean
- */
- public function isStaticMethod() {
- return is_string($this->callback) && false !== strpos($this->callback, ':');
- }
- /**
- * @return boolean
- */
- public function isFunction() {
- return is_string($this->callback) && !$this->isStaticMethod();
- }
- /**
- * @return boolean
- */
- public function toString() {
- if ($this->isStaticMethod() || $this->isFunction()) {
- return $this->callback;
- }
- }
- }
Класс-помощник, который разрешит проблему.
- class CallbackResolver
- {
- public static function resolve($callback) {
- if (is_string($callback) && false !== strpos($callback, ':')) {
- list ($class, $method) = explode('::', $callback, 2);
- return new Callback($class, $method);
- } else if (is_array($callback) && 2 == count($callback) && is_object($callback[0]) && is_string($callback[1])) {
- return new Callback($callback[0], $callback[1]);
- } else {
- return new Callback($callback);
- }
- }
- }
Пример использования:
- <?php
- // Пример №1
- function test() {
- return 'Привет, мир!';
- }
- try {
- $callback = CallbackResolver::resolve('test');
- if ($callback instanceof Callback) {
- // Функция?
- if ($callback->isFunction()) {
- // Вызов двумя способами:
- $callback(/* arg, arg,.. */);
- // или
- $callback->call([
- // args
- ]);
- }
- }
- } catch (\InvalidArgumentException $e) {
- // Обработка исключения
- }
- // Пример №2
- try
- {
- $callback = CallbackResolver::resolve('test2');
- //
- } catch (\InvalidArgumentException $e) {
- // Обработка исключения
- }
- // В данном случае нужно будет обработать исключение т.к функции test2 не существует
- // Пример №3
- class test
- {
- public static function test($name) {
- echo 'Привет, мир!';
- }
- }
- try
- {
- $callback = CallbackResolver::resolve('test::test');
- if ($callback instanceof Callback) {
- if ($callback->isStaticMethod()) {
- $callback();
- }
- }
- } catch (\InvalidArgumentException $e) {
- // Обработка исключения
- }
- // Пример №4
- try
- {
- $callback = CallbackResolver::resolve(function() {
- echo 'Привет, мир!';
- });
- if ($callback instanceof Callback) {
- if ($callback->isClosure()) {
- $callback();
- }
- }
- } catch (\InvalidArgumentException $e) {
- // Обработка исключения
- }
- // Пример №5
- class test
- {
- public function test() {
- echo 'Привет, мир!';
- }
- }
- try
- {
- $callback = CallbackResolver::resolve([new test(), 'test']);
- if ($callback instanceof Callback) {
- if ($callback->isDynamicMethod()) {
- $callback();
- }
- }
- } catch (\InvalidArgumentException $e) {
- // Обработка исключения
- }