phanalist

E0012: Service Compatibility with Shared Memory Model

In plain English: In long-running PHP runtimes (like RoadRunner, Swoole, or FrankenPHP), application services remain in memory across multiple requests. This rule ensures that services do not mutate their own object properties during request handling, preventing request data leaks between users.

Why it matters: In traditional PHP-FPM, memory is wiped clean after every request. In modern workers (Swoole/RoadRunner), a single service instance handles thousands of requests. If a service stores user-specific state in $this->someProperty = $request->input;, that state leaks into the next request handled by another user, causing severe security vulnerabilities and data corruption.

❌ The Bad Example

namespace App\Service;

class UserService {
    private string $currentUser;

    public function handleRequest(Request $request): void {
        // Mutating $this state in a long-running worker!
        $this->currentUser = $request->get('user'); 
        $this->process();
    }
}

✅ The Good Example

namespace App\Service;

class UserService {
    // Pass state as method parameters instead of storing in $this
    public function handleRequest(Request $request): void {
        $user = $request->get('user');
        $this->process($user);
    }
}

What the rule checks

When it does not report

How to fix

Configuration

rules:
  E0012:
    include_namespaces:
      - "App\\Service\\"
      - "App\\Controller\\"
    exclude_namespaces: []
    reset_interfaces:
      - "ResetInterface"

Junior Engineer’s Rule of Thumb:

Treat your services as stateless. Never store user request data in $this->property inside controllers or services, especially when running modern long-running PHP servers!