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

94,927

Solution 1

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:

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"

Solution 2

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?

Solution 3

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

Solution 4

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"

Solution 5

In case you don't want to use get_called_class() you can use other tricks of late static binding (PHP 5.3+). But the downside in this case you need to have getClass() method in every model. Which is not a big deal IMO.

<?php

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

    public function __construct($data)
    {
        echo get_class($this) . ': ' . print_r($data, true) . PHP_EOL;
    }
}

class User extends Base
{
    protected static $_table = 'users';

    public static function getClass()
    {
        return __CLASS__;
    }
}

class Image extends Base
{
    protected static $_table = 'images';

    public static function getClass()
    {
        return __CLASS__;
    }
}

$user = User::find(1); // User: Array ([table] => users [id] => 1)  
$image = Image::find(5); // Image: Array ([table] => images [id] => 5)
Share:
94,927

Related videos on Youtube

user3679701
Author by

user3679701

I'm a code monkey.

Updated on July 08, 2022

Comments

  • user3679701
    user3679701 almost 2 years

    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 below:

    class BaseModel {
        /*
         * Return an instance of a Model from the database.
         */
        static public function get (/* varargs */) {
            // 1. Notice we want an instance of User
            $class = get_class(parent); // value: bool(false)
            $class = get_class(self);   // value: bool(false)
            $class = get_class();       // value: string(9) "BaseModel"
            $class =  __CLASS__;        // value: string(9) "BaseModel"
    
            // 2. Query the database with id
            $row = get_row_from_db_as_array(func_get_args());
    
            // 3. Return the filled instance
            $obj = new $class();
            $obj->data = $row;
            return $obj;
        }
    }
    
    class User extends BaseModel {
        protected $table = 'users';
        protected $fields = array('id', 'name');
        protected $primary_keys = array('id');
    }
    class Section extends BaseModel {
        // [...]
    }
    
    $my_user = User::get(3);
    $my_user->name = 'Jean';
    
    $other_user = User::get(24);
    $other_user->name = 'Paul';
    
    $my_user->save();
    $other_user->save();
    
    $my_section = Section::get('apropos');
    $my_section->delete();
    

    Obviously, this is not the behavior I was expecting (although the actual behavior also makes sense).. So my question is if you guys know of a mean to get, in the parent class, the name of child class.

  • user3679701
    user3679701 over 15 years
    Yes, I just read about debug_backtrace().. A possible solution would be to use late static binding from PHP 5.3 but that's not a possibility in my case. Thank you.
  • user3679701
    user3679701 over 15 years
    .. no. You didn't understand what I was trying to bo, but that's because I didn't explain it well :). Actually, I'm just trying to provide a static method (implemented in BaseModel) to get() an instance of a given Model (may it be User, Role or whatever). I will update the question..
  • user3679701
    user3679701 over 15 years
    Ok, updated. Of course the BaseModel class has much more methods, including some to keep track of what is changed in the object and UPDATE only what has chaged, etc... But thank you anyway :).
  • Levi Morrison
    Levi Morrison over 12 years
    If you are using abstract classes, this is a must-know.
  • Justin C
    Justin C almost 10 years
    I think $x = new Parent(); should be $x = new Child();.
  • Xesau
    Xesau over 9 years
    array_shift seems is slow, because it will have to change every key of the array... Just $args[0] instead;
  • godbout
    godbout over 5 years
    Thank you! Was struggling with ReflectionClass but calling static() is the way to go!
  • bdalina
    bdalina over 5 years
    this is it pancit!
  • shmnff
    shmnff almost 5 years
    Child class might be without constructor