Skip to main content
rule

php — Cursor rule: what it does, how to install

A Cursor rule for PHP style, security, API design, and testing. It targets PSR-12 and modern PHP 8.4+ projects.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/php.mdc
Open on GitHub

What php does

This rule guides Cursor while it edits PHP files. It sets PSR-12 as the style baseline, requires four-space indentation and Unix LF endings, and places declare(strict_types=1); in each PHP file. It also favors typed parameters and return values, constructor property promotion, match, ??, and native attributes.

The guidance covers Composer autoload settings, ORM query loading, caching, strict comparisons, and error handling. Security checks include input validation, context-aware output escaping, parameterized queries, password hashing with password_hash(), dependency audits, and CSRF tokens.

It also describes REST conventions, PHPUnit unit and integration tests, PHPStan or Psalm, and CI checks on every commit. The rule targets PHP 8.4+, so older projects need a compatibility review before adopting these recommendations.

What it helps with

  • format PHP code according to PSR-12
  • add strict typing and explicit types
  • prevent SQL injection in database queries
  • validate input and escape rendered output
  • set up PHPUnit and static analysis checks

Example prompts for the agent

  • Refactor this PHP file to PSR-12 and add strict typing.
  • Review the $_POST and $_GET handling for validation, query safety, and output escaping.
  • Create PHPUnit tests for this class and suggest PHPStan checks.

How to install php

Manually: put the files in place

.cursor/rules/php.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about php

How do I install php in Cursor?

Place the rule file at .cursor/rules/php.mdc in the project.

What does the php rule do?

It gives Cursor guidance for PHP style, type declarations, security controls, API structure, exception handling, and tests.

Which PHP version does this rule target?

Its recommendations target PHP 8.4+ and use features such as union types, attributes, and match.

Source text

php.mdc · CC0-1.0
---
description: This guide provides definitive best practices for writing clean, secure, and maintainable PHP code, strictly adhering to PSR-12 and modern PHP 8.4+ features.
globs: **/*
---
# PHP Best Practices

This document outlines the definitive best practices for PHP development within our team. Adherence to these guidelines ensures consistency, maintainability, and security across all projects.

## Critical Guidelines:

### 1. Code Organization and Structure (PSR-12 & Strict Types)

Always adhere to PSR-12 for coding style. This includes indentation, brace placement, and line length. Crucially, enable strict typing in every PHP file.

*   **Indentation**: Use 4 spaces, never tabs.
*   **Line Endings**: Unix LF only.
*   **Closing Tag**: Omit `?>` from files containing only PHP code.
*   **File Header Order**:
    1.  `<?php`
    2.  File-level docblock (optional)
    3.  `declare(strict_types=1);`
    4.  `namespace` declaration
    5.  `use` statements (class, then function, then constant, grouped)
    6.  The rest of the code.

❌ BAD:
```php
<?php
namespace App\Service;
use App\Model\User;
declare(strict_types=1);

class UserService {
    public function getUser($id) { // Missing return type, no strict types at top
        return User::find($id);
    }
}
```

✅ GOOD:
```php
<?php

declare(strict_types=1);

namespace App\Service;

use App\Model\User;
use App\Repository\UserRepository;

class UserService
{
    public function __construct(private UserRepository $userRepository) {}

    public function getUser(int $id): ?User
    {
        return $this->userRepository->find($id);
    }
}
```

### 2. Common Patterns and Anti-patterns

*   **Type Hinting**: Always use scalar and return type declarations. Leverage PHP 8+ union types, intersection types, and `mixed`/`static`/`never` where appropriate.
*   **Constructor Property Promotion**: Use for concise dependency injection.
*   **Match Expression**: Prefer `match` over `switch` for cleaner, more expressive comparisons.
*   **Null Coalescing Operator (`??`)**: Use to simplify checks for `null` or unset variables.
*   **Attributes**: Prefer native PHP attributes (`#[Attribute]`) over docblock annotations for metadata.

❌ BAD:
```php
class LegacyProcessor {
    public function process($type, $data) {
        switch ($type) { // Old switch, no types
            case 'foo': return 'Foo ' . $data;
            case 'bar': return 'Bar ' . $data;
            default: return null;
        }
    }
}
```

✅ GOOD:
```php
<?php

declare(strict_types=1);

#[Attribute(Attribute::TARGET_CLASS)]
class MyServiceAttribute {}

#[MyServiceAttribute]
class ModernProcessor
{
    public function process(string $type, string $data): ?string
    {
        return match ($type) {
            'foo' => 'Foo ' . $data,
            'bar' => 'Bar ' . $data,
            default => null,
        };
    }

    public function getSetting(array $config): string
    {
        // Use null coalescing for default values
        return $config['setting'] ?? 'default_value';
    }
}
```

### 3. Performance Considerations

*   **Latest PHP Version**: Always use the current stable PHP version (8.4+).
*   **Composer Autoloading**: Optimize Composer's autoloader for production (`composer dump-autoload --optimize --no-dev --classmap-authoritative`).
*   **Avoid N+1 Queries**: Eager load relationships in ORMs.
*   **Caching**: Implement application-level caching for frequently accessed data.

### 4. Common Pitfalls and Gotchas

*   **Loose Comparisons**: Always use strict comparison operators (`===`, `!==`).
*   **Error Suppression**: Never use the `@` operator. Handle errors gracefully with exceptions.
*   **Modifying Arrays During Iteration**: Leads to unpredictable behavior. Iterate over a copy or use appropriate collection methods.

### 5. Security Best Practices

*   **Input Validation & Sanitization**: Validate all external input. Use specific validation rules, not just `filter_var`.
*   **Output Escaping**: Escape all output based on context (HTML, URL, JavaScript, CSS). Use templating engines that auto-escape or dedicated functions (e.g., `htmlspecialchars`).
*   **Prepared Statements**: Always use parameterized queries (PDO or ORM) to prevent SQL injection.
*   **Password Hashing**: Use `password_hash()` with `PASSWORD_ARGON2ID` (or `PASSWORD_BCRYPT` as fallback). Never store plain text passwords.
*   **Dependency Updates**: Regularly update Composer dependencies and run `composer audit`.
*   **CSRF Protection**: Implement CSRF tokens for state-changing requests.

❌ BAD:
```php
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'"; // SQL Injection!
$db->query($sql);
echo "Hello, " . $_GET['name']; // XSS vulnerability!
```

✅ GOOD:
```php
<?php

declare(strict_types=1);

// Input Validation
if (!isset($_POST['username']) || !is_string($_POST['username'])) {
    throw new InvalidArgumentException('Invalid username.');
}
$username = trim($_POST['username']);

// Password Hashing
$hashedPassword = password_hash($_POST['password'], PASSWORD_ARGON2ID);

// Prepared Statements
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([':username' => $username, ':password' => $hashedPassword]);

// Output Escaping
echo "Hello, " . htmlspecialchars($_GET['name'] ?? 'Guest', ENT_QUOTES, 'UTF-8');
```

### 6. Error Handling

*   **Exceptions**: Use exceptions for all exceptional conditions. Create custom exception classes for domain-specific errors.
*   **Centralized Handling**: Implement a global exception handler to catch unhandled exceptions and log them.
*   **Logging**: Use a robust logging library (e.g., Monolog) for all errors, warnings, and important events.

### 7. API Design

*   **RESTful Principles**: Design APIs to be resource-oriented, using standard HTTP methods (GET, POST, PUT, DELETE) and status codes.
*   **Consistent Naming**: Use consistent pluralized resource names (e.g., `/users`, not `/user`).
*   **Versioning**: Implement API versioning (e.g., `/v1/users`).
*   **Payload Validation**: Strictly validate all incoming request payloads.

### 8. Testing Approaches

*   **PHPUnit**: Write comprehensive unit and integration tests using PHPUnit.
*   **Test Doubles**: Use mocks, stubs, and fakes to isolate units of code during testing.
*   **Static Analysis**: Integrate PHPStan or Psalm into your CI/CD pipeline with a high strictness level.
*   **Continuous Integration**: Automate tests and static analysis checks on every commit.

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

All IDE rules for Programming languages →

From the same set240

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor