Одну вещь, которую я часто вижу, когда просматриваю чужой код на php, это не правильное использование функции  method_exists(), и это требует немного разъяснений.

Это типичный пример того, о чем я тут говорю

if (method_exists($object, 'SomeMethod')){
  $object->SomeMethod($this, TRUE);
}

Цель у этого куска кода довольно проста - понять: имеет ли некий объект (переменная $object) метод с названием SomeMethod, если так то вызвать его, подав несколько аргументов на вход

Да, но...

Этот код будет, вероятно, работать очень хорошо в течение всей своей жизни, но что если метод объекта будет не видим в текущем положении (к примеру метод private или protected)? PHP функция method_exists()  делает следующее: она проверяет если класс или объект имеет метод исходя из того, что метод будет вызван внутри самого объекта. И вернет true если это так, или false если нет. Т.е. видимость метода, в конкретном применении вообще не проверяется. Поэтому, если вы используете private или protected методы, то такая проверка вернет true, но когда вы попытаетесь вызвать такой код, то увидите следующую ошибку

“Fatal error: Call to private method…”, immediately terminating the current script execution.

Правильный инструмент для правильной работы

Реальная цель предыдущего кода, была в том, чтобы определить, может ли данный метод быть вызван в данном контексте

Поэтому верно будет использовать is_callable() функцию php

Как это работает?

is_callable() получает на вход  callback как первый аргумент, который, в нашем случае, является массивом и содержит два занчения: первое из которых - это объект (ну или название класса в виде строки), а второй содержит имя метода. is_callable() вернет TRUE когда метод будет доступен в данном контексте

if (is_callable(array($object, 'SomeMethod'))){
  $object->SomeMethod($this, TRUE);
}

Следующий кусок кода илюстрирует разницу между работой двух функций method_exists() и is_callable() в действии:

class Foo {
  public function PublicMethod() {}
  private function PrivateMethod() {}
  public static function PublicStaticMethod() {}
  private static function PrivateStaticMethod() {}
}
 
$foo = new Foo();
 
$callbacks = array(
  array($foo, 'PublicMethod'),
  array($foo, 'PrivateMethod'),
  array($foo, 'PublicStaticMethod'),
  array($foo, 'PrivateStaticMethod'),
  array('Foo', 'PublicMethod'),
  array('Foo', 'PrivateMethod'),
  array('Foo', 'PublicStaticMethod'),
  array('Foo', 'PrivateStaticMethod'),
);
 
foreach ($callbacks as $callback) {
  var_dump($callback);
  var_dump(method_exists($callback[0], $callback[1])); // 0: object / class name, 1: method name
  var_dump(is_callable($callback));
  echo str_repeat('-', 40), "\n";
}

Запустите это, и вы увидите, что все тесты вернули true при использовании method_exists(), даже private методы, тогда как is_callable() вернул FALSE

Больше деталей

is_callable() нужно использовать, когда нужно проверить - может ли быть вызван тот или иной метод в данном контексте, и совершенно ничего не говорит, о том, есть ли такой метод в определении класса
кроме того, если проверяемый класс, имеет реализацию метода  __call() тогда is_callable()  вернет true для любых, даже не существующих методов. А method_exists() вернет false;

Все остальное вы можете узнать, в PHP документации.

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить

Комментарии   

0
slotternur
# slotternur 18.02.2015 13:33
ко мне с сайта приходят письма о новых пользователях.
будто бы я админ!
я думаю случилось ошибка! свяжитесь со мной
ПСЫ
не нашел контактов
+1
Leroy
# Leroy 18.02.2015 14:34
уже ведь не должно приходить. Спасибо. Вчера исправил этот косяк
+1
slotternur
# slotternur 18.02.2015 14:46
Лерой я у вас в долгу напишите мне в почту. Я потерял ваши контакты!
0
Dave
# Dave 21.02.2015 16:28
> Все остальное вы можете узнать, в .

Совсем нет кода в статье, поправьте, плз.
0
Andrey
# Andrey 02.08.2016 17:57
не плохо бы еще и орегинал ыказувать, откуда брали статью: http://jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/