<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jean-Michel Feurprier &#187; php5</title>
	<atom:link href="http://blog.jmfeurprier.com/category/php/php5/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jmfeurprier.com</link>
	<description>LAMP Web Architect</description>
	<lastBuildDate>Sat, 13 Feb 2010 00:16:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>method_exists() vs. is_callable()</title>
		<link>http://blog.jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/</link>
		<comments>http://blog.jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 07:17:24 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[php5]]></category>
		<category><![CDATA[tips and tricks]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/</guid>
		<description><![CDATA[One thing I often see when re-factoring PHP applications, is the improper use of the method_exists() function, and I think this needs a little bit of clarification. <a href="http://blog.jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One thing I often see when re-factoring PHP applications, is the improper use of the <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> function, and I think this needs a little bit of clarification.<br />
<span id="more-221"></span><br />
Here is a typical example of what I&#8217;m talking about:</p>
<pre class="brush: php; title: ; notranslate">

if (method_exists($object, 'SomeMethod'))
{
  $object-&gt;SomeMethod($this, TRUE);
}
</pre>
<p>The purpose of this code snippet is quite easy to understand (even if I don&#8217;t encourage to do this kind of not-very-OOP-stuff): having an object named &#8220;$object&#8221;, we try to know if it has a method named &#8220;SomeMethod&#8221;, if so, we call it, and provide some arguments to it.</p>
<h3>Yes, but&#8230;</h3>
<p>This code will probably run very well during all its lifetime, but what if the object&#8217;s method is not visible from the current scope (like&#8230; a private or protected method)? PHP&#8217;s <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> function does what it says: it checks if the provided class or object has a method named like the provided one, and returns TRUE if so, or FALSE if not, visibility is not questionned. So, if you provide a private or protected existing method name (being out of current scope) to <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, you&#8217;ll get TRUE as the return value, and a nice &#8220;Fatal error: Call to private method&#8230;&#8221;, immediately terminating the current script execution.</p>
<h3>The right tool for the right job</h3>
<p>The real intent of the previous code snippet was in fact to know if the application could <strong>call</strong> a method on the object, from the current scope.</p>
<p>This is why (among other reasons) <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> is part of the PHP built-in functions.</p>
<h3>How does it work?</h3>
<p><a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> receives a <a href="http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback">callback</a> as its first argument, which, in our case, consists of an array of two values: the first being an object (or a string holding a class name), and the second being a string holding a method name. <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> returns TRUE when the provided callback can be called from the current scope, or FALSE if not. </p>
<pre class="brush: php; title: ; notranslate">

if (is_callable(array($object, 'SomeMethod')))
{
  $object-&gt;SomeMethod($this, TRUE);
}
</pre>
<p>Here is another snippet of code to illustrate the differences between <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> and <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> in action:</p>
<pre class="brush: php; title: ; notranslate">
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), &quot;\n&quot;;
}
</pre>
<p>Run it, and you&#8217;ll see that every test returns TRUE with <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, even private methods, while <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> returns FALSE for these (and will also trigger strict errors with non-static methods being queried as static ones, be aware of this).</p>
<h3>More details</h3>
<p><a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> has other uses, like checking the syntax of the provided callback, without checking if there really is a class or a method with the provided names.<br />
Like <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a>, <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> can trigger a class autoloading process if the provided class is not already loaded.<br />
If an object has the magic <a href="http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods">__call()</a> method implemented, then <a href="http://www.php.net/manual/en/function.is-callable.php">is_callable()</a> will return TRUE for any non-existent method, while <a href="http://www.php.net/manual/en/function.method-exists.php">method_exists()</a> will return FALSE. I guess the same behavior can be observed with the recent (PHP 5.3.0) <a href="http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods">__callStatic()</a> magic method, but I did not test it (yet).<br />
Everything else you need to know is in the <a href="http://www.php.net/manual/">PHP manual</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jmfeurprier.com/2010/01/03/method_exists-vs-is_callable/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

