Check if a method exists in an extended class but not parent class

Viewed 4813

With method_exists, it checks all methods, including the parent class.

Example:

class Toot {
    function Good() {}
}

class Tootsie extends Toot {
    function Bad() {}
}

function testMethodExists() {
    // true
    var_dump(method_exists('Toot', 'Good'));

    // false
    var_dump(method_exists('Toot', 'Bad'));

    // true
    var_dump(method_exists('Tootsie', 'Good'));

    // true
    var_dump(method_exists('Tootsie', 'Bad'));
}

How can I check that the method only exists on the current class and not parent class (ie. Tootsie)?

6 Answers

Based on the @sleepless answer above, but working in case the method doesn't exist at all:

function methodImplementedInClass($className, $methodName) {
    // If this class doesn't have the method at all, return false
    if (!method_exists($className, $methodName)) {
        return false;
    }
    // Now check if the method was implemented in this class or in some parent
    return (new ReflectionClass($className))->getMethod($methodName)->class == $className;
}

Here's my solution, using reflection and checking the actual class involved in the Reflection Method.

<?php

class Base {
    public function BaseOnly() {
    }

    public function Extended() {
    }
}

class Child extends Base {
    public function ChildOnly() {
    }

    public function Extended() {
    }
}

function childMethodExists($baseClass, $childClass, $methodName) {
    if (!method_exists($childClass, $methodName)) {
        return false; // doesn't exist in the child class or base class
    }
    if (!method_exists($baseClass, $methodName)) {
        return true; // only exists on child class, as otherwise it would have returned above
    }
    // now to check if it is overloaded
    $baseMethod = new ReflectionMethod($baseClass, $methodName);
    $childMethod = new ReflectionMethod($childClass, $methodName);
    return $childMethod->class !== $baseMethod->class;
}

var_dump(childMethodExists(Base::class, Child::class, 'BaseOnly')); // false
var_dump(childMethodExists(Base::class, Child::class, 'ChildOnly')); // true
var_dump(childMethodExists(Base::class, Child::class, 'Neither')); // false
var_dump(childMethodExists(Base::class, Child::class, 'Extended')); // true
Related