Making a list you can check twice: A yule log

By
Christ Tyler

Here at liquidfish, our developers are like a family. Like a family, we help each other out. In much the same way, developers the world over are one big extended family. Sure, we have our disagreements, we don't always see eye-to-eye, but for the most part we help each other. So when I needed to find a good way to make Laravel log to the database, I went looking for help. And wow but that extended family made it harder than it needed to be! Laravel is a very extensible framework; that's why we like it. It comes pre-built with logging tools, models, and plenty of other goodies to make a developer happy. Laravel uses Monolog for most of its logging needs, which can write to whatever channel you care to set up. So why is logging to the database not built in? I couldn't say, but it turns out it's actually super simple! No need for a store-bought package with gimmicky settings; the best gifts are often homemade.

#How to: The meat of the yuletide feast

So, you're ready for the recipe for my super-simple database log?

You'll need: 1 Model class

1 AbstractProcessingHandler class

1 migration and a dash of setting spices.

The Model:


namespace App\Logging;
use Illuminate\Database\Eloquent\Model;
class Log extends Model
{
    protected $fillable = ['message','context','level','level_name','extra'];
    protected $casts = ['context'=>'array','extra'=>'array'];
}

The AbstractProcessingHandler:


namespace App\Logging;
use Monolog\Handler\AbstractProcessingHandler;
class MonoLogDBHandler extends AbstractProcessingHandler
{
    protected function write(array $record)
    {
        $log = new Log($record);
        $log->save();
    }
}

The Migration:


Schema::create('logs', function (Blueprint $table) {
    $table->increments('id');
    $table->string('message');
    $table->text('context');
    $table->smallInteger('level');
    $table->string('level_name',50);
    $table->text('extra');
    $table->timestamps();
});

And finally, settings: In your `config/logging.php` you'll find a list of channels. Here's what our new db channel looks like:


'db' => [
    'driver' => 'monolog',
    'with'=>['level' => \Monolog\Logger::DEBUG],
    'handler' => \App\Logging\MonoLogDBHandler::class,
], 

Now we can use the db channel for all our logging. To use it by default, we can either set the 'default' channel to db, or (my preference) use the 'stack' channel which logs to multiple channels and then add the db channel to the stack. Easy as mincemeat pie!

#Wrapping it up: Santa's little helpers

Now we just have to write to the log:


Log::info('Little Johnny',['Nice'=>true]);
Log::info('Cindy Lue Who',['Nice'=>true]);
Log::warning('The Grinch',['Nice'=>false]);

Now that's the makings of a happy yule log!