Пытался задать вопрос на stackoverflow, но, видимо, из-за корявого английского меня там не поняли. Мне нужно инициализировать свойство трейта как экземпляр соседнего класса.
trait FilterTrait {
protected $_filter = new Filter(); // Нельзя использовать как дефолтное значение
public function __construct () { // Перезапишется в используемом классе
$this->_filter = new Filter();
}
public function SetFilter ($arFilter) {
$this->_filter->Set($arFilter);
}
public function CleanFilter () {
$this->_filter->CLean();
}
public function GetFilter () {
return $this->_filter->Get();
}
...
}
Не хочу, чтобы дочерний класс помогал в работе используемого трейта, и вообще знал что-то об его устройстве, вот так:
class Select extends Query {
use TablesListTrait,
FieldsListTrait,
FilterTrait,
HavingTrait,
SortTrait,
LimitTrait,
GroupTrait;
function __construct () {
$this->_tablesList = new TablesList();
$this->_fieldsList = new FieldsList();
$this->_filter = new Filter();
...
}
...
}
И инициализировать при каждом вызове метода тоже не хочу
trait FilterTrait {
protected $_filter;
public function InitializeFilter () {
if (is_null($this->_filter)) {
$this->_filter = new Filter();
}
}
public function SetFilter ($arFilter) {
$this->InitializeFilter();
$this->_filter->Set($arFilter);
}
public function CleanFilter () {
$this->InitializeFilter();
$this->_filter->CLean();
}
public function GetFilter () {
$this->InitializeFilter();
return $this->_filter->Get();
}
}
Можно, конечно, замутить перезагрузку методов, но это не сильно лучше.
Нашел информацию о том, что в версии 5.6 вот такое написание поддерживается
class Foo {
protected $bar = new Baz();
}
не проверял, но все-таки большинство хостингов на данный момент стоят на 5.3 - 5.4, и использовать эти фишки пока сложно. К тому же хочу еще реализовать регистрацию мнемоник для вызова методов трейта из параметров, передающихся в дочерние классы. Если бы существовал какой-нибудь магический метод, регистрирующий несколько __construct функций, мне бы это помогло:
trait Actions {
protected $_arActions = array();
public function RegisterActions ($arActions) {
$this->_arActions = array_merge($this->_arActions, $arActions);
}
public function ResetParameters ($arParameters) {
foreach ($arParameters as $mnemonic => $actionParameters) {
if (isset($this->_arActions[$mnemonic])) {
$action = $this->_arActions[$mnemonic];
$this->$action($actionParameters);
}
}
}
}
trait FilterTrait {
use Actions;
public function __onUse () {
$arActions = array(
"filter" => "SetFilter"
);
$this->RegisterActions($arActions);
}
public function SetFilter ($arFilter) {...}
}
class Select extends Query {
use TablesListTrait,
FieldsListTrait,
FilterTrait,
HavingTrait,
SortTrait,
LimitTrait,
GroupTrait;
public function __construct ($arParams) {
$this->ResetParameters($arParams);
}
}
...
$arSelectParams = array(
"table" => "products",
"fields" => array(
"id",
"name",
"price"
),
"filter" => array(
"id" => 5,
"<=price" => 1000
),
"sort" => array(
"price" => "asc"
)
);
$query = new Select($arSelectParams);
Есть какой-нибудь вариант сделать что-то подобное сейчас или, если нет, ожидается ли концепция подобного в будущем, где-нибудь в седьмой версии?