-
Notifications
You must be signed in to change notification settings - Fork 2
3. Custom Database Driver
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.
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.