Страница 2 из 3
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:25
pistol
zelenin писал(а): ↑2017.04.21, 19:22
pistol писал(а): ↑2017.04.21, 19:19Я все это веду к тому, что если будут использовать не $this, а $this->owner, то можно будет по-старому инжектить методы трейтов:
так как инжектить? пример выше - это обычное использование трейтов. там же нет динамического аттача.
При вызове несуществующего метода, можно возвращать одноименный метод из приаттаченных трейтов.
Если во всех трейтах будет использоваться $this->owner вместо $this и заюзан Yii\\base\Trait, можно гарантировать одинаковый результат работы трейтов приаттаченых нормально и динамически.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:30
zelenin
pistol писал(а): ↑2017.04.21, 19:25
zelenin писал(а): ↑2017.04.21, 19:22
pistol писал(а): ↑2017.04.21, 19:19Я все это веду к тому, что если будут использовать не $this, а $this->owner, то можно будет по-старому инжектить методы трейтов:
так как инжектить? пример выше - это обычное использование трейтов. там же нет динамического аттача.
При вызове несуществующего метода, можно возвращать одноименный метод из приаттаченных трейтов.
это то, ради чего трейты были созданы.
pistol писал(а): ↑2017.04.21, 19:25Если во всех трейтах будет использоваться $this->owner вместо $this и заюзан Yii\\base\Trait, можно гарантировать одинаковый результат работы трейтов приаттаченых нормально и динамически.
я спрашиваю, где вы динамически аттачите трейты? трейты не аттачатся динамически. и $this->owner не нужен.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:32
ElisDN
pistol писал(а): ↑2017.04.21, 19:25
При вызове несуществующего метода, можно возвращать одноименный метод из приаттаченных трейтов.
Предлагаете инжектить коллбэки в трейт, чтобы магией их оттуда вызывать?
P.S. Трейты не настраиваются и на события не навешиваются, поэтому поведения они никогда не заменят.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:45
pistol
zelenin писал(а): ↑2017.04.21, 19:30
я спрашиваю, где вы динамически аттачите трейты? трейты не аттачатся динамически. и $this->owner не нужен.
В yii\base\Component, как и раньше (магией __call). Вот только как вытащить метод из трейта - хз, инстанс трейта не создается, только если рефлексией как-то. Попробую ради интереса.
ElisDN писал(а): ↑2017.04.21, 19:32
pistol писал(а): ↑2017.04.21, 19:25
При вызове несуществующего метода, можно возвращать одноименный метод из приаттаченных трейтов.
Предлагаете инжектить коллбэки в трейт, чтобы магией их оттуда вызывать?
P.S. Трейты не настраиваются и на события не навешиваются, поэтому поведения они никогда не заменят.
А вот настройки - да, даже теоритических идей нет, как это сделать.
Всем спасибо. Понял, что не получится использовать коллбеки как раньше.
Ждем выхода нового YII
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:47
zelenin
pistol писал(а): ↑2017.04.21, 19:45
zelenin писал(а): ↑2017.04.21, 19:30
я спрашиваю, где вы динамически аттачите трейты? трейты не аттачатся динамически. и $this->owner не нужен.
В yii\base\Component, как и раньше
да код покажите. не аттачатся же.
pistol писал(а): ↑2017.04.21, 19:45только как вытащить метод из трейта - хз, инстанс трейта не создается, только если рефлексией как-то. Попробую ради интереса.
так о том и речь, что обсуждаем то, чего нет.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:49
zelenin
их и не надо аттачить. Поведения много где использовались, но теперь есть для каждого использования поведений современные кейсы.
например к моделям AR - обычные трейты, поведения реквеста - миддлвари итд.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 19:56
pistol
zelenin писал(а): ↑2017.04.21, 19:49
их и не надо аттачить. Поведения много где использовались, но теперь есть для каждого использования поведений современные кейсы.
например к моделям AR - обычные трейты, поведения реквеста - миддлвари итд.
Подумал еще немного - действительно, по-настоящему важных кейсов, где нужно аттачить динамически поведение не вспомнил. Везде только для перехвата событий в сервисе используется, можно просто $obj->on() такое инжектить.
Спасибо.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 20:29
pistol
zelenin писал(а): ↑2017.04.21, 19:47
так о том и речь, что обсуждаем то, чего нет.
Поразбирался с рефлексией - не получилось ничего.
Но все-таки нашел способ сделать так, чтобы все работало как раньше (с динамическим инжектом и отжектом). Но только со статическими методами и свойствами
Код: Выделить всё
<?php
//Упрощенный yii::$app
class Yii
{
public static $app = [];
}
//Упрощенный yii\base\Trait
trait YiiTrait
{
function getOwner()
{
return Yii::$app['Obj'];
}
}
//Упрощенный yii\base\Object
class YiiObject
{
private $traits = [];
public function attachTrait($trait)
{
$this->traits[] = $trait;
}
public function __call($method, $args)
{
foreach($this->traits as $trait) {
if(method_exists($trait, $method)) {
return $trait::$method($args);
}
}
throw new Exception('Такого метода нет!');
}
}
//Пользовательский трейт
trait Tr
{
use YiiTrait;
function __construct()
{
return $this->sum();
}
public static function sum()
{
return YiiTrait::getOwner()->x + YiiTrait::getOwner()->y;
}
}
//Пользовательский компонент
class Obj extends YiiObject
{
public $x;
public $y;
public function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
}
//Инит приложения
Yii::$app = [
'Obj' => new Obj(1, 6),
];
//Если не атачить - вылетет Exception
Yii::$app['Obj']->attachTrait('Tr');
echo Yii::$app['Obj']->sum();
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.21, 20:36
pistol
Блин... Теперь пойду ковырять, как Yii узнает, что возвращать в getOwner
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.22, 08:36
maleks
pistol писал(а): ↑2017.04.21, 19:56
Подумал еще немного - действительно, по-настоящему важных кейсов, где нужно аттачить динамически поведение не вспомнил. Везде только для перехвата событий в сервисе используется, можно просто $obj->on() такое инжектить.
Если в системе на компонентах есть события, то и должен быть удобный способ навесить сразу набор событий.
Не каждое сидеть и в init() прописывать ->on(), а одним махом. Поведения с этим справляются. Даже пусть эта связь будет статической, все равно это надо. Это в том числе и готовый шаблон Наблюдатель.
Как трейты смогут по нормальному навешивать группы событий на компонент, пока идей нет.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.22, 10:11
maleks
pistol писал(а): ↑2017.04.21, 20:36
Блин... Теперь пойду ковырять, как Yii узнает, что возвращать в getOwner
Бросьте вы это, про "владельца" трейта вам уже выше сказали, а вы все код какой то сочиняете, код получается конечно знатный
,но не для ядра yii, может для вашей цмс разве..
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.22, 10:50
pistol
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();
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 14:21
Йож
Илья, трейт по сути инклуд, как написал Дмитрий Елисеев.
Код: Выделить всё
trait MyTrait
{
public function sum()
{
return "ok";
}
}
class MyClass {
}
echo (new MyClass)->sum(); //error
Если подключить трейт:
Код: Выделить всё
class MyClass {
use MyTrait;
}
echo (new MyClass)->sum(); //ok
Зачем там owner определять..
А так Yii 2.2 будет наверно через два года, чего сейчас париться
Плюс в тексте написано про traits+events, AccessorTrait, EventTrait etc. В общем механизм будет продуман и задокументирован, останется просто пользоваться
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 17:33
pistol
Йож писал(а): ↑2017.04.23, 14:21
Илья, трейт по сути инклуд, как написал Дмитрий Елисеев.
Зачем там owner определять..
Да, я понимаю, что это инклуд. Просто стало интересно, возможно ли с трейтами оставить функционал ->attachBehavior(), без owner этого не реализовать. Оказывается, трейты можно юзать без класса, но только статик. функции.
Йож писал(а): ↑2017.04.23, 14:21
А так Yii 2.2 будет наверно через два года, чего сейчас париться
Плюс в тексте написано про traits+events, AccessorTrait, EventTrait etc. В общем механизм будет продуман и задокументирован, останется просто пользоваться
+, очень интересно, ждем
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 18:02
zelenin
pistol писал(а): ↑2017.04.23, 17:33+, очень интересно, ждем
многие умрут к этому времени
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 20:11
Йож
zelenin писал(а): ↑2017.04.23, 18:02
многие умрут к этому времени
pistol писал(а): ↑2017.04.23, 17:33
+, очень интересно, ждем
Согласен!
P.S.
https://github.com/pistol88/yii2-cart/pull/28
На днях еще до админки yii2-order доберусь основательно, еще чего-нибудь полезное дозакину
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 20:24
SiZE
Ну вы тут и наобсуждали. С одной стороны я рад что люди задаются такими вопросами, с другой стороны удручает, что они не умеют при этом использовать поиск.
https://github.com/yiisoft/yii2/issues/1053
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 20:29
pistol
Спасибо! Только подожди недельку.
https://github.com/dvizh - мы все модули, которые для сайтов, рефакторим тут и скоро выкатим скелетон, в котором очень много всего интересного будет из неопубликованного. Модули из аккаунтов прогеров будут "заморожены" с ссылкой в Ридми на /dvizh.
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 20:30
pistol
Re: Как заинжектить трейт в объект
Добавлено: 2017.04.23, 20:42
pistol
Правда, по всей видимости, инфа устарела. В этом топике в 2013 было решено оставить поведения.