Search code examples
phpoopphp-5.3php-5.2

Is there any way to detect the target class in static methods?


Below is an example class hierarchy and code. What I'm looking for is a way to determine if 'ChildClass1' or 'ChildClass2' had the static method whoAmI() called on it without re-implementing it in each child class.

<?php

abstract class ParentClass {

    public static function whoAmI () {

        // NOT correct, always gives 'ParentClass'
        $class = __CLASS__;

        // NOT correct, always gives 'ParentClass'. 
        // Also very round-about and likely slow.
        $trace = debug_backtrace();
        $class = $trace[0]['class'];

        return $class;
    }
}

class ChildClass1 extends ParentClass {

}

class ChildClass2 extends ParentClass {

}

// Shows 'ParentClass'
// Want to show 'ChildClass1'
print ChildClass1::whoAmI(); 
print "\n";

// Shows 'ParentClass'
// Want to show 'ChildClass2'
print ChildClass2::whoAmI();
print "\n";

Solution

  • Now that PHP 5.3 is widely available in the wild, I wanted to put together a summary answer to this question to reflect newly available techniques.

    As mentioned in the other answers, PHP 5.3 has introduced Late Static Binding via a new static keyword. As well, a new get_called_class() function is also available that can only be used within a class method (instance or static).

    For the purpose of determining the class as was asked in this question, the get_called_class() function is appropriate:

    <?php
    
    abstract class ParentClass {
    
        public static function whoAmI () {
            return get_called_class();
        }
    
    }
    
    class ChildClass1 extends ParentClass {
    
    }
    
    class ChildClass2 extends ParentClass {
    
    }
    
    // Shows 'ChildClass1'
    print ChildClass1::whoAmI(); 
    print "\n";
    
    // Shows 'ChildClass2'
    print ChildClass2::whoAmI();
    print "\n";
    

    The user contributed notes for get_called_class() include a few sample implementations that should work in PHP 5.2 as well by making use of debug_backtrace().