DEV Community

Zac
Zac

Posted on

Cursor with PHP and Laravel: .cursorrules that stop the framework confusion

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.
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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)