views:

158

answers:

5

Hi,

I'm trying to use the php function method_exists, but I need to check if the method exists in the parent class of an object.

so:

class Parent
{
    public function myFunction()
    {
        /* ... */
    }
}

class Child extends Parent
{
    /* ... */
}

$myChild = new Child();

if (method_exists($myChild, 'myFunction'))
{
    /* ... */
}

if (method_exists(Parent, 'myFunction'))
{
    /* ... */
}

if (is_callable(array('Parent', 'myFunction'))
{
    /* ... */
}

But none of the above are working. I'm not sure what to try next.

Thanks for any help!

+5  A: 

Class child must extend the parent in that case

class Parent
{
   public function hello()
   {

   }
}

class Child extends Parent
{

}

$child = new Child();

if(method_exists($child,"hello"))
{
    $child->hello();
}

Update This would have the same effect as method_exists I believe.

function parent_method_exists($object,$method)
{
    foreach(class_parents($object) as $parent)
    {
        if(method_exists($parent,$method)
        {
           return true;
        }
    }
    return false;
}

if(method_exists($child,"hello") || parent_method_exists($object,"hello"))
{
    $child->hello();
}

Just updated from Wrikken's post

RobertPitt
I forgot to add the extends part, in my project Child does extend Parent. It's actually a Doctrine Base Model class, but on futher investigation I don't think what I'm trying to do will work, as functions in the Doctrine Base model classes seem to be working with overloading/interception as there is no function declarations visible
Serg
@Serg If you have `extends Parent` in your actual code then your first expression `if (method_exists($myChild, 'myFunction'))` would be true. (NB: I added the closing parenthesis)
w3d
@Serg: Maybe you should add a more concrete example to your question and explain in detail what you're actually trying to achieve.
VolkerK
updated my post.
RobertPitt
Thanks everyone, I ended up using is_callable and it is working now as I require.
Serg
+1  A: 

RobertPitt is correct in that the Child class is not a child class unless it extends the Parent class. But from your original code snippet, the following should be true:

if (method_exists('Parent', 'myFunction')
{
  // True
}

Note the 'Parent' is in quotes, you had it unquoted. Passing the class name as a string.

w3d
+1  A: 

If you want to know specifically if it exists in the parent, and not only in your own class:

foreach(class_parents($this) as $parent){
    if(method_exists($parent,$method){
        //do something, for instance:
        parent::$method();
        break;
    }
}
Wrikken
+2  A: 

You should use PHP's Reflection API:

class Parend
{
  public function myFunction()
  {

  }
}

class Child extends Parend{}

$c = new Child();


$rc = new ReflectionClass($c);
var_dump($rc->hasMethod('myFunction')); // true

And if you want to know in which (parent) class the method lives:

class Child2 extends Child{}

$c = new Child2();
$rc = new ReflectionClass($c);

while($rc->getParentClass())
{
    $parent = $rc->getParentClass()->name;
    $rc = new ReflectionClass($parent);
}
var_dump($parent); // 'Parend'
Dennis Haarbrink
Does the reflection API work also with objects that use overloading/interception?
kiamlaluno
AFAIK it dynamically (at runtime) inspects objects/classes, so that would be yes.
Dennis Haarbrink
No, it wouldn't be able to catch that a `__call()` function (although it would be easy to test for the existance of `__call()`). Ex: `class A{function __call($func,$args){}} $r = new ReflectionClass('A');var_dump($r->hasMethod'thisRandomFunctionWorks'));` outputs false, although the function can be called.
Wrikken
A: 

Wouldn't method_exists and get_parent_class combined also work if done within the child class?

For instance

class Parent
{

}

class Child extends Parent
{
   public function getConfig()
   {
     $hello = (method_exists(get_parent_class($this), 'getConfig')) ? parent::getConfig() : array();
   }
}
KRavEN