sustained
1 year ago

Register dynamic model events from static trait boot method.

Posted 1 year ago by sustained

In episode 25 of Let's Build a Forum with TDD we start working on adding an activity feed.

After we get our tests passing, we extract the code to a trait which we can use in all of our models.

The trait looks something like this:

<?php

namespace App;

trait RecordsActivity
{
    protected static function bootRecordsActivity()
    {
        static::created(function ($model) {
            $model->record('created');
        });
    }

    public function activities()
    {
        return $this->morphMany(Activity::class, 'subject');
    }

    public function record($eventName)
    {
        $this->activities()->create([
            'action' => $eventName,
            'user_id' => auth()->id(),
            'subject_id' => $this->id,
            'subject_type' => get_class($this)
        ]);
    }
}

Now I figured I could take this slightly further so first I added this to my Thread model:

    protected static $activities = [
        'created'
    ];

Next I modify bootRecordsActivity:

    protected static function bootRecordsActivity()
    {
        foreach (static::$activities as $eventName) {
            static::$eventName(function ($model) {
                $model->record($eventName);
            });
        }
    }

But this doesn't work as expected.

It's looking for a static::$eventName property in the Thread model but I instead want to call a static method (static::created) dynamically. I then tried static::{$eventName} but no dice.

Is there a clean way to achieve this? I'm pretty new to PHP (well, it's been many years).

I tried googling and attempted some stuff with get_called_class and such but didn't have any luck.

Thanks!

Please sign in or create an account to participate in this conversation.