Skip to content

3. Custom Database Driver

Warrick Bayman edited this page Apr 12, 2021 · 2 revisions

Deadbolt comes with a default ArrayDriver class that simply sources permissions and roles from the default deadbolt.php config file. If you want to store permissions in a database table then you can write your own DatabaseDriver for Deadbolt.

For this example, we'll implement a DatabaseDeadboltDriver class that will source permissions from a permissions table in our database. We won't worry about groups right now, but once permissions are implemented, you'll see that groups would be quite simple.

Implementing

Our DatabaseDeadboltDriver class should implement DriverInterface to ensure we cover all the basics. The interface requires that we implement a permissions(...$roles): array method and a groups(): array method. Both methods must return an array, and the permissions method can filter the returned permissions by the names of the specified groups. The groups method can just return an empty array for now.

<?php

namespace App\Drivers;

use App\Group;
use App\Permission;
use TPG\Deadbolt\Drivers\Contracts\DriverInterface;

class EloquentDriver implements DriverInterface
{
    public function permissions(...$groups): array
    {
        return [];
    }

    public function groups(): array
    {
        return [];
    }
}

We now that we want to store our permissions in a permissions database table, so lets create that migration:

public function up()
{
    Schema::create('permissions', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('description')->nullable();
        $table->timestamps();
    });
}

You can fill the table with permissions, but for our example, we'll just seed the database with the following:

Permission:create(['name' => 'articles.create', 'description' => 'Create Articles']);
Permission:create(['name' => 'articles.edit', 'description' => 'Edit Articles']);
Permission:create(['name' => 'articles.delete', 'description' => 'Delete Articles']);

The permissions method in our driver needs to return an array of permissions. Each array element is keyed by the name of the permission and the value is the description. Taking the example permissions we have, we should get this from the method:

[
    'articles.create' => 'Create Articles',
    'articles.edit' => 'Edit Articles',
    'articles.delete' => 'Delete Articles',
]

To get this right, we'll grab the permissions from the database, which will come in as a Collection instance. We can then tell the collection to key by the name attribute and return the whole thing as an array:

public function permissions(...$groups): array
{
    return DB::table('permissions')
        ->select('name', 'description')
        ->get()
        ->keyBy('name')
        ->toArray();
}

Now update the deadbolt.php config to make use our new driver. Change the driver config option to look something like this:

return [

    'driver' => App\Drivers\DatabaseDeadboltDriver::class,

];

Now when you source permissions using Deadbolt, they'll come from the database table. Let's make one more change so that permissions are cached from the database. That way we don't need to make another DB query every time we want to get the permissions.

    public function permissions(...$groups): array
    {
        return Cache::remember('permissions', 3600, function () {
            return DB::table('permissions')->select('name', 'description')
                ->get()
                ->keyBy('name')
                ->toArray();
        });
    }

Thats it! You can now implement groups as well. You could have a groups table that has a many-to-many relationship with the permissions table, or maybe the name of the group is just a string column on the permissions table. It's up to you.

Clone this wiki locally