These rules are not enforced by PHP-CS-Fixer, so they must be followed manually.
- Use
camelCasefor all string-like internal variables and keys (unless public-facing). - Avoid using
finalon classes unless necessary.
- Use native property types whenever possible.
- Avoid using
@varunless native typing is impossible (e.g., for inherited third-party classes).
- Omit docblocks for fully type-hinted methods unless extra description is needed.
- When used, docblock descriptions must be full sentences and provide real context.
- Do not use fully qualified class names in docblocks.
- Always write
Type|null(withnulllast), notnull|Typeor?Type. - In method signatures, prefer
Type|nullover?Type(even though PHP allows both).
-
Prefer string interpolation:
// Good $greeting = "Hi, I am $name."; // Bad $greeting = 'Hi, I am ' . $name . '.';
- Break long ternary expressions across multiple lines.
- Keep them on one line only if very short.
- Always use curly braces.
- Follow the happy-path-last pattern (fail early, return early).
- Start single-line comments with a space after
//. - Use a single
*on each line in multi-line block comments. - Prefer expressive code over explanatory comments.
- Add blank lines between logical blocks for readability.
- Don’t add extra blank lines inside
{}blocks. - Only group single-line operations if equivalent (e.g., migrations).
- File names and keys must use
snake_case. - Do not use
env()outside configuration files. Create config keys for them.
-
Use kebab-case for command names:
php artisan delete-old-records
-
Always provide terminal feedback after a command runs (e.g.,
$this->comment('Done!');).
- Public-facing URLs must use kebab-case.
- Route names must use camelCase.
- Use route methods first (e.g.,
Route::get()->name()). - Route parameters should be in camelCase.
- Only use
/at the beginning of a URL if it is the root (/).
- Use singular resource names (e.g.,
PostController). - Stick to standard CRUD methods:
index,show,store,update,destroy, etc. - Extract a separate controller if additional actions are needed.
-
Always use array syntax for rules:
'email' => ['required', 'email'],
-
Prefer custom rule classes over
Validator::extend().
- All strings (including app name, messages, etc.) must be translated.
- Use
Lang::translate()(never hardcode output strings).
- Controllers: Singular resource +
ControllersuffixUserController,EventDayController - Invokable Controllers: Name by action, suffixed with
ControllerSendReportController - Resources / Transformers: Use plural form +
Resource/TransformerUsersResource,OrdersTransformer - Jobs: Verb-based names
CreateUser,ArchiveOldPosts - Events: Reflect timing
LoanApproved,ApprovingLoan - Listeners: Describe action, suffixed with
ListenerSendInvitationMailListener - Commands: Suffixed with
CommandPublishScheduledPostsCommand
-
Use structured error responses:
{ "message": "Invalid Vendor for Promotion", "code": 1003 } -
Use module-specific error code ranges (e.g.,
1001–1999for orders).
- Use pagination when returning multiple records.
- Never expose Eloquent models directly to frontend; use Transformers or Resources.
- Prefer timestamp columns (e.g.,
published_at) over booleans (is_published). - Avoid lazy loading, even for
hasOnerelationships.
-
Do not use
Type::cases()or dynamic enums in migrations. -
Always hard-code enum values:
$table->enum('type', ['One', 'Two', 'Three']);
- Use PascalCase for enum case names, not
UPPERCASE.
findByX()for single item queries.getByX()orget()returningEnumerablefor collections.persistMany()for batch inserts.save()for single create/update operations.