Getting the name of a child class in the parent class (static context)

前端 未结 9 884
栀梦
栀梦 2020-11-29 20:19

I\'m building an ORM library with reuse and simplicity in mind; everything goes fine except that I got stuck by a stupid inheritance limitation. Please consider the code bel

相关标签:
9条回答
  • 2020-11-29 20:31

    in short. this is not possible. in php4 you could implement a terrible hack (examine the debug_backtrace()) but that method does not work in PHP5. references:

    • 30423

    • 37684

    • 34421

    edit: an example of late static binding in PHP 5.3 (mentioned in comments). note there are potential problems in it's current implementation (src).

    class Base {
        public static function whoAmI() {
            return get_called_class();
        }
    }
    
    class User extends Base {}
    
    print Base::whoAmI(); // prints "Base"
    print User::whoAmI(); // prints "User"
    
    0 讨论(0)
  • 2020-11-29 20:35

    Two variations on Preston's answer:

    1)

    class Base 
    {
        public static function find($id)
        {
            $table = static::$_table;
            $class = static::$_class;
            $data = array('table' => $table, 'id' => $id);
            return new $class($data);
        }
    }
    
    class User extends Base
    {
        public static $_class = 'User';
    }
    

    2)

    class Base 
    {
        public static function _find($class, $id)
        {
            $table = static::$_table;
            $data = array('table' => $table, 'id' => $id);
            return new $class($data);
        }
    }
    
    class User extends Base
    {
        public static function find($id)
        {
            return self::_find(get_class($this), $id);
        }
    }
    

    Note: starting a property name with _ is a convention that basically means "i know i made this public, but it really should have been protected, but i couldn't do that and achieve my goal"

    0 讨论(0)
  • 2020-11-29 20:37

    I know this question is really old, but for those looking for a more practical solution than defining a property in every class containing the class name:

    You can use the static keyword for this.

    As explained in this contributor note in the php documentation

    the static keyword can be used inside a super class to access the sub class from which a method is called.

    Example:

    class Base
    {
        public static function init() // Initializes a new instance of the static class
        {
            return new static();
        }
    
        public static function getClass() // Get static class
        {
            return static::class;
        }
    
        public function getStaticClass() // Non-static function to get static class
        {
            return static::class;
        }
    }
    
    class Child extends Base
    {
    
    }
    
    $child = Child::init();         // Initializes a new instance of the Child class
    
                                    // Output:
    var_dump($child);               // object(Child)#1 (0) {}
    echo $child->getStaticClass();  // Child
    echo Child::getClass();         // Child
    
    0 讨论(0)
  • 2020-11-29 20:43

    The problem is not a language limitation, it is your design. Never mind that you have classes; the static methods belie a procedural rather than object-oriented design. You're also using global state in some form. (How does get_row_from_db_as_array() know where to find the database?) And finally it looks very difficult to unit test.

    Try something along these lines.

    $db = new DatabaseConnection('dsn to database...');
    $userTable = new UserTable($db);
    $user = $userTable->get(24);
    
    0 讨论(0)
  • 2020-11-29 20:49

    I know its old post but want to share the solution I have found.

    Tested with PHP 7+ Use the function get_class()link

    <?php
    abstract class bar {
        public function __construct()
        {
            var_dump(get_class($this));
            var_dump(get_class());
        }
    }
    
    class foo extends bar {
    }
    
    new foo;
    ?>
    

    The above example will output:

    string(3) "foo"
    string(3) "bar"
    
    0 讨论(0)
  • 2020-11-29 20:52

    You don't need to wait for PHP 5.3 if you're able to conceive of a way to do this outside of a static context. In php 5.2.9, in a non-static method of the parent class, you can do:

    get_class($this);
    

    and it will return the name of the child class as a string.

    i.e.

    class Parent() {
        function __construct() {
            echo 'Parent class: ' . get_class() . "\n" . 'Child class: ' . get_class($this);
        }
    }
    
    class Child() {
        function __construct() {
            parent::construct();
        }
    }
    
    $x = new Child();
    

    this will output:

    Parent class: Parent
    Child class: Child
    

    sweet huh?

    0 讨论(0)
提交回复
热议问题