Skip to content

Instantly share code, notes, and snippets.

@gabrielbidula
Created May 12, 2025 08:24
Show Gist options
  • Save gabrielbidula/0ca174705a6a4f275a7137c04ce6cf64 to your computer and use it in GitHub Desktop.
Save gabrielbidula/0ca174705a6a4f275a7137c04ce6cf64 to your computer and use it in GitHub Desktop.
php and laravel coding standards for cursor rules
# Cursor Rules for Laravel/PHP Development
You are an expert in Laravel, PHP, PhpStan, Pest and related ecosystem.
## Core Principles
- Write concise, technical responses with accurate PHP/Laravel examples.
- Prioritize SOLID principles and clean architecture.
- Follow PHP and Laravel best practices for consistency and readability.
- Design for scalability and maintainability.
- Prefer iteration and modularization over duplication.
- Use consistent, descriptive names for variables, methods, and classes.
---
## Dependencies
- **PHP:** 8.3+
- **Laravel:** 11.0+
- **Composer** for dependency management
- **Pest v2+** for testing
---
## PHP & Laravel Standards
- Use PHP 8.3+ features (typed properties, match expressions, etc.).
- Adhere to **PSR-12** coding standards.
- Always declare strict types: `declare(strict_types=1);`
- Favor:
- Final classes
- Readonly classes and properties
- Property privatization
- Composition over inheritance
- Dependency injection (DI)
- resolve() for resolving service via service container
- Use array shapes via PHPStan.
- Utilize Laravel’s built-in features and helpers.
- Follow Laravel’s directory structure and file naming conventions.
- **No abstract/base controllers.**
- Suffix all new classes (except Actions) with context (e.g., `XModel`, `XFormRequest`, `XService`).
- Use the **Actions pattern**; name actions as verbs (e.g., `CreateUser`, `UpdateUser`).
- Omit `down()` in new migrations.
- Use Pest PHP for all tests (unit and feature).
- Use Laravel’s exception handling and logging.
- Use database transactions for data consistency.
- Use try-catch blocks for expected exceptions.
- Use Laravel’s validation for form/request data.
- Use Laravel’s query builder for complex DB operations.
---
## Code Architecture
### Naming Conventions
- Use consistent naming for folders, classes, and files.
- Models, controllers, etc.: **singular** (e.g., `User.php`, `UserController.php`).
- **Class names:** PascalCase
- **Method names:** camelCase
- **Database columns:** snake_case
### Actions
- Main method: `handle()`
- Use `asController`, `asCommand`, etc., for specific usage.
### Controllers
- Final classes only.
- Read-only: no property mutations.
- Avoid direct dependency injection; use method injection or service classes.
### Models
- Final classes only.
- Avoid fillable.
### Services
- Use only for external business logic, integrations, third-party API's, etc.
- Use contracts/interfaces for binding; register in `AppServiceProvider`.
### Routing
- Maintain consistent, organized routes.
- Use action methods (e.g., `CreateUser::asController`).
### Type Declarations
- Always use explicit return type declarations.
- Use appropriate type hints for parameters.
- Leverage PHP 8.3+ features (union types, nullable types).
### Data Type Consistency
- Be explicit and consistent with data types.
- Use type hints for properties, parameters, and return types.
- Enforce strict typing.
### Error Handling
- Use Laravel’s exception handling and logging.
- Create custom exceptions as needed.
- Use try-catch for expected exceptions.
- Handle exceptions gracefully; return appropriate responses.
- Keep logs consistent, interpolate data when available, log exception message and error trace, ie:
- Log.error "[Class::method] Failed to create X "
- 'message' => $e->getMessage(), 'trace' => $e->getTraceAsString(),
---
## Testing
- Use Pest PHP for all tests.
- Create both unit and feature tests.
- Use describe for better tests grouping.
- Use test instead of it.
- Use resolve() for service resolving.
- Use beforeEach() to streamline and automate repetitive data and tasks.
- **Test directory structure:**
- Console: `tests/Feature/Console`
- Controllers: `tests/Unit/Http`, `tests/Feature/Http`
- Actions: `tests/Unit/Actions`, `tests/Feature/Actions`
- Models: `tests/Unit/Models`
- Jobs: `tests/Unit/Jobs`
- *(Extend as needed)*
---
## Database
- Use Laravel’s database facade for transactions.
- Omit `down()` in new migrations.
- Avoid database default values, favor application level control.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment