Viewed   108 times

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.

 Answers

3

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"
Tuesday, August 2, 2022
1

A base class should really never depend on information about child classes---

To answer your question:

class base {
    public function __construct() {
        print "Class:" . get_class($this) . "n";
    }
}

class child extends base{
    public function __construct() {
        parent::__construct();
    }
}
$c = new child();

Just for future reference -- this can be acheived in a static context using get_called_class(), but this is only available in PHP >= 5.3

Saturday, October 8, 2022
5

Static methods are resolved on the compile-time type of the variable. m is of type Main, so the method in Main is called.

If you change it to SubMain m ..., then the method on SubMain will be called.

Tuesday, August 16, 2022
 
hade
 
3

Not possible. Static methods are not runtime polymorphic in any way. It's absolutely impossible to distinguish these cases:

System.out.println(Entity.getClass());
System.out.println(User.getClass());

They compile to the same byte code (assuming that the method is defined in Entity).

Besides, how would you call this method in a way where it would make sense for it to be polymorphic?

Monday, August 22, 2022
 
3

To call a static method, you don't use:

$foobar = new FooBar;
$foobar->foo()

You call

FooBar::foo();

The PHP manual says...

Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).

This is why you are able to call the method on an instance, even though that is not what you intended to do.

Whether or not you call a static method statically or on an instance, you cannot access $this in a static method.

http://php.net/manual/en/language.oop5.static.php

You can check to see if you are in a static context, although I would question whether this is overkill...

class Foobar
{
  public static function foo()
  {
    $backtrace = debug_backtrace();
    if ($backtrace[1]['type'] == '::') {
      exit('foo');
    }
  }
}

One additional note - I believe that the method is always executed in a static context, even if it is called on an instance. I'm happy to be corrected on this if I'm wrong though.

Saturday, October 15, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :