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

前端 未结 9 885
栀梦
栀梦 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:54

    Maybe this isn't actually answering the question, but you could add a parameter to get() specifing the type. then you can call

    BaseModel::get('User', 1);
    

    instead of calling User::get(). You could add logic in BaseModel::get() to check whether a get method exists in the subclass and then call that if you want to allow the subclass to override it.

    Otherwise the only way I can think of obviously is by adding stuff to each subclass, which is stupid:

    class BaseModel {
        public static function get() {
            $args = func_get_args();
            $className = array_shift($args);
    
            //do stuff
            echo $className;
            print_r($args);
        }
    }
    
    class User extends BaseModel {
        public static function get() { 
            $params = func_get_args();
            array_unshift($params, __CLASS__);
            return call_user_func_array( array(get_parent_class(__CLASS__), 'get'), $params); 
        }
    }
    
    
    User::get(1);
    

    This would probably break if you then subclassed User, but I suppose you could replace get_parent_class(__CLASS__) with 'BaseModel' in that case

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

    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)
    
    0 讨论(0)
  • 2020-11-29 20:56

    It appears you might be trying to use a singleton pattern as a factory pattern. I would recommend evaluating your design decisions. If a singleton really is appropriate, I would also recommend only using static methods where inheritance is not desired.

    class BaseModel
    {
    
        public function get () {
            echo get_class($this);
    
        }
    
        public static function instance () {
            static $Instance;
            if ($Instance === null) {
                $Instance = new self;
    
            }
            return $Instance;
        }
    }
    
    class User
    extends BaseModel
    {
        public static function instance () {
            static $Instance;
            if ($Instance === null) {
                $Instance = new self;
    
            }
            return $Instance;
        }
    }
    
    class SpecialUser
    extends User
    {
        public static function instance () {
            static $Instance;
            if ($Instance === null) {
                $Instance = new self;
    
            }
            return $Instance;
        }
    }
    
    
    BaseModel::instance()->get();   // value: BaseModel
    User::instance()->get();        // value: User
    SpecialUser::instance()->get(); // value: SpecialUser
    
    0 讨论(0)
提交回复
热议问题