PHP code example of elpandape / bouncer

1. Go to this page and download the library: Download elpandape/bouncer library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

elpandape / bouncer example snippets


use ElPandaPe\Bouncer\Concerns\HasRolesAndPermissions;

class User extends Authenticatable
{
    use HasRolesAndPermissions;
}

Bouncer::allow($user)->to('edit', Post::class);     // grant, at any granularity
Bouncer::forbid($user)->to('edit', $secretPost);    // an explicit denial always wins
Bouncer::assign('editor')->on($org)->to($user);     // a role, scoped to one model

$user->can('edit', $post);                          // it is Laravel's Gate
Post::whereCan($user, 'edit')->paginate();          // which rows, as a query scope
Bouncer::explain($user, 'edit', $post);             // why, row by row

$user->can('edit-site');            // simple permission
$user->can('edit', $post);          // one instance
$user->can('edit', Post::class);    // the whole class
Gate::authorize('edit', $post);     // throws on deny
@can('edit', $post) ... @endcan     // Blade, as always

use ElPandaPe\Bouncer\Facades\Bouncer;

Bouncer::allow($user)->to('ban-users');            // simple permission
Bouncer::allow($user)->to('edit', Post::class);    // every post
Bouncer::allow($user)->to('edit', $post);          // one post
Bouncer::allow($user)->everything();               // wildcard
Bouncer::allow($user)->toOwn(Post::class);         // only what they own
Bouncer::allowEveryone()->to('browse');            // everyone

Bouncer::assign('admin')->to($user);               // roles, created on the fly
Bouncer::allow('admin')->to('audit');              // grant to a role by name
Bouncer::sync($user)->roles(['editor', 'writer']); // declarative sync

Bouncer::allow($user)->to('view', Document::class);
Bouncer::forbid($user)->to('view', $classifiedDocument);

Bouncer::allow($user)->toOwn(Post::class);            // any action on owned posts
Bouncer::allow($user)->toOwn(Post::class, ['edit']);  // only these actions
Bouncer::allow($user)->toOwnEverything();

Bouncer::ownedVia('author_id');                       // global attribute
Bouncer::ownedVia(Post::class, 'writer_id');          // per class
Bouncer::ownedVia(fn ($post, $user) => $post->team_id === $user->team_id);

Bouncer::allow($user)->toOwn(Post::class);
Bouncer::forbid($user)->toOwn(Post::class, 'delete'); // owners still can't delete

Bouncer::assign('editor')->on($orgOne)->to($user);   // editor only inside orgOne
Bouncer::assign('editor')->on($orgTwo)->to($user);   // same role, second context
Bouncer::retract('editor')->on($orgOne)->from($user); // leave one; without on(), all

Bouncer::restrictedVia(Post::class, 'organization_id');           // membership by FK
Bouncer::restrictedVia(fn ($entity, $context) => ...);            // or a closure

Bouncer::assign('admin')->on($project)->to($user);
$user->can('manage', $project);          // true: the entity IS the context
$user->can('edit', $taskInProject);      // true: task->project_id points at it

Bouncer::tenant()->to($tenantId);       // everything now scoped to this tenant
Bouncer::tenant()->onceTo(9, fn () => ...); // temporary, exception-safe
Bouncer::tenant()->onlyRelations();     // keep the permission catalog global
Bouncer::tenant()->dontScopeRoleGrants();

Bouncer::tenant()->removeOnce(fn () => Bouncer::unforbid($user)->to('publish'));

Bouncer::allow($user)->to('view', Document::class)
    ->where('status', 'published')
    ->orWhere(fn ($group) => $group->where('tier', '>=', 2)->whereColumn('owner_id', 'id'));

Bouncer::allow('viewer')->to('view', Document::class)->where('status', 'published');
Bouncer::forbid($user)->to('view', Document::class)->where('classified', true);

use ElPandaPe\Bouncer\Concerns\QueriesByPermission;

Post::whereCan($user, 'view')->latest()->paginate();

$why = Bouncer::explain($user, 'edit', $post);

$why->allowed();      // bool
$why->cause;          // Cause::ForbiddenViaRole, Cause::GrantedDirectly, …
$why->permission;     // the decisive catalog row
$why->role;           // the role that carried it, when one did
(string) $why;        // "Explicitly forbidden by permission [edit] via role [banned]."

Event::listen(PermissionGranted::class, function (PermissionGranted $event) {
    audit('granted', $event->authority, $event->permissions->pluck('name'));
});

Bouncer::findRole('ghost');            // RoleDoesNotExist (a ModelNotFoundException)
Bouncer::findPermission('ghost');      // PermissionDoesNotExist
Bouncer::authorize('publish', $post);  // UnauthorizedException (an AuthorizationException)
config(['bouncer.models.role' => Foo::class]); // ConfigurationException, fail-fast

enum Permission: string { case EditSite = 'edit-site'; }

Bouncer::allow($user)->to(Permission::EditSite);
Bouncer::assign(Role::Admin)->to($user);
$user->isAn(Role::Admin);
Bouncer::authorize(Permission::EditSite);

// config/bouncer.php — a real store with a TTL:
'cache' => [
    'enabled' => true,
    'store' => 'default',
    'prefix' => 'bouncer',
    'expiration_time' => DateInterval::createFromDateString('24 hours'),
],

Bouncer::refresh();          // invalidate everything: an O(1) version bump
Bouncer::refreshFor($user);  // drop one authority's payload

Bouncer::disallow($user)->to('publish');   // the next check is already correct

// Script verdicts without touching tables; unscripted checks fall to your policies.
$fake = Bouncer::fake();
$fake->allow('edit-site')->forbid('delete');

$fake->assertChecked('edit-site');
$fake->assertGranted('edit-site');
$fake->assertForbidden('delete');
$fake->assertNothingChecked();

// Or arrange real rows tersely with the trait:
use ElPandaPe\Bouncer\Testing\WithPermissions;

$this->allowUser($user, 'view', Document::class);
$this->assignRoles($user, 'admin');

Route::get('/admin', ...)->middleware('bouncer.role:admin,editor');      // any of
Route::put('/site', ...)->middleware('bouncer.permission:edit-site');    // all of

use ElPandaPe\Bouncer\Concerns\HasRolesAndPermissions;

class User extends Authenticatable
{
    use HasRolesAndPermissions;
}

// ✅ Do — point the config at your model, keep the concern:
// config/bouncer.php
'models' => ['role' => App\Models\Role::class],

// app/Models/Role.php
class Role extends Model
{
    use ElPandaPe\Bouncer\Models\Concerns\IsRole;
}

// ❌ Don't — don't hardcode package classes in relations or checks;
// resolve them via config so swapped models keep working everywhere.
$user->roles()->attach(ElPandaPe\Bouncer\Models\Role::first());

Gate::forUser($tenantUser)->allows('edit', $post);
Bouncer::explain($tenantUser, 'edit', $post);   // diagnosis takes any authority

Bouncer::ownedVia(Business::class, fn ($business, $user) => $business->owners()->whereKey($user->getKey())->exists());
Bouncer::allow($user)->toOwn(Business::class, ['manage']);

// In your User model or an observer:
protected static function booted(): void
{
    static::created(fn (User $user) => Bouncer::assign('member')->to($user));
}

Bouncer::tenant()->removeOnce(fn () => $user->roles()->get()->groupBy('pivot.scope'));

Bouncer::sync($user)->roles(['editor']);          // declarative
Bouncer::retract('viewer')->from($user);          // or surgical
Bouncer::assign('editor')->to($user);