Basic Seeder Structure
Create a seeder using Artisan:php artisan make:seeder RoleAndPermissionSeeder
Simple Seeder Example
database/seeders/RoleAndPermissionSeeder.php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RoleAndPermissionSeeder extends Seeder
{
public function run(): void
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create permissions
Permission::create(['name' => 'view posts']);
Permission::create(['name' => 'create posts']);
Permission::create(['name' => 'edit posts']);
Permission::create(['name' => 'delete posts']);
// Create roles and assign permissions
$role = Role::create(['name' => 'writer']);
$role->givePermissionTo(['view posts', 'create posts', 'edit posts']);
$role = Role::create(['name' => 'admin']);
$role->givePermissionTo(Permission::all());
}
}
Best Practices
1. Reset Cache Before Seeding
Always reset the permission cache at the start of your seeder to avoid stale data.
public function run(): void
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Your seeder logic...
}
2. Use findOrCreate for Idempotent Seeders
Make your seeders idempotent (can run multiple times safely):public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Use findOrCreate instead of create
$viewPosts = Permission::findOrCreate('view posts');
$editPosts = Permission::findOrCreate('edit posts');
$deletePosts = Permission::findOrCreate('delete posts');
$admin = Role::findOrCreate('admin');
$admin->syncPermissions([$viewPosts, $editPosts, $deletePosts]);
}
3. Organize by Resource
Structure permissions logically by resource:public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Posts permissions
$postPermissions = [
'view posts',
'create posts',
'edit posts',
'delete posts',
];
// User permissions
$userPermissions = [
'view users',
'create users',
'edit users',
'delete users',
];
// Create all permissions
foreach (array_merge($postPermissions, $userPermissions) as $permission) {
Permission::findOrCreate($permission);
}
// Assign to roles
Role::findOrCreate('editor')->syncPermissions($postPermissions);
Role::findOrCreate('admin')->syncPermissions(Permission::all());
}
Advanced Seeder Patterns
Structured Permissions Array
database/seeders/RoleAndPermissionSeeder.php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RoleAndPermissionSeeder extends Seeder
{
public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
$permissions = [
'posts' => ['view', 'create', 'edit', 'delete', 'publish'],
'comments' => ['view', 'create', 'edit', 'delete', 'moderate'],
'users' => ['view', 'create', 'edit', 'delete', 'ban'],
'settings' => ['view', 'edit'],
];
// Create permissions
foreach ($permissions as $resource => $actions) {
foreach ($actions as $action) {
Permission::findOrCreate("{$action} {$resource}");
}
}
// Define role permissions
$rolePermissions = [
'super-admin' => Permission::all(),
'admin' => Permission::whereIn('name', [
'view posts', 'create posts', 'edit posts', 'delete posts',
'view users', 'edit users',
'view comments', 'moderate comments',
])->get(),
'editor' => Permission::whereIn('name', [
'view posts', 'create posts', 'edit posts', 'publish posts',
'view comments', 'moderate comments',
])->get(),
'writer' => Permission::whereIn('name', [
'view posts', 'create posts', 'edit posts',
])->get(),
];
// Create roles and assign permissions
foreach ($rolePermissions as $roleName => $permissions) {
$role = Role::findOrCreate($roleName);
$role->syncPermissions($permissions);
}
}
}
CRUD Pattern Helper
database/seeders/RoleAndPermissionSeeder.php
class RoleAndPermissionSeeder extends Seeder
{
private function createCrudPermissions(string $resource): array
{
$actions = ['view', 'create', 'edit', 'delete'];
$permissions = [];
foreach ($actions as $action) {
$permissions[] = Permission::findOrCreate("{$action} {$resource}");
}
return $permissions;
}
public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create CRUD permissions for multiple resources
$postPermissions = $this->createCrudPermissions('posts');
$userPermissions = $this->createCrudPermissions('users');
$commentPermissions = $this->createCrudPermissions('comments');
// Create roles
Role::findOrCreate('admin')->syncPermissions(Permission::all());
Role::findOrCreate('editor')->syncPermissions(array_merge(
$postPermissions,
$commentPermissions
));
}
}
Seeding with Guards
When using multiple guards, specify the guard for each permission:public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Web guard permissions
Permission::findOrCreate('view dashboard', 'web');
Permission::findOrCreate('edit profile', 'web');
// Admin guard permissions
Permission::findOrCreate('manage users', 'admin');
Permission::findOrCreate('view logs', 'admin');
// API guard permissions
Permission::findOrCreate('access api', 'api');
Permission::findOrCreate('write api', 'api');
// Create roles with guards
$webAdmin = Role::findOrCreate('admin', 'web');
$webAdmin->givePermissionTo(['view dashboard', 'edit profile']);
$superAdmin = Role::findOrCreate('super-admin', 'admin');
$superAdmin->givePermissionTo(['manage users', 'view logs']);
}
Seeding with Teams
For multi-tenant applications using teams:public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create permissions (not team-specific)
Permission::findOrCreate('edit posts');
Permission::findOrCreate('delete posts');
Permission::findOrCreate('manage team');
// Create global roles (available to all teams)
$superAdmin = Role::create([
'name' => 'super-admin',
'team_id' => null, // Global role
]);
$superAdmin->givePermissionTo(Permission::all());
// Create team-specific roles
$teams = \App\Models\Team::all();
foreach ($teams as $team) {
setPermissionsTeamId($team->id);
$admin = Role::create([
'name' => 'admin',
'team_id' => $team->id,
]);
$admin->givePermissionTo(['edit posts', 'delete posts', 'manage team']);
$editor = Role::create([
'name' => 'editor',
'team_id' => $team->id,
]);
$editor->givePermissionTo(['edit posts']);
}
// Reset team context
setPermissionsTeamId(null);
}
Assigning Roles to Users
database/seeders/UserSeeder.php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class UserSeeder extends Seeder
{
public function run(): void
{
// Create admin user
$admin = User::create([
'name' => 'Admin User',
'email' => '[email protected]',
'password' => bcrypt('password'),
]);
$admin->assignRole('super-admin');
// Create editor users
User::factory()
->count(5)
->create()
->each(fn ($user) => $user->assignRole('editor'));
// Create writer users
User::factory()
->count(10)
->create()
->each(fn ($user) => $user->assignRole('writer'));
}
}
Wildcard Permissions
If using wildcard permissions, create them in your seeder:public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create specific permissions
Permission::findOrCreate('posts.view');
Permission::findOrCreate('posts.create');
Permission::findOrCreate('posts.edit');
Permission::findOrCreate('posts.delete');
// Create wildcard permissions
Permission::findOrCreate('posts.*');
Permission::findOrCreate('admin.*');
Permission::findOrCreate('*.*'); // Super permission
// Assign wildcards to roles
Role::findOrCreate('admin')->givePermissionTo('admin.*');
Role::findOrCreate('super-admin')->givePermissionTo('*.*');
}
Running Seeders
Run Specific Seeder
php artisan db:seed --class=RoleAndPermissionSeeder
Add to DatabaseSeeder
database/seeders/DatabaseSeeder.php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
RoleAndPermissionSeeder::class,
UserSeeder::class,
]);
}
}
php artisan db:seed
Fresh Migration with Seed
php artisan migrate:fresh --seed
Performance Tips
Disable Events During Seeding
Disable Events During Seeding
Events can slow down bulk operations:
public function run(): void
{
// Disable events
config(['permission.events_enabled' => false]);
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Your seeding logic...
// Re-enable if needed
config(['permission.events_enabled' => true]);
}
Use Bulk Inserts for Large Datasets
Use Bulk Inserts for Large Datasets
For hundreds of permissions, use database bulk inserts:
use Illuminate\Support\Facades\DB;
public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
$permissions = [];
$timestamp = now();
foreach (['posts', 'users', 'comments'] as $resource) {
foreach (['view', 'create', 'edit', 'delete'] as $action) {
$permissions[] = [
'name' => "{$action} {$resource}",
'guard_name' => 'web',
'created_at' => $timestamp,
'updated_at' => $timestamp,
];
}
}
DB::table('permissions')->insertOrIgnore($permissions);
}
Cache Warming
Cache Warming
Warm up the cache after seeding:
public function run(): void
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Your seeding logic...
// Warm up cache
Permission::all(); // Triggers cache build
}
Testing Your Seeders
tests/Feature/RoleSeederTest.php
namespace Tests\Feature;
use Database\Seeders\RoleAndPermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class RoleSeederTest extends TestCase
{
use RefreshDatabase;
public function test_seeder_creates_all_roles(): void
{
$this->seed(RoleAndPermissionSeeder::class);
$this->assertDatabaseHas('roles', ['name' => 'admin']);
$this->assertDatabaseHas('roles', ['name' => 'editor']);
$this->assertDatabaseHas('roles', ['name' => 'writer']);
}
public function test_admin_has_all_permissions(): void
{
$this->seed(RoleAndPermissionSeeder::class);
$admin = Role::findByName('admin');
$permissionCount = Permission::count();
$this->assertCount($permissionCount, $admin->permissions);
}
public function test_seeder_is_idempotent(): void
{
$this->seed(RoleAndPermissionSeeder::class);
$firstCount = Role::count();
// Run again
$this->seed(RoleAndPermissionSeeder::class);
$secondCount = Role::count();
$this->assertEquals($firstCount, $secondCount);
}
}
Common Patterns
Define Permission Structure
Create a clear structure for your permissions, organized by resource and action.
Example: Complete Seeder
database/seeders/RoleAndPermissionSeeder.php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RoleAndPermissionSeeder extends Seeder
{
public function run(): void
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Define permissions by resource
$resources = [
'posts' => ['view', 'create', 'edit', 'delete', 'publish'],
'comments' => ['view', 'create', 'edit', 'delete', 'approve'],
'users' => ['view', 'create', 'edit', 'delete'],
'roles' => ['view', 'create', 'edit', 'delete'],
'settings' => ['view', 'edit'],
];
// Create all permissions
$allPermissions = [];
foreach ($resources as $resource => $actions) {
foreach ($actions as $action) {
$permission = Permission::findOrCreate("{$action} {$resource}");
$allPermissions[] = $permission;
}
}
// Create roles with specific permissions
Role::findOrCreate('super-admin')
->syncPermissions($allPermissions);
Role::findOrCreate('admin')
->syncPermissions([
'view posts', 'create posts', 'edit posts', 'delete posts',
'view users', 'create users', 'edit users',
'view comments', 'approve comments',
]);
Role::findOrCreate('editor')
->syncPermissions([
'view posts', 'create posts', 'edit posts', 'publish posts',
'view comments', 'edit comments',
]);
Role::findOrCreate('writer')
->syncPermissions([
'view posts', 'create posts', 'edit posts',
]);
// Create initial admin user
$admin = User::firstOrCreate(
['email' => '[email protected]'],
[
'name' => 'Super Admin',
'password' => bcrypt('password'),
]
);
$admin->assignRole('super-admin');
}
}