Страница 1 из 1

Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 16:40
Kilimangaro
Всем привет! Хочу при обработке события, сераилзовать его сохранить в БД. Но получаю ошибку:
Error : Exception Serialization of 'Closure' is not allowed

Вот примеры, как я пробовал это реализовать

Код: Выделить всё

$app->on(\yii\base\Application::EVENT_AFTER_REQUEST, function($event){
    serialize($event);
});

Код: Выделить всё

\Yii::$app->on($name, function(Notification $event){
     serialize($event);
});

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 17:39
zelenin

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:00
Kilimangaro
я так понимаю ты > 6к сообщений именно такого характера налупасил? За что я люблю рунет так это "что бы не случилось напечатай в ответ линк на google"

Изображение

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:08
zelenin
Kilimangaro писал(а):
я так понимаю ты > 6к сообщений именно такого характера налупасил?
все мои сообщения можно посомтреть. еще одну ссылку дать?
Kilimangaro писал(а):За что я люблю рунет так это "что бы не случилось напечатай в ответ линк на google"
на этом форуме ссылки на гугл только на справочные вопросы.
Kilimangaro писал(а):Изображение
и что не понятно? нам своими словами пересказать? сериализовать анонимку можно только переделав ее в НЕанонимку, например в вид [$this, 'functionName'] или воспользовавшись сторонней либой, которая сама это сделает. вот я пересказал тебе то, что было написано по посещенным тобою ссылкам.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:18
Kilimangaro
zelenin писал(а):и что не понятно? нам своими словами пересказать? сериализовать анонимку можно только переделав ее в НЕанонимку, например в вид [$this, 'functionName'] или воспользовавшись сторонней либой, которая сама это сделает. вот я пересказал тебе то, что было написано по посещенным тобою ссылкам.
Ну во первых не нам, а тебе, я с тобой говорю а не со всеми. Не знаешь - шагай мимо. Знаешь, помоги. И исходи из того, что с тобой общается человек, который
а) Уже юзал google
б) Уже юзал первое что приходит в голову, в частности
[$this, 'functionName'] или воспользовавшись сторонней либой, которая сама это сделает. вот я пересказал тебе то, что было написано по посещенным тобою ссылкам.
Другое дело, что, например я не все понял, что было по ссылкам. Именно поэтому я тут. То есть для более широкого общения, сейчас внимание, важная вставка, - с людьми, которые шарят.

Код: Выделить всё

public function actionNotify()
    {
        $topic = Topic::findOne(30);
        $topic->on(ActiveRecord::EVENT_AFTER_UPDATE,[$this, 'hanlder']);
        $topic->save();
    }

    public function hanlder($event)
    {
        serialize($event);
    }
Если речь идет о таком решении, то это первое что я попробовал и это не привело к успеху.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:24
zelenin
Kilimangaro писал(а):
zelenin писал(а):и что не понятно? нам своими словами пересказать? сериализовать анонимку можно только переделав ее в НЕанонимку, например в вид [$this, 'functionName'] или воспользовавшись сторонней либой, которая сама это сделает. вот я пересказал тебе то, что было написано по посещенным тобою ссылкам.
Ну во первых не нам, а тебе, я с тобой говорю а не со всеми.
нет, ты задал вопрос на форуме - тут кроме меня еще есть люди.
Kilimangaro писал(а):Не знаешь - шагай мимо. Знаешь, помоги.
помог. вопрос справочный - отправил в гугл.
Kilimangaro писал(а):И исходи из того, что с тобой общается человек, который
а) Уже юзал google
б) Уже юзал первое что приходит в голову, в частности
[$this, 'functionName'] или воспользовавшись сторонней либой, которая сама это сделает. вот я пересказал тебе то, что было написано по посещенным тобою ссылкам.
Другое дело, что, например я не все понял, что было по ссылкам. Именно поэтому я тут. То есть для более широкого общения, сейчас внимание, важная вставка, - с людьми, которые шарят.

Код: Выделить всё

public function actionNotify()
    {
        $topic = Topic::findOne(30);
        $topic->on(ActiveRecord::EVENT_AFTER_UPDATE,[$this, 'hanlder']);
        $topic->save();
    }

    public function hanlder($event)
    {
        serialize($event);
    }
 
Если речь идет о таком решении, то это первое что я попробовал и это не привело к успеху.
[/quote]с этого и надо было начинать, т.к. вопрос по моему мнению справочный и трудностей с этим у меня никогда не возникало. А если у тебя возникли, но ты ничего о своем данном опыте не поведал, то я закономерно делаю вывод, что ты даже не гуглил.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:32
zelenin
ругается у тебя на сериализацию эвента (т.е. где-то внутри эвента есть анонимка). а переделываешь ты саму функцию сериализации.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:50
Kilimangaro
Для тех, кто в танке, как этот мистер 6к постов "иди гугли", во избежании дальнейших недоразумений, объясню:
Нужно сериализовать объект, который прилетает в обработчик события, но все мои попытки приводят к ошибкам: Exception Serialization of 'Closure' is not allowed

Код: Выделить всё

$topic->on(ActiveRecord::EVENT_AFTER_UPDATE,function($event){
    serialize($event); //Exception Serialization of 'Closure' is not allowed
});
Тогда я попробовал схитрить

Код: Выделить всё

$topic->on(ActiveRecord::EVENT_AFTER_UPDATE,[$this, 'handler']);  //Exception Serialization of 'Closure' is not allowed

Тогда, я подумал, может в Event есть какое-то свойство, из-за которого глюк (например анонимка)? И переписал код вообще без обработки события, может дело вовсе не в замыкании

Код: Выделить всё

$topic = Topic::findOne(30);
$event = new \yii\base\Event(['sender' => $topic]);
echo serialize($event);
Этот код успешно отработал, тогда я подумал, ну остается один вариант, проблема таки в замыкании. Следовательно, я написал свою версию

Код: Выделить всё

$callback = function($obj){
    echo serialize($obj);
};

class A {
    public $foo;

    public function __construct($bar){
        $this->foo = $bar;
    }
}

$obj = new A('РАБОТАЙ ЖЕ ЕБАННОЕ ГАВНО');
$callback($obj);
Этот код успешно отработал. Отсюда стало понятно две вещи
1. Анонимная функция, она же замыкание спокойно внутри себя может сериализовать
2. Она отлично может серилизовать объекты внутри себя.

Тогда я попробовал сделать так и опять обламался, потому что все работает

Код: Выделить всё

$callback = function($obj){
   echo serialize($obj);
};

$topic = Topic::findOne(40);
$event = new \yii\base\Event(['sender' => $topic]);
$callback($event);
Ну и тут я немного "подвис". С такими выводами: Если Event и мой ActiveRecord сериализуется в не обработчика событий, просто в анонимке, то значит в них нет свойств по причине которых не проходила бы сериализация. Если допустим, проблемным является само замыкание во время обработки события, то тогда это должно было бы работать в таком виде, но нет:

Код: Выделить всё

$topic->on(ActiveRecord::EVENT_AFTER_UPDATE,[$this, 'handler']);  //Exception Serialization of 'Closure' is not allowed
Отсюда у меня вопрос, как заставить это работать?

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 18:55
zelenin
Kilimangaro писал(а):Для тех, кто в танке, как этот мистер 6к постов "иди гугли"
отличный способ спрашивать совета на форуме, задевая человека, который тебе уже все разжевал и в рот положил.
Kilimangaro писал(а):ЕБАННОЕ ГАВНО

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.20, 19:35
R3D3
Kilimangaro писал(а): Тогда, я подумал, может в Event есть какое-то свойство, из-за которого глюк (например анонимка)? И переписал код вообще без обработки события, может дело вовсе не в замыкании
Все правильно сделал. Только это не глюк, а хорошо задокументированное поведение. Подробнее вот тут viewtopic.php?f=19&t=36439#p186658
Отсюда у меня вопрос, как заставить это работать?
Найти в твоем объекте $event все содержащиеся анонимки и любой ценой избавиться от них. Тогда $event станет нормально сериализовываться.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.21, 09:17
Kilimangaro
Почему тогда вот этот код успешно выполнился? Все правила соблюдены: те же объекты, так же анонимка но результат другой?
R3D3 писал(а):
Отсюда у меня вопрос, как заставить это работать?
Найти в твоем объекте $event все содержащиеся анонимки и любой ценой избавиться от них. Тогда $event станет нормально сериализовываться.

Код: Выделить всё

$callback = function($obj){
   echo serialize($obj);
};

$topic = Topic::findOne(40);
$event = new \yii\base\Event(['sender' => $topic]);
$callback($event);
Изображение

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.21, 09:28
Kilimangaro
отличный способ спрашивать совета на форуме, задевая человека, который тебе уже все разжевал и в рот положил.
Спасибо. Поржал.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.21, 10:34
ElisDN
Kilimangaro писал(а):Почему тогда вот этот код успешно выполнился?
Потому что Вы не выполнили $topic->on(..., $callback), который бы поместил вашу анонимку в private $_events топика. Тогда бы топик не ссериализовался.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.21, 16:59
R3D3
Локальный совет: сделай var_dump($event) сразу перед сериализацией в своем приложении и увидишь что в объекте содержится еще куча всякой хрени, в том числе и анонимки.

Глобальный совет: сериализовывать и сохранять в базу $event далеко не самая лучшая идея, лучше создавать из них более плоские и примитивные объекты, а их уже сериализовывать.

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.21, 17:01
zelenin
R3D3 писал(а):Глобальный совет: сериализовывать и сохранять в базу $event далеко не самая лучшая идея, лучше создавать из них более плоские и примитивные объекты, а их уже сериализовывать.
:!:

Re: Как сериализовать Event в обработчике (замыкание)

Добавлено: 2016.04.29, 13:26
Kilimangaro
R3D3 писал(а):Глобальный совет: сериализовывать и сохранять в базу $event далеко не самая лучшая идея, лучше создавать из них более плоские и примитивные объекты, а их уже сериализовывать.
Вот это пожалуй самый шикарный совет, так и сделал. Спасибо :)

А суть проблемы, была таковой. Если передавать просто

Код: Выделить всё

new Event(); 
(то есть не определять sender явно), то в sender, Yii пихает объект Application. В котором, естественно, тьма переменных с типом Closure. Тоже самое, будет если передавать в sender Controller. Если же, передавать в sender модель, например $topic, то все работает нормально. Интересный момент, что изначально, я так и делал, но не работало. Странно, только почему, оно сразу не работало. Может где-то был не внимателен, ну или это магия.