In your apps there's probably a lot going on. Users log in and out, they create, update and delete content, mails get sent and so on. For an administrator of an app these events provide useful insights. In almost every project we make at Spatie we log these events and show them in the admin-section of our site. Here's how that looks like in our Laravel template called Blender.

log

We made a new package called laravel-activitylog that makes logging activities in a Laravel app a cinch. In this blogpost I'd like to walk you through it.

Basic logging

This is the most basic way to log some activity:

activity()->log('Look mum, I logged something');

This will write a record in the activity_log table. You can retrieve activity using the Spatie\Activitylog\Models\Activity model that the package provides.

$lastActivity = Activity::all()->last(); //returns the last logged activity

$lastActivity->description; //returns 'Look mum, I logged something';

You can specify on which object the activity is performed by using performedOn:

activity()
   ->performedOn($someContentModel)
   ->log('edited');

$lastActivity = Activity::all()->last(); //returns the last logged activity

$lastActivity->subject; //returns the model that was passed to `performedOn`;

You can set who or what caused the activity by using causedBy:

activity()
   ->causedBy($userModel)
   ->performedOn($someContentModel)
   ->log('edited');

$lastActivity = Activity::all()->last(); //returns the last logged activity

$lastActivity->causer; //returns the model that was passed to `causedBy`;   

If you're not using causedBy the package will automatically use the logged in user.

Automatic model event logging

A neat feature of this package is that it can automatically log events such as when a model is created, updated and deleted. To make this work all you need to do is let your model use the Spatie\Activitylog\Traits\LogsActivity-trait.

As a bonus the package will also log the changed attributes for all these events when setting $logAttributes property on the model.

Here's an example:

use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\Traits\LogsActivity;

class NewsItem extends Model
{
    use LogsActivity;

    protected $fillable = ['name', 'text'];

    protected static $logAttributes = ['name', 'text'];
}

Let's see what gets logged when creating an instance of that model.

$newsItem = NewsItem::create([
   'name' => 'original name',
   'text' => 'Lorum'
]);

//creating the newsItem will cause an activity being logged
$activity = Activity::all()->last();

$activity->description; //returns 'created'
$activity->subject; //returns the instance of NewsItem that was created
$activity->changes; //returns ['attributes' => ['name' => 'original name', 'text' => 'Lorum']];

Now let's update some that $newsItem.

$newsItem->name = 'updated name'
$newsItem->save();

//updating the newsItem will cause an activity being logged
$activity = Activity::all()->last();

$activity->description; //returns 'updated'
$activity->subject; //returns the instance of NewsItem that was created

Calling $activity->changes will return this array:

[
   'attributes' => [
        'name' => 'original name',
        'text' => 'Lorum',
    ],
    'old' => [
        'name' => 'updated name',
        'text' => 'Lorum',
    ],
];

Pretty cool, right?

Now, what happens when you call delete?

$newsItem->delete();

//deleting the newsItem will cause an activity being logged
$activity = Activity::all()->last();

$activity->description; //returns 'deleted'
$activity->changes; //returns ['attributes' => ['name' => 'updated name', 'text' => 'Lorum']];

Read the documentation on event logging to learn how to choose the events that must be logged, how to customize the description for an event, and how to specify the attributes of which the changes must be logged.

Using multiple logs

When not specify a log name the activities will be logged on the default log.

activity()->log('hi');

$lastActivity = Spatie\Activitylog\Models\Activity::all()->last();

$lastActivity->log_name; //returns 'default', this value can be changed in the config file ;

You can specify the log on which an activity must be logged by passing the log name to the activity function:

activity('other-log')->log("hi");

Activity::all()->last()->log_name; //returns 'other-log';

Like mentioned before Activity model is just a regular Eloquent model that you know and love. So you can just use a where on it.

Activity::where('log_name' , 'other-log')->get(); //returns all activity from the 'other-log'

The package also provides an inLog scope you can use:

Activity::inLog('other-log')->get();

//you can pass multiple log names to the scope
Activity::inLog('default', 'other-log')->get();

//passing an array is just as good
Activity::inLog(['default', 'other-log'])->get();

This concludes the tour of laravel-activitylog. Want to know more about the package, then head over to the documentation to learn all the options. If you find this package useful, be sure to take a look at the Laravel packages we previous made.