Database Seeding | laravel-permission | Spatie

   [Docs](https://spatie.be/docs)  [Laravel-permission](https://spatie.be/docs/laravel-permission/v6)  Advanced-usage  Database Seeding

 Version   v7   v6   v5   v4   v3

 Other versions for crawler [v7](https://spatie.be/docs/laravel-permission/v7) [v6](https://spatie.be/docs/laravel-permission/v6) [v5](https://spatie.be/docs/laravel-permission/v5) [v4](https://spatie.be/docs/laravel-permission/v4) [v3](https://spatie.be/docs/laravel-permission/v3)

- [ Introduction ](https://spatie.be/docs/laravel-permission/v6/introduction)
- [ Support us ](https://spatie.be/docs/laravel-permission/v6/support-us)
- [ Prerequisites ](https://spatie.be/docs/laravel-permission/v6/prerequisites)
- [ Installation in Laravel ](https://spatie.be/docs/laravel-permission/v6/installation-laravel)
- [ Installation in Lumen ](https://spatie.be/docs/laravel-permission/v6/installation-lumen)
- [ Upgrading ](https://spatie.be/docs/laravel-permission/v6/upgrading)
- [ Questions and issues ](https://spatie.be/docs/laravel-permission/v6/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-permission/v6/changelog)
- [ About us ](https://spatie.be/docs/laravel-permission/v6/about-us)

Basic Usage
-----------

- [ Basic Usage ](https://spatie.be/docs/laravel-permission/v6/basic-usage/basic-usage)
- [ Direct Permissions ](https://spatie.be/docs/laravel-permission/v6/basic-usage/direct-permissions)
- [ Using Permissions via Roles ](https://spatie.be/docs/laravel-permission/v6/basic-usage/role-permissions)
- [ Enums ](https://spatie.be/docs/laravel-permission/v6/basic-usage/enums)
- [ Teams permissions ](https://spatie.be/docs/laravel-permission/v6/basic-usage/teams-permissions)
- [ Wildcard permissions ](https://spatie.be/docs/laravel-permission/v6/basic-usage/wildcard-permissions)
- [ Blade directives ](https://spatie.be/docs/laravel-permission/v6/basic-usage/blade-directives)
- [ Defining a Super-Admin ](https://spatie.be/docs/laravel-permission/v6/basic-usage/super-admin)
- [ Using multiple guards ](https://spatie.be/docs/laravel-permission/v6/basic-usage/multiple-guards)
- [ Artisan Commands ](https://spatie.be/docs/laravel-permission/v6/basic-usage/artisan)
- [ Middleware ](https://spatie.be/docs/laravel-permission/v6/basic-usage/middleware)
- [ Passport Client Credentials Grant usage ](https://spatie.be/docs/laravel-permission/v6/basic-usage/passport)
- [ Example App ](https://spatie.be/docs/laravel-permission/v6/basic-usage/new-app)

Best Practices
--------------

- [ Roles vs Permissions ](https://spatie.be/docs/laravel-permission/v6/best-practices/roles-vs-permissions)
- [ Model Policies ](https://spatie.be/docs/laravel-permission/v6/best-practices/using-policies)
- [ Performance Tips ](https://spatie.be/docs/laravel-permission/v6/best-practices/performance)

Advanced usage
--------------

- [ Testing ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/testing)
- [ Database Seeding ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/seeding)
- [ Exceptions ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/exceptions)
- [ Extending ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/extending)
- [ Cache ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/cache)
- [ Events ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/events)
- [ Custom Permission Check ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/custom-permission-check)
- [ UUID/ULID ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/uuid)
- [ PhpStorm Interaction ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/phpstorm)
- [ Other ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/other)
- [ Timestamps ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/timestamps)
- [ UI Options ](https://spatie.be/docs/laravel-permission/v6/advanced-usage/ui-options)

      You are viewing the documentation for **an older version** of this package. You can check the version you are using with the following command:

 `                                    composer show spatie/laravel-permission                                                                                                                                                                                                                                    `

Database Seeding
================

###  On this page

1. [ Flush cache before/after seeding ](#content-flush-cache-beforeafter-seeding)
2. [ Database Cache Store ](#content-database-cache-store)
3. [ Roles/Permissions Seeder ](#content-rolespermissions-seeder)
4. [ User Seeding with Factories and States ](#content-user-seeding-with-factories-and-states)
5. [ Speeding up seeding for large data sets ](#content-speeding-up-seeding-for-large-data-sets)

Flush cache before/after seeding
------------------------------------------------------------------------------------------------------------------------------------------------------

You may discover that it is best to flush this package's cache **BEFORE seeding, to avoid cache conflict errors**.

And if you use the `WithoutModelEvents` trait in your seeders, flush it **AFTER creating any roles/permissions as well, before assigning or granting them**.

```
// reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
```

You can optionally flush the cache before seeding by using the `SetUp()` method of your test suite (see the Testing page in the docs).

Or it can be done directly in a seeder class, as shown below.

Database Cache Store
--------------------------------------------------------------------------------------------------------------------

TIP: If you have `CACHE_STORE=database` set in your `.env`, remember that [you must install Laravel's cache tables via a migration before performing any cache operations](https://laravel.com/docs/cache#prerequisites-database). If you fail to install those migrations, you'll run into errors like `Call to a member function perform() on null` when the cache store attempts to purge or update the cache. This package does strategic cache resets in various places, so may trigger that error if your app's cache dependencies aren't set up.

Roles/Permissions Seeder
------------------------------------------------------------------------------------------------------------------------------

Here is a sample seeder, which first clears the cache, creates permissions and then assigns permissions to roles (the order of these steps is intentional):

```
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class RolesAndPermissionsSeeder extends Seeder
{
    public function run(): void
    {
        // Reset cached roles and permissions
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

        // create permissions
        Permission::create(['name' => 'edit articles']);
        Permission::create(['name' => 'delete articles']);
        Permission::create(['name' => 'publish articles']);
        Permission::create(['name' => 'unpublish articles']);

        // update cache to know about the newly created permissions (required if using WithoutModelEvents in seeders)
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

        // create roles and assign created permissions

        // this can be done as separate statements
        $role = Role::create(['name' => 'writer']);
        $role->givePermissionTo('edit articles');

        // or may be done by chaining
        $role = Role::create(['name' => 'moderator'])
            ->givePermissionTo(['publish articles', 'unpublish articles']);

        $role = Role::create(['name' => 'super-admin']);
        $role->givePermissionTo(Permission::all());
    }
}
```

User Seeding with Factories and States
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

To use Factory States to assign roles after creating users:

```
// Factory:
    public function definition() {...}

    public function active(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => 1,
            ])
            ->afterCreating(function (User $user) {
                $user->assignRole('ActiveMember');
            });
    }

// Seeder:
// To create 4 users using this 'active' state in a Seeder:
User::factory(4)->active()->create();
```

To seed multiple users and then assign each of them a role, WITHOUT using Factory States:

```
// Seeder:
User::factory()
    ->count(50)
    ->create()
    ->each(function ($user) {
        $user->assignRole('Member');
    });
```

Speeding up seeding for large data sets
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

When seeding large quantities of roles or permissions you may consider using Eloquent's `insert` command instead of `create`, as this bypasses all the internal checks that this package does when calling `create` (including extra queries to verify existence, test guards, etc).

```
    $arrayOfPermissionNames = ['writer', 'editor'];
    $permissions = collect($arrayOfPermissionNames)->map(function ($permission) {
        return ['name' => $permission, 'guard_name' => 'web'];
    });

    Permission::insert($permissions->toArray());
```

Alternatively you could use `DB::insert`, as long as you also provide all the required data fields. One example of this is shown below ... but note that this example hard-codes the table names and field names, thus does not respect any customizations you may have in your permissions config file.

```
$permissionsByRole = [
    'admin' => ['restore posts', 'force delete posts'],
    'editor' => ['create a post', 'update a post', 'delete a post'],
    'viewer' => ['view all posts', 'view a post']
];

$insertPermissions = fn ($role) => collect($permissionsByRole[$role])
    ->map(fn ($name) => DB::table('permissions')->insertGetId(['name' => $name, 'guard_name' => 'web']))
    ->toArray();

$permissionIdsByRole = [
    'admin' => $insertPermissions('admin'),
    'editor' => $insertPermissions('editor'),
    'viewer' => $insertPermissions('viewer')
];

foreach ($permissionIdsByRole as $role => $permissionIds) {
    $role = Role::whereName($role)->first();

    DB::table('role_has_permissions')
        ->insert(
            collect($permissionIds)->map(fn ($id) => [
                'role_id' => $role->id,
                'permission_id' => $id
            ])->toArray()
        );
}

// and also add the command to flush the cache again now after doing all these inserts
```

**CAUTION**: ANY TIME YOU DIRECTLY RUN DB QUERIES you are bypassing cache-control features. So you will need to manually flush the package cache AFTER running direct DB queries, even in a seeder.
