skills/leeovery/claude-laravel/laravel-policies

laravel-policies

SKILL.md

Laravel Policies

Policies encapsulate authorization logic and delegate to permission systems.

Related guides:

Structure

<?php

declare(strict_types=1);

namespace App\Policies;

use App\Enums\Permission;
use App\Models\Order;
use App\Models\User;

class OrderPolicy
{
    public function viewAny(User $user): bool
    {
        return $user->can(Permission::ListOrders);
    }

    public function view(User $user, Order $order): bool
    {
        return $user->can(Permission::ViewOrders)
            && $order->customer_id === $user->customer_id;
    }

    public function create(User $user): bool
    {
        return $user->can(Permission::CreateOrders);
    }

    public function update(User $user, Order $order): bool
    {
        return $user->can(Permission::UpdateOrders)
            && $order->canBeModified()
            && $order->customer_id === $user->customer_id;
    }

    public function delete(User $user, Order $order): bool
    {
        return $user->can(Permission::DeleteOrders)
            && $order->isPending();
    }

    public function cancel(User $user, Order $order): bool
    {
        return $this->update($user, $order)
            && $order->canBeCancelled();
    }
}

Permission Enum

<?php

declare(strict_types=1);

namespace App\Enums;

use Henzeb\Enumhancer\Concerns\Comparison;
use Henzeb\Enumhancer\Concerns\Dropdown;

enum Permission: string
{
    use Comparison, Dropdown;

    case ListOrders = 'list orders';
    case ViewOrders = 'view orders';
    case CreateOrders = 'create orders';
    case UpdateOrders = 'update orders';
    case DeleteOrders = 'delete orders';
    case CancelOrders = 'cancel orders';
}

Standard Policy Methods

Laravel conventions for policy methods:

  • viewAny() - List/index
  • view() - Show single resource
  • create() - Create new resource
  • update() - Update resource
  • delete() - Delete resource
  • restore() - Restore soft-deleted
  • forceDelete() - Permanently delete

Custom methods for non-standard actions:

  • cancel()
  • approve()
  • ship()
  • etc.

Key Patterns

1. Delegate to Permission System

return $user->can(Permission::CreateOrders);

2. Ownership Checks

return $user->can(Permission::ViewOrders)
    && $order->customer_id === $user->customer_id;

3. State Checks

return $user->can(Permission::DeleteOrders)
    && $order->isPending();

4. Combine Existing Methods

public function cancel(User $user, Order $order): bool
{
    return $this->update($user, $order)
        && $order->canBeCancelled();
}

Usage in Routes

Route::get('/orders', [OrderController::class, 'index'])
    ->can('viewAny', Order::class);

Route::get('/orders/{order}', [OrderController::class, 'show'])
    ->can('view', 'order');

Route::post('/orders', [OrderController::class, 'store'])
    ->can('create', Order::class);

See routing-permissions.md for route authorization.

Summary

Policies should:

  • Use permission enums (not strings)
  • Check ownership when needed
  • Check state when needed
  • Delegate to permission system
  • Follow Laravel naming conventions
  • Stay simple and focused
Weekly Installs
27
GitHub Stars
36
First Seen
Jan 24, 2026
Installed on
opencode23
codex22
gemini-cli22
cursor22
github-copilot20
claude-code18