PHP has been around long enough that there are five ways to do anything. Laravel adds its own layer on top. Cursor will happily suggest PHP 5 patterns, raw SQL in a Laravel app, or helper functions your project has explicitly moved away from.
Here's the .cursorrules setup that keeps it on track.
The core file
# Laravel project rules
## Stack
PHP 8.2+, Laravel 11, MySQL, Redis for caching and queues
## PHP version requirements
- Use PHP 8.x features: named arguments, match expressions, enum, readonly, fibers where applicable
- Never suggest PHP 7.x or earlier patterns
- No old-style constructors, no mysql_ functions, no PHP 4/5 OOP patterns
## Laravel conventions
- Models: app/Models/
- Controllers: thin — logic goes in Services or Actions
- Services: app/Services/ — complex business logic
- Actions: app/Actions/ — single-responsibility operations
- Repositories: app/Repositories/ — only if data access is complex
- Form Requests for validation: never validate in controllers
- Resources for API responses: never manually format JSON in controllers
## Database
- Eloquent ORM. No raw SQL except in migration files.
- Eager load relationships to prevent N+1 queries
- Use query scopes for reusable query logic
- Migrations for all schema changes — never modify tables directly
## Patterns to use
- Service classes over fat controllers
- Form Request classes for validation
- Eloquent Resources for API responses
- Jobs/Queues for background processing
- Events/Listeners for decoupled side effects
## Patterns to avoid
- Business logic in controllers or models
- Raw DB::statement() unless in migrations
- dd() or var_dump() in any committed code
- Static methods for things that should be injected
## Rules
- Minimal footprint. Only touch files required for the task.
- Follow PSR-12 naming conventions.
- Do not add comments to code you didn't write.
What this prevents
Raw SQL in controllers — Cursor defaults to this when it's unsure how Eloquent handles something. The explicit rule stops it.
Logic in controllers — The classic Laravel anti-pattern. The rule pushes it to Services.
PHP 7 patterns — If your codebase has old code, Cursor will copy those patterns. Specifying PHP 8.2+ stops the drift.
N+1 queries — Cursor often generates eager loading on loops. The rule makes it explicit.
Adding project-specific context
Append your specific models and their relationships so Cursor doesn't guess:
## Key models
- User: has many Orders, belongs to many Roles
- Order: belongs to User, has many OrderItems, has one Payment
- Product: has many OrderItems, belongs to many Categories
## Authentication
Laravel Sanctum. Auth middleware: auth:sanctum. User from request: $request->user()
The more specific the context, the fewer wrong-direction suggestions.
Full .cursorrules templates for more stacks: builtbyzac.com/cursor-rules.html. Generator tool: builtbyzac.com/tools/cursorrules-generator.html.
Top comments (0)