maleks писал(а): ↑2017.04.22, 10:11
pistol писал(а): ↑2017.04.21, 20:36
Блин... Теперь пойду ковырять, как Yii узнает, что возвращать в getOwner
Бросьте вы это, про "владельца" трейта вам уже выше сказали, а вы все код какой то сочиняете, код получается конечно знатный
,но не для ядра yii, может для вашей цмс разве..
Ну, я для саморазвития сделал определение owner магией и поздним статическим связыванием. Для пользователя все работает как раньше, за исключением того, что "поведения" теперь должны содержать только статические методы. Такие поведения могут быть приаттачены как трейт (через Use) и динамически через ->attachTrait() уже после инстанцирования класса, результат при этом будет одинаков.
Более того, такие трейты могут быть даже конфигурированы статическими свойствами. И, соответственно, также аттачиться из конфига с настройками:
Код: Выделить всё
'as MyTrait' => [
'class' => 'common\traits\MyTrait'
'var1' => 1,
]
Код: Выделить всё
<?php
//Упрощенный yii::$app
class Yii
{
public static $app = [];
}
//Упрощенный yii\base\Trait
trait YiiTrait
{
public static $owner;
function getOwner()
{
if(!$owner = self::$owner) {
$owner = get_called_class();
}
return Yii::$app[$owner];
}
}
//Упрощенный yii\base\Object
class YiiObject
{
private $traits = [];
public function attachTrait($trait)
{
$this->traits[] = $trait;
}
public function __call($method, $args)
{
if(isset($this->traits)) {
foreach($this->traits as $trait) {
if(method_exists($trait, $method)) {
$trait::$owner = get_called_class();
$return = $trait::$method($args);
$trait::$owner = null;
return $return;
}
}
}
throw new Exception('Method don\'t exists');
}
}
//Пользовательский трейт
trait Tr
{
public static $owner;
use YiiTrait;
public static function sum()
{
return self::getOwner()->x + self::getOwner()->y;
}
}
//Пользовательский трейт 2
trait Tr2
{
use YiiTrait;
public static function sum()
{
return self::getOwner()->x + self::getOwner()->y;
}
}
//Пользовательский компонент 1
class Obj extends YiiObject
{
use Tr;
public $x;
public $y;
public function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
}
//Пользовательский компонент 2
class Obj2 extends YiiObject
{
public $x;
public $y;
public function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
}
//Инит приложения
Yii::$app = [
'Obj' => new Obj(1, 6),
'Obj2' => new Obj2(8, 6),
];
//Если не атачить - вылетет Exception
//Yii::$app['Obj']->attachTrait('Tr'); - это зааттачено через трейт
Yii::$app['Obj2']->attachTrait('Tr2');
echo Yii::$app['Obj']->sum();
echo '<br />';
echo Yii::$app['Obj2']->sum();
echo '<br />';
echo Yii::$app['Obj']->sum();
echo '<br />';
echo Yii::$app['Obj2']->sum();
echo '<br />';
echo Yii::$app['Obj']->sum();