Getting the name of a child class in the parent class (static context)
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)
Related videos on Youtube
Comments
-
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 over 15 yearsYes, 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 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 over 15 yearsOk, 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 over 12 yearsIf you are using abstract classes, this is a must-know.
-
Justin C almost 10 yearsI think
$x = new Parent();
should be$x = new Child();
. -
Xesau over 9 yearsarray_shift seems is slow, because it will have to change every key of the array... Just $args[0] instead;
-
godbout over 5 yearsThank you! Was struggling with ReflectionClass but calling
static()
is the way to go! -
bdalina over 5 yearsthis is it pancit!
-
shmnff almost 5 yearsChild class might be without constructor