PHPackages                             mike-bronner/laravel-governor - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. mike-bronner/laravel-governor

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

mike-bronner/laravel-governor
=============================

Managing policy and control in Laravel.

0.22.0(3mo ago)20007[4 issues](https://github.com/mike-bronner/laravel-governor/issues)[3 PRs](https://github.com/mike-bronner/laravel-governor/pulls)MITPHPPHP ^8.2CI passing

Since Sep 2Pushed 1w ago7 watchersCompare

[ Source](https://github.com/mike-bronner/laravel-governor)[ Packagist](https://packagist.org/packages/mike-bronner/laravel-governor)[ GitHub Sponsors](https://github.com/mikebronner)[ RSS](/packages/mike-bronner-laravel-governor/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (10)Dependencies (8)Versions (204)Used By (0)

Governor For Laravel
====================

[](#governor-for-laravel)

[![Tests](https://github.com/mikebronner/laravel-governor/actions/workflows/tests.yml/badge.svg)](https://github.com/mikebronner/laravel-governor/actions/workflows/tests.yml)[![codecov](https://camo.githubusercontent.com/324a452467b6f83b8769b440ed9bedfe4ac1511c94c7d7eda9eb1e197b845188/68747470733a2f2f636f6465636f762e696f2f67682f6d696b6562726f6e6e65722f6c61726176656c2d676f7665726e6f722f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/mikebronner/laravel-governor)[![Latest StableVersion](https://camo.githubusercontent.com/b9adc4fb319a41279cb848afe4524f94250caf7535a29cf9930d4e5173c677d6/68747470733a2f2f706f7365722e707567782e6f72672f67656e65616c6162732f6c61726176656c2d676f7665726e6f722f762f737461626c652e706e67)](https://packagist.org/packages/genealabs/laravel-governor)[![Total Downloads](https://camo.githubusercontent.com/13c173bf166c4412987eedcb805928a5eba1cf2cf2ed67cd547b20ab8d3f1e01/68747470733a2f2f706f7365722e707567782e6f72672f67656e65616c6162732f6c61726176656c2d676f7665726e6f722f646f776e6c6f6164732e706e67)](https://packagist.org/packages/genealabs/laravel-governor)

[![Governor for Laravel](https://repository-images.githubusercontent.com/41706753/37d93d00-f1b1-11e9-9f67-067c80849466)](https://repository-images.githubusercontent.com/41706753/37d93d00-f1b1-11e9-9f67-067c80849466)

**Manage authorization with granular role-based permissions in your Laravel apps.**

[![screencast 2017-06-04 at 3 34 56 pm](https://cloud.githubusercontent.com/assets/1791050/26765962/fa085878-493b-11e7-9bb7-b4d9f88844a0.gif)](https://cloud.githubusercontent.com/assets/1791050/26765962/fa085878-493b-11e7-9bb7-b4d9f88844a0.gif)

Table of Contents
-----------------

[](#table-of-contents)

- [Goal](#goal)
- [Requirements](#requirements)
- [Installation](#installation)
- [Implementation](#implementation)
- [Upgrading](#upgrading)
- [Configuration](#configuration)
- [API Reference](#api-reference)
    - [Traits](#traits)
    - [Policies](#policies)
    - [Models](#models)
    - [Artisan Commands](#artisan-commands)
    - [REST API Endpoints](#rest-api-endpoints)
    - [Events](#events)
    - [Blade Components](#blade-components)
- [Examples](#examples)

Goal
----

[](#goal)

Provide a simple method of managing ACL in a Laravel application built on the Laravel Authorization functionality. By leveraging Laravel's native Authorization functionality there is no additional learning or implementation curve. All you need to know is Laravel, and you will know how to use Governor for Laravel.

Requirements
------------

[](#requirements)

LaravelPHPPackage10.x8.2+latest11.x8.2+latest12.x8.2+latest13.x8.3+latest### Additional Requirements

[](#additional-requirements)

- Bootstrap 3 (needs to be included in your layout file)
- FontAwesome 4 (needs to be included in your layout file)

Installation
------------

[](#installation)

The user with the lowest primary key will be set up as the SuperAdmin. If you're starting on a new project, be sure to add an initial user now. If you already have users, you can update the role-user entry to point to your intended user, if the first user is not the intended SuperAdmin. Now let's get the package installed.

Install via composer:

```
composer require genealabs/laravel-governor
```

Implementation
--------------

[](#implementation)

1. First we need to update the database by running the migrations and data seeders:

    ```
    php artisan migrate --path="vendor/genealabs/laravel-governor/database/migrations"
    php artisan db:seed --class=LaravelGovernorDatabaseSeeder
    ```
2. If you have seeders of your own, run them now:

    ```
    php artisan db:seed
    ```
3. Next, assign permissions (this requires you have users already populated):

    ```
    php artisan db:seed --class=LaravelGovernorPermissionsTableSeeder
    ```
4. Now we need to make the assets available:

    ```
    php artisan governor:publish --assets
    ```
5. Lastly, add the `Governing` trait to the User model of your app:

    ```
    use GeneaLabs\LaravelGovernor\Traits\Governing;

    class User extends Authenticatable
    {
        use Governing;
    }
    ```

    For non-User models that should be governed (have ownership tracking and permission-scoped queries), use the `Governable` trait instead:

    ```
    use GeneaLabs\LaravelGovernor\Traits\Governable;

    class BlogPost extends Model
    {
        use Governable;
    }
    ```

Upgrading
---------

[](#upgrading)

The following upgrade guides should help navigate updates with breaking changes.

### From 0.11.5+ to 0.12 \[Breaking\]

[](#from-0115-to-012-breaking)

The role\_user pivot table has replaced the composite key with a primary key, as Laravel does not fully support composite keys. Run:

```
php artisan db:seed --class="LaravelGovernorUpgradeTo0120"
```

### From 0.11 to 0.11.5 \[Breaking\]

[](#from-011-to-0115-breaking)

The primary keys of the package's tables have been renamed. (This should have been a minor version change, instead of a patch, as this was a breaking change.) Run:

```
php artisan db:seed --class="LaravelGovernorUpgradeTo0115"
```

### From 0.10 to 0.11 \[Breaking\]

[](#from-010-to-011-breaking)

The following traits have changed:

- `Governable` has been renamed to `Governing`.
- `Governed` has been renamed to `Governable`.
- the `governor_created_by` has been renamed to `governor_owned_by`. Run migrations to update your tables. ```
    php artisan db:seed --class="LaravelGovernorUpgradeTo0110"
    ```
- replace any reference in your app from `governor_created_by` to `governor_owned_by`.

### From 0.6 to Version 0.10 \[Breaking\]

[](#from-06-to-version-010-breaking)

To upgrade from version previous to `0.10.0`, first run the migrations and seeders, then run the update seeder:

```
php artisan migrate --path="vendor/genealabs/laravel-governor/database/migrations"
php artisan db:seed --class="LaravelGovernorDatabaseSeeder"
php artisan db:seed --class="LaravelGovernorUpgradeTo0100"
```

### to 0.6 \[Breaking\]

[](#to-06-breaking)

1. If you were extending `GeneaLabs\LaravelGovernor\Policies\LaravelGovernorPolicy`, change to extend `GeneaLabs\LaravelGovernor\Policies\BasePolicy`;
2. Support for version of Laravel lower than 5.5 has been dropped.

Configuration
-------------

[](#configuration)

Publish the configuration file if you need to customize defaults:

```
php artisan governor:publish --config
```

### Config Options

[](#config-options)

KeyTypeDefaultDescription`layout-view``string``'layouts.app'`Blade layout used to render Governor's built-in admin views. Must include Bootstrap 3 and FontAwesome 4.`content-section``string``'content'`Name of the `@yield` section in your layout where Governor renders page content.`auth-model-primary-key-type``string``'bigInteger'`Primary key type of your User model. Used when Governor adds the `governor_owned_by` column. Accepts `'integer'` or `'bigInteger'`.`models.auth``string``config('auth.providers.users.model')`Fully-qualified class name of your User model.`models.action``string``Action::class`Model class for actions. Override to extend the default.`models.assignment``string``Assignment::class`Model class for role assignments.`models.entity``string``Entity::class`Model class for entities.`models.group``string``Group::class`Model class for entity groups.`models.ownership``string``Ownership::class`Model class for ownership levels.`models.permission``string``Permission::class`Model class for permissions.`models.role``string``Role::class`Model class for roles.`models.team``string``Team::class`Model class for teams.`models.invitation``string``TeamInvitation::class`Model class for team invitations.`user-name-property``string``'name'`Property on the User model used for display in the admin UI.`url-prefix``string``'/genealabs/laravel-governor/'`URL prefix for all Governor web routes.`superadmins``string|null``env('GOVERNOR_SUPERADMINS')`JSON array of users to auto-create as SuperAdmins during seeding. Format: `[{"name":"...","email":"...","password":"..."}]``admins``string|null``env('GOVERNOR_ADMINS')`JSON array of users to auto-create as Admins during seeding. Same format as `superadmins`.`entity-aliases``array``[]`Map of raw entity names to display names in the UI. E.g. `['User' => 'Team Member']`.`cache.enabled``bool``false`Enable cross-request caching of lookup tables (roles, actions, entities, permissions).`cache.ttl``int|null``3600`Cache TTL in seconds. Set to `null` for "forever" (until manually invalidated).### Caching

[](#caching)

Governor can cache lookup table queries across requests to reduce database load. This is disabled by default.

To enable caching, publish the config file and update the `cache` section:

```
'cache' => [
    'enabled' => true,
    'ttl' => 3600, // seconds, or null for "forever"
],
```

Cache is automatically invalidated when any lookup table model (Action, Entity, Ownership, Permission, Role) is created, updated, or deleted. Invalidation is coarse-grained: a change to any single lookup table flushes the cache for all lookup tables. This keeps the invalidation logic simple and reliable, which is appropriate given that lookup tables change infrequently.

### Views

[](#views)

If you would like to customize the views, publish them:

```
php artisan governor:publish --views
```

and edit them in `resources/views/vendor/genealabs-laravel-governor`.

### Tables

[](#tables)

Tables will automatically be updated with a `governor_owned_by` column that references the user that created the entry. There is no more need to run separate migrations or work around packages that have models without a `created_by` property.

### Admin Views

[](#admin-views)

The easiest way to integrate Governor into your app is to add menu items to the relevant section of your app's menu (restrict access using Laravel Authorization methods). The following named routes are available:

- Role Management: `genealabs.laravel-governor.roles.index`
- User-Role Assignments: `genealabs.laravel-governor.assignments.index`
- Teams: `genealabs.laravel-governor.teams.index`
- Groups: `genealabs.laravel-governor.groups.index`

For example:

```
Governor
```

### 403 Unauthorized

[](#403-unauthorized)

We recommend making a custom 403 error page to let the user know they don't have access. Otherwise the user will just see the default error message. See  for more details on how to set those up.

---

API Reference
-------------

[](#api-reference)

### Traits

[](#traits)

Governor provides two traits for your Eloquent models. Use `Governing` on your User model (it includes `Governable` automatically). Use `Governable` on any other model that should be governed.

#### `Governing` Trait

[](#governing-trait)

**Namespace:** `GeneaLabs\LaravelGovernor\Traits\Governing`**Use on:** Your User model

This trait adds role management, team membership, and permission resolution to the User model. It includes the `Governable` trait, so you do not need to add both.

##### `hasRole(string $name): bool`

[](#hasrolestring-name-bool)

Check whether the user has a specific role.

- **Parameters:** `$name` — the role name (e.g. `'SuperAdmin'`, `'Member'`)
- **Returns:** `true` if the user has the given role or is a SuperAdmin

```
if ($user->hasRole('Editor')) {
    // user has the Editor role
}
```

##### `roles(): BelongsToMany`

[](#roles-belongstomany)

Eloquent relationship to the user's assigned roles.

- **Returns:** `BelongsToMany` relationship to `Role` via `governor_role_user`

```
$roleNames = $user->roles->pluck('name'); // ['SuperAdmin', 'Member']
```

##### `ownedTeams(): HasMany`

[](#ownedteams-hasmany)

Eloquent relationship to teams owned by this user.

- **Returns:** `HasMany` relationship to `Team` where `governor_owned_by` matches the user

```
$myTeams = $user->ownedTeams;
```

##### `teams(): BelongsToMany`

[](#teams-belongstomany)

Eloquent relationship to teams the user is a member of.

- **Returns:** `BelongsToMany` relationship to `Team` via `governor_team_user`

```
$teamNames = $user->teams->pluck('name');
```

##### `permissions` (Accessor)

[](#permissions-accessor)

All permissions associated with the user's roles.

- **Returns:** `Collection` of `Permission` models

```
$permissions = $user->permissions;
```

##### `effectivePermissions` (Accessor)

[](#effectivepermissions-accessor)

Deduplicated permissions across all roles, collapsed to the highest ownership level per entity/action pair. If any role grants `"any"` ownership, the effective permission is `"any"`; if the best is `"own"`, it returns `"own"`.

- **Returns:** `Collection` of `Permission` models with `role_name` and `team_name` set to `null`

```
$effective = $user->effectivePermissions;
```

---

#### `Governable` Trait

[](#governable-trait)

**Namespace:** `GeneaLabs\LaravelGovernor\Traits\Governable`**Use on:** Any Eloquent model that should have ownership tracking and permission-scoped queries

##### `ownedBy(): BelongsTo`

[](#ownedby-belongsto)

Eloquent relationship to the user who owns this model.

- **Returns:** `BelongsTo` relationship to the auth model via `governor_owned_by`

```
$owner = $blogPost->ownedBy;
```

##### `teams(): MorphToMany`

[](#teams-morphtomany)

Eloquent polymorphic relationship to teams associated with this model.

- **Returns:** `MorphToMany` relationship to `Team` via `governor_teamables`

```
$teams = $blogPost->teams;
```

##### Query Scopes

[](#query-scopes)

All scopes filter query results based on the authenticated user's permissions. If the user has `"any"` ownership for the relevant action, the query is unmodified. If the user has `"own"` ownership, results are limited to records they own or belong to their teams. If neither, the query returns no results.

ScopeFilters by actionUsage`scopeDeletable``delete``BlogPost::deletable()->get()``scopeForceDeletable``forceDelete``BlogPost::forceDeletable()->get()``scopeRestorable``restore``BlogPost::restorable()->get()``scopeUpdatable``update``BlogPost::updatable()->get()``scopeViewable``view``BlogPost::viewable()->get()``scopeViewAnyable``viewAny``BlogPost::viewAnyable()->get()`These scopes can be applied directly to any query builder instance, making them useful in Nova or other admin panels:

**Nova example:**

```
use Laravel\Nova\Resource as NovaResource;
use Laravel\Nova\Http\Requests\NovaRequest;

abstract class Resource extends NovaResource
{
    public static function indexQuery(NovaRequest $request, $query)
    {
        return $query->viewAnyable();
    }
}
```

---

### Policies

[](#policies)

#### `BasePolicy`

[](#basepolicy)

**Namespace:** `GeneaLabs\LaravelGovernor\Policies\BasePolicy`

All Governor policies must extend this class. It provides automatic permission checking for standard Laravel policy methods. Policies are auto-detected from your `app/Policies` directory (and any paths configured via `policy_paths` in config) — you do not need to register them manually.

##### Default Policy Methods

[](#default-policy-methods)

These methods are implemented automatically. Override them only if you need custom behavior:

MethodSignatureDescription`create``create(?Model $user): bool`Can the user create a new instance? Checks `create` action permission.`update``update(?Model $user, Model $model): bool`Can the user update this model? Checks `update` action with ownership.`viewAny``viewAny(?Model $user): bool`Can the user list all instances? Checks `viewAny` action permission.`view``view(?Model $user, Model $model): bool`Can the user view this model? Checks `view` action with ownership.`delete``delete(?Model $user, Model $model): bool`Can the user delete this model? Checks `delete` action with ownership.`restore``restore(?Model $user, Model $model): bool`Can the user restore this model? Checks `restore` action with ownership.`forceDelete``forceDelete(?Model $user, Model $model): bool`Can the user force-delete this model? Checks `forceDelete` action with ownership.SuperAdmins bypass all permission checks and always return `true`.

Guest users (unauthenticated) are assigned the `Guest` role if it exists.

##### Custom Policy Actions

[](#custom-policy-actions)

You can define custom actions beyond the standard CRUD operations by adding public methods to your policy class. Governor automatically detects any public methods that are not inherited from `BasePolicy` and registers them as custom actions in the permissions system.

```
class BlogPostPolicy extends BasePolicy
{
    public function publish(?Model $user, Model $model): bool
    {
        return $this->authorizeCustomAction($user, $model);
    }

    public function archive(?Model $user, Model $model): bool
    {
        return $this->authorizeCustomAction($user, $model);
    }
}
```

Custom actions are registered with names in the format `App\Models\BlogPost:publish` and appear in the role permission editor.

To check custom actions in your application:

```
$user->can('publish', $blogPost);
```

##### Creating a Policy

[](#creating-a-policy)

Create a policy class that extends `BasePolicy`. That's it — no methods are required for the default CRUD actions to work:

```
