Loading...

This is taking longer than expected.

Coding standards

Laravel Policies

These are the standards the analyzer applies. Every rule states what it checks and why it exists.

All standards

General Rules

  • Host-application policies live in app/Policies/; package policies live in the package's src/Policies/ directory
  • Only extend BasePolicy when the model has its own independent CRUD in the admin frontend (registered via Laravel Front). BasePolicy validates hasPermissionTo($name) against permissions stored in the database — if there is no CRUD, the permission does not exist and there is no reason to create it.
  • Do not infer that a model lacks independent CRUD merely because a policy adds business logic such as && $model->can_be_deleted or && ! $instance->is_paid. Verify route/resource evidence such as Route::front('ModelName'), an app/Front/Resources/ModelName.php resource, or an explicit permission before failing extends BasePolicy.
  • When a model does not have its own CRUD (e.g. BillingPrice, BillingPriceVariation), the policy handles only business logic (e.g. "cannot delete if it has children") without checking user permissions by name. Access is inherited from the parent model's permission (e.g. if the user has the plans permission, they have access to prices and variations).
  • Do not register policies manually in AppServiceProvider. Laravel autodiscovers policies that follow the App\Policies\{Model}Policy naming convention. Package policies are the exception: autodiscovery only maps App\Models\X to App\Policies\XPolicy, so the package service provider registers them with Gate::policy().
  • Prefer policies for reusable authorization and access rules tied to protected models or resources. Do not create ad hoc component helpers such as canAccessVisitor() or canManageResource() to hold authorization logic when there is a useful policy subject; put the rule in the policy and call it through Laravel authorization (authorize, can, @can, or equivalent project helpers).
  • Inline checks are acceptable for local UI state, public flows, or one-off guards with no useful policy subject, but protected resource access should default to policy-backed authorization.
  • When a policy enforces a persistence-sensitive business rule, pair it with an observer safety net for the same rule.
  • When delete authorization has business logic (e.g. "cannot delete if it has children"), expose that logic as the can_be_deleted accessor on the model. The policy delete() and observer deleting() read $model->can_be_deleted instead of duplicating the condition.
Weblabor Logo Developed by Weblabor