- Every PHP file must start with
<?phpfollowed immediately bydeclare(strict_types=1);on line 2. No exceptions. No blank lines between them. - Never use
var_dump(),dd(),dump(), orprint_r()in any file underapp/,routes/, orconfig/. These are test-only functions. - All class files must be in
app/with subdirectories matching namespace:App\Models\Userlives inapp/Models/User.php. - Use
final classby default. Only removefinalif the class is explicitly designed for extension (document why in a comment). - Never use
arraytype hint. Usearray<string, mixed>,array<int, Model>, or specific collection types instead.
- All database queries must use Eloquent or Query Builder. Raw SQL queries are forbidden except in migrations and only with explicit
DB::statement()calls. - Never use
Model::all(). UseModel::query()->get()orModel::query()->paginate()with explicit column selection:->select(['id', 'name']). - Every Eloquent query must call
->select()explicitly. Never rely onSELECT *. - Relationships must be defined as methods in Model classes using
hasMany(),belongsTo(),belongsToMany()— never usewith()in controller logic without the relationship being defined in the Model first. - Use
eager loadingwith->with()for all relationships accessed in loops. If you access a relationship in a loop withoutwith(), that's an N+1 bug. - Scopes must be defined as methods prefixed with
scope:scopeActive()becomes->active()in queries. Never filter in controller logic. - Mutators and accessors must use
Attribute::make()syntax (Laravel 9+). Never usegetAttribute()orsetAttribute()directly. - Timestamps are enabled by default. If a model doesn't need them, explicitly set
public $timestamps = false;with a comment explaining why.
- All user input validation must happen in
app/Http/Requests/Form Request classes. Never validate in controllers. - Form Request class name must match the action:
StoreUserRequest,UpdateUserRequest,DeleteUserRequest. File:app/Http/Requests/StoreUserRequest.php. - Every Form Request must have
authorize()returning a boolean andrules()returning an array. Both are required. - Use
Rule::unique()for database uniqueness checks, not custom validation logic. - Custom validation rules must be in
app/Rules/as classes implementingValidationRule. Never use closure-based rules in Form Requests. - Validated data must be accessed via
$request->validated()in controllers, never$request->all()or$request->input().
- All API responses must use
app/Http/Resources/classes extendingJsonResourceorResourceCollection. - Resource class name must match the model:
UserResourceforUsermodel. File:app/Http/Resources/UserResource.php. - Never return raw Eloquent models from controllers. Always wrap in a Resource:
return new UserResource($user);. - Collection responses must use
UserResource::collection($users)or extendResourceCollectionfor pagination metadata. - Resource
toArray()method must explicitly list every field. Never use$this->resource->toArray()or$this->all().
- Controller class name must end with
Controller:UserController,PostController. File:app/Http/Controllers/UserController.php. - One controller per resource. Never mix multiple resources in one controller.
- Controller methods must be named after REST actions:
index,show,create,store,edit,update,destroy. No other method names. - Controllers must be thin. Business logic goes in
app/Services/or Model methods, never in controller methods. - Constructor injection only. Never use
app()orresolve()in controller methods. - Every controller method must have a return type hint:
public function show(User $user): UserResource.
- All exceptions must extend
Exceptionor a specific exception class inapp/Exceptions/. Never throw genericException. - Create custom exception classes in
app/Exceptions/:ModelNotFoundException,ValidationFailedException,UnauthorizedException. - Every custom exception must have a
render()method returning a JSON response withstatus,message, anddatakeys. - Try-catch blocks must catch specific exception types, never
catch (Exception $e)orcatch (Throwable $e). - Exceptions must be caught at the boundary (controller or command) and converted to responses. Never let them bubble up uncaught.
- Use
abort(404),abort(403),abort(422)for HTTP errors. Never throw custom exceptions for HTTP status codes.
- Environment variables must be read in
config/files only, never inapp/code. Useconfig('app.key')instead ofenv('APP_KEY'). - Never hardcode API keys, database credentials, or secrets. All must come from
.envfile. .envfile must never be committed. Add to.gitignoreimmediately..env.examplemust exist with all required keys and dummy values. Update it when adding new env vars.- Configuration values must be type-cast in
config/files:'debug' => (bool) env('APP_DEBUG', false).
- Test files must be in
tests/Feature/for integration tests ortests/Unit/for unit tests. - Test class name must match the class being tested with
Testsuffix:UserControllerTest,UserServiceTest. File:tests/Feature/UserControllerTest.php. - Every public method must have at least one test. No exceptions.
- Test method names must describe the scenario:
testStoreUserWithValidDataReturnsCreatedResponse(), nevertestStore(). - Use
$this->actingAs($user)for authenticated requests, never manually set headers. - Mock external services (APIs, mail, queues) using
Mail::fake(),Http::fake(),Queue::fake(). - Never use real database in tests. Use
RefreshDatabasetrait orDatabaseTransactionstrait.
- Models:
app/Models/ - Controllers:
app/Http/Controllers/ - Requests:
app/Http/Requests/ - Resources:
app/Http/Resources/ - Services:
app/Services/ - Rules:
app/Rules/ - Exceptions:
app/Exceptions/ - Migrations:
database/migrations/ - Seeders:
database/seeders/ - Tests:
tests/Feature/andtests/Unit/
- Model names: singular, PascalCase:
User,BlogPost,Comment - Table names: plural, snake_case:
users,blog_posts,comments - Variable names: camelCase:
$userId,$isActive,$userData - Method names: camelCase:
getUserById(),isUserActive() - Constant names: UPPER_SNAKE_CASE:
MAX_RETRIES,DEFAULT_TIMEOUT - Boolean methods/properties: prefix with
is,has,can:isActive(),hasPermission(),canDelete()
- Every method must have parameter type hints and return type hints. No exceptions.
- Use nullable types explicitly:
?string,?User, never omit the?. - Use union types for multiple possibilities:
string|int,User|null(not?Userif there are other types). - Use
voidreturn type for methods that don't return anything. - Use
neverreturn type for methods that always throw or exit. - Generic types must be specified:
Collection<User>,array<string, int>, never bareCollectionorarray.
- Never use
globalkeyword. - Never use
eval()orcall_user_func()with string arguments. - Never use
extract()orcompact()in production code. - Never use
@error suppression operator. - Never use
goto. - Never use
staticproperties for state. Use dependency injection instead. - Never use string-based route names without
route()helper: alwaysroute('users.show', $user), never hardcoded URLs.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>