13

Currently I am using observers to handle some stuff after creation and updating of my models.

I want to update my app by making it real-time using but I am not able to find documentation regarding the use of in combination with observers (instead of events).

You can use events and their broadcast functionality in combination with their respective listeners to get this functionality but I like the more clean code of observers (less "magic").

Looking at the code of the laravel framework I can see that the observable still uses eloquent events so I do suspect that there is a way to broadcast these.

So my question: is there a way to broadcast eloquent events using without creating individual events or manually adding broadcast statements on every event?

milo526
  • 5,012
  • 5
  • 41
  • 60
  • I am in the same position now.I tried to implement ShouldBroadcast in observer but no luck. Did you find any solution with less magic? – effe Sep 21 '17 at 11:11
  • I would say you can't. But you could write a dynamic event, that will deal with all your observers. If you give us a more concrete example for what you want to achieve we could find a solution. For example you could write and event, that will get all changes from the called observer and pass it to a broadcast channel. – cre8 Sep 21 '17 at 21:26
  • 1
    After a quick look at the code, it looks like for model events, the model is treated as the event that is dispatched, so try adding the `ShouldBroadcast` interface to your model, and define the `broadcastOn()` method to implement the interface. This is untested, so let us know if that does what you're looking for. – patricus Sep 22 '17 at 06:09
  • @mimo My current project has some observers that handle eloquent events (created, saved etc) I need to broadcast the models with their current state. – milo526 Sep 26 '17 at 10:50
  • Are you trying to broadcast all model events? Or just certain events on certain models? – mr_carrera Sep 29 '17 at 19:09

1 Answers1

6

Interesting question! We can create a reusable, general-purpose observer that broadcasts events fired from the models that it observes. This removes the need to create individual events for each scenario, and we can continue to use existing observers:

class BroadcastingModelObserver 
{ 
    public function created(Model $model) 
    {
        event(new BroadcastingModelEvent($model, 'created'));
    }

    public function updated(Model $model) { ... }
    public function saved(Model $model) { ... }
    public function deleted(Model $model) { ... }
}

class BroadcastingModelEvent implements ShouldBroadcast 
{
    public $model; 
    public $eventType;

    public function __construct(Model $model, $eventType) 
    {
        $this->model = $model; 
        $this->eventType = $eventType;
    }

    public function broadcastOn() { ... }
}

Then, simply instruct the observer to observe any models that you need to broadcast events to Echo for:

User::observe(BroadcastingModelObserver::class);
Post::observe(BroadcastingModelObserver::class); 
...

As you know, multiple observers can observe the same model. This is a very simple example. We can do a lot of neat things with this pattern. For instance, we could declare which attributes we want to broadcast on each model and configure the event to filter out any that the model doesn't explicitly allow. Each model might also declare the channel that the event publishes to or the type of events that it should broadcast.

Alternatively, we could broadcast the event from your existing observers, but it sounds like you want to avoid adding these statements to each one.

Cy Rossignol
  • 16,216
  • 4
  • 57
  • 83