2016-10-29 2 views
1

У меня есть приложение Laravel для свойств, скажем, где-то в моем коде я:Бесконечного цикл при прослушивании модели события

$property = new Property(); 
$property->city = "New York"; 
... 
$property->save(); 

Тогда я прослушиватель события, ожидающий определенное событие:

$events->listen(
    'eloquent.saved: Properties\\Models\\Property', 
    'Google\Listeners\[email protected]' 
); 

И, наконец, в SetGeoLocationInfo.php у меня есть

public function fire($event) 
{ 
    $property = $event; 
    ... 
    //get GPS data from Google Maps 

    $property->latitude = $googleMapsObject->latitude; 
    $property->longitude = $googleMapsObject->longitude; 
    $property->save(); 
} 

И когда я сохранить модель в идет в конечная рекурсия, из-за save(), вызванного в обработчике.

Как я могу изменить свой код, чтобы он заполнил данные о местоположении только один раз после сохранения и избежать рекурсии?

Я не могу использовать flushEventListeners(), потому что в этом случае другие слушатели перестают работать (например, имущество фото есть).

+0

при стрельбе, используйте сохранение, вместо того, чтобы сохранить – Farkie

+0

Просто переопределить метод сохранения в собственности - передавать аргументы для режима экономии. В fire() вот так: $ property-> save (Свойство :: SAVE_FROM_GOOGLE_FIRE); для другого чего-то большего. – Deep

ответ

1

В этом случае, вероятно, лучше использовать метод saving. Но следует помнить, что во время saving вы не должны использовать save метод больше, так что ваш метод fire должен выглядеть следующим образом:

public function fire($event) 
{ 
    $property = $event; 
    ... 
    //get GPS data from Google Maps 

    $property->latitude = $googleMapsObject->latitude; 
    $property->longitude = $googleMapsObject->longitude; 
} 

Другое решение было бы добавить условие, чтобы установить и сохранить расположение GPS только если он еще не установлен :

if (empty($property->latitude) || empty($property->longitude)) { 
    $property->latitude = $googleMapsObject->latitude; 
    $property->longitude = $googleMapsObject->longitude; 
    $property->save(); 
} 
+0

Это не может избежать рекурсии – Deep

+0

@Deep Почему вы так думаете? Если вы сохраняете только два раза, у вас не будет рекурсии –

+0

Поскольку свойства (значение, существует) не могут быть основными/ведущими для режима сохранения – Deep

0

Ваша недвижимость метод сохранения (вы должны определить константы свойств для него):

public function save($mode = Property::SAVE_DEFAULT) 
{ 
    switch ($mode) { 
     case Property::SAVE_FOO: 
      // something for foo 
     break; 
     case Property::SAVE_BAR: 
      // something for bar 
     break; 
     default: 
      parent::save(); 
     break; 
    } 
} 

Назовите это:

public function fire($event) 
{ 
    $property = $event; 
    ... 
    //get GPS data from Google Maps 

    $property->latitude = $googleMapsObject->latitude; 
    $property->longitude = $googleMapsObject->longitude; 
    $property->save(Property::SAVE_FOO); 
} 

или

$property->save(); // as default 

Что хорошего? Все условия находятся в одном месте (в режиме сохранения).

+0

Извините, вы имеете в виду, что я должен написать непосредственно в БД вместо '// что-то для foo'? – ademin

+0

Да, почему бы и нет? Вы сами пришли к рекурсии. У вас есть два пути: 1) переписать без рекурсии 2) переопределить метод сохранения и записать в него все, что необходимо. – Deep

+0

Я не знаю, это не похоже на решение, это больше похоже на хак. Я ожидал, что могу создать пользовательское событие или передать некоторые аргументы с событием ... – ademin

0

Пользователь может установить forget(), чтобы отключить прослушиватель событий.

Event::listen('a', function(){ 
    Event::forget('a'); 

    echo 'update a '; 
    event("b"); 
}); 

Event::listen('b', function(){ 
    Event::forget('b'); 

    echo 'update b '; 
    event("a"); 
}); 

event("a"); // update a update b 

Клавиши модели событий названы «eloquent.{$event}: {$name}», например, «eloquent.updated: Foo»

Смежные вопросы