---
title: "Custom models & tables — Permissions for Laravel | Roundly"
description: "Swap in your own Role and Permission subclasses, rename the tables, and resolve the configured setup in code."
url: https://roundly-consulting.com/open-source/docs/permissions-for-laravel/custom-models
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Permissions for Laravel](https://roundly-consulting.com/open-source/docs/permissions-for-laravel.md)

# Custom models & tables

Both models are non-final and resolved through config everywhere — never by a hard-coded class name. Extend them to add your own relations, scopes or casts:

```php
namespace App\Models;

use RoundlyConsulting\Permissions\Models\Role as BaseRole;

class Role extends BaseRole
{
    // your own relations, scopes, casts …
}
```

```php
// config/permissions.php
'models' => [
    'role' => App\Models\Role::class,
    'permission' => App\Models\Permission::class,
],
```

Permissions::role(), Permissions::permission(), every grant and every relation then use your class. Because rows are created as your class, your model events and observers fire — and the package’s cache invalidation hooks onto your model too:

```php
use RoundlyConsulting\Permissions\Facades\Permissions;

$role = Permissions::role('editor');  // an App\Models\Role instance
Permissions::roleModel();             // App\Models\Role::class
Permissions::roleModel()::query();    // a query on your class
$user->roles;                         // Collection<App\Models\Role>
```

A configured class must be the packaged Role or Permission or a subclass of it. Anything else — an Eloquent model that does not extend it, or a value that is not a model at all — throws InvalidConfigurationException naming the key; it is never silently replaced by the packaged model.

## Table names

Rename any table in table\_names before you migrate — column names are fixed:

```php
// config/permissions.php
'table_names' => [
    'roles' => 'acl_roles',
    'permissions' => 'acl_permissions',
    'permission_role' => 'acl_permission_role',
    'model_roles' => 'acl_model_roles',
    'model_permissions' => 'acl_model_permissions',
],
```

## Resolving the setup in code

For the model classes, Permissions::roleModel() and permissionModel() are enough. The static resolvers on PermissionRegistrar also expose the resolved tables and key type — the published migrations call them, and so can your raw queries and own migrations:

```php
use RoundlyConsulting\Permissions\Support\PermissionRegistrar;

PermissionRegistrar::roleModel();              // configured Role class-string
PermissionRegistrar::permissionModel();        // configured Permission class-string

PermissionRegistrar::rolesTable();             // resolved table names
PermissionRegistrar::permissionsTable();
PermissionRegistrar::permissionRoleTable();
PermissionRegistrar::modelRolesTable();
PermissionRegistrar::modelPermissionsTable();

PermissionRegistrar::keyType();                // KeyType enum — BigInt, Uuid or Ulid
```

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/permissions-for-laravel.md)
