#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]);
}
}
}