Получить константу, переопределенную из дочернего метода, объявленного в абстрактном классе

#php #oop #class #reflection #constants

#php #ооп #класс #отражение #константы

Вопрос:

У меня есть это (сокращенное):

 abstract class MyModel
{
    const DBID = "";
    const TOKEN = "";

    public function getDB()
    {
        if(!$this->_DB)
        {
            $c = get_called_class(); // doesn't work pre php 5.3
            echo $c::DBID; // doesn't work pre php 5.3
            echo $c::TOKEN // doesn't work pre php 5.3
        }

        return $this->_qb;
    } 
  

Проблема в том, что get_called_class() и $c::DBID/TOKEN не работает в php <5.3

Есть ли способ, которым я могу выполнить ту же задачу из абстрактного класса, совместимого с 5.2.9?

Ответ №1:

РЕДАКТИРОВАТЬ: константы на самом деле не предназначены для изменения во всех экземплярах объекта, вместо этого вы можете рассмотреть переменные-члены.

Абстрактные классы не могут быть созданы напрямую. Вы можете создать дочерний класс для расширения вашего абстрактного класса, а затем вызвать getDb() .

 abstract class MyModel
{
    private $dbId;
    private $token;

    public function setDbId($dbId)
    {
        $this->dbId = $dbId;
    }

    public function setToken($token)
    {
        $this->token = $token;
    }

    public function getDbId()
    {
        return $this->dbId;
    }

    public function getToken()
    {
        return $this->token;
    }

    public function __construct()
    {
        // All child classes will have the same values
        $this->setDbId('myParentDbId');
        $this->setToken('myParentToken');
    }

    protected function getDb()
    {
        echo $this->getDbId();
        echo $this->getToken();
    }
}

class MyChildModel extends MyModel
{
    // Don't need any methods, just access to abstract parent
    // But if I wanted to override my parent I could do this
    public function __construct()
    {            
        parent::__construct();

        $this->setDbId('myChildDbId');
        $this->setToken('myChildToken');
    }
}

$myChildModel = new MyChildModel();
var_dump($myChildModel->getDb());
  

Комментарии:

1. Разве в абстрактном конструкторе я не сделал бы: $this-> setDbId(parent:: $dbID) и $this-> setToken(parent::$token)?

2. Если вы хотите использовать родительскую версию тех же значений, просто удалите переопределяющие значения дочернего элемента, тогда любые вызовы getDb() будут использовать родительскую версию. Я просто показывал вам гибкость, которую обеспечивает это решение.

Ответ №2:

У меня было решение в базе кода PHP 5.2, которое использовало отражение для получения констант подкласса из суперкласса, но я бы не советовал этого делать, если это не является абсолютно необходимым, потому что отражение является относительно дорогим инструментом в PHP с точки зрения производительности.

В PHP 5.3 введено ключевое слово static, как в static::CONST вместо self::CONST для доступа к статическим членам класса. Я никогда на самом деле не пробовал это, но я считаю, что он должен быть в состоянии делать то, что вам нужно. Посмотрите позднее статическое связывание в руководстве по PHP.

Для записи, вот код для метода, который использовал отражение для получения константы подкласса.

 class SomeClass
{
    /**
     * Get reflection class for item
     * 
     * Get a reflector for this item so that internal constants can be used for the permission checking
     * functions.  This is necessary because of how static binding works prior to PHP 5.3.  
     * 
     * @return ReflectionClass
     */
    protected function getRef ()
    {
        if (!$this -> ref)
        {
            $this -> ref    = new ReflectionClass ($this);
        }
        return ($this -> ref);
    }

    /**
     * Check that the user has permission to create an item of the type this object represents
     *
     * @todo Use late static binding instead of reflection once PHP 5.3 becomes available on the server
     * @return bool True if OK
     */
    public function canCreate ()
    {
        $ref    = $this -> getRef ();
        if ($flag = $ref -> getConstant ('USR_FLAG_CREATE'))
        {
            return (self::$user -> permissions [$flag]);
        }
    }
}