Skip to content

PHP 8.2 — Apply readonly classes #46

@s2x

Description

@s2x

PHP 8.2 — Apply readonly classes

Problem Description

PHP 8.2 introduces the readonly class modifier, which allows marking an entire class as immutable. Classes where ALL properties are readonly can be converted to readonly class, which simplifies the code and improves its readability.

Location

Below is an analysis of classes in the project regarding the possibility of applying readonly class:

✅ Candidates for readonly class

File Class Justification
src/Resolver.php Resolver All properties are readonly
src/Reboot/Strategy/StackRebootStrategy.php StackRebootStrategy One readonly property
src/Scheduler/TaskErrorListener.php TaskErrorListener One readonly property
src/Supervisor/ProcessErrorListener.php ProcessErrorListener One readonly property
src/Scheduler/TaskHandler.php TaskHandler All properties are readonly
src/Supervisor/ProcessHandler.php ProcessHandler All properties are readonly
src/Middleware/StaticFilesMiddleware.php StaticFilesMiddleware One readonly property
src/Middleware/SymfonyController.php SymfonyController One readonly property
src/Event/ProcessStartEvent.php ProcessStartEvent All properties are readonly
src/Event/TaskStartEvent.php TaskStartEvent All properties are readonly
src/ServerAlreadyRunningException.php ServerAlreadyRunningException No own properties
src/ServerNotRunningException.php ServerNotRunningException No own properties
src/ServerStopFailedException.php ServerStopFailedException No own properties

❌ Excluded classes (have mutable properties)

File Class Reason for exclusion
src/KernelFactory.php KernelFactory Has $kernel (nullable, mutable)
src/Reboot/Strategy/ExceptionRebootStrategy.php ExceptionRebootStrategy Has $exception (mutable)
src/Reboot/Strategy/MaxJobsRebootStrategy.php MaxJobsRebootStrategy Has $jobsCount (mutable)
src/Scheduler/Trigger/CronExpressionTrigger.php CronExpressionTrigger Has $expression (immutable, but not readonly)
src/Event/ProcessErrorEvent.php ProcessErrorEvent Has $error with setter (mutable)
src/Event/TaskErrorEvent.php TaskErrorEvent Has $error with setter (mutable)
src/Attribute/AsTask.php AsTask Attributes require mutable public properties
src/Attribute/AsProcess.php AsProcess Attributes require mutable public properties

Analysis

Example transformation — src/Resolver.php

Before:

final class Resolver implements ResolverInterface
{
    public function __construct(private readonly ResolverInterface $resolver, private readonly array $options)
    {
    }
}

After:

final readonly class Resolver implements ResolverInterface
{
    public function __construct(private ResolverInterface $resolver, private array $options)
    {
    }
}

Example transformation — exception classes

Before:

final class ServerAlreadyRunningException extends \RuntimeException
{
    public function __construct()
    {
        parent::__construct('Workerman is already running.');
    }
}

After:

final readonly class ServerAlreadyRunningException extends \RuntimeException
{
    public function __construct()
    {
        parent::__construct('Workerman is already running.');
    }
}

Proposed Solution

For each candidate class:

  1. Change class declaration from final class Foo to final readonly class Foo
  2. Remove the readonly keyword from individual property declarations (they become automatically readonly at the class level)

List of changes to make:

  1. src/Resolver.php — line 9
  2. src/Reboot/Strategy/StackRebootStrategy.php — line 7
  3. src/Scheduler/TaskErrorListener.php — line 11
  4. src/Supervisor/ProcessErrorListener.php — line 11
  5. src/Scheduler/TaskHandler.php — line 12
  6. src/Supervisor/ProcessHandler.php — line 12
  7. src/Middleware/StaticFilesMiddleware.php — line 10
  8. src/Middleware/SymfonyController.php — line 13
  9. src/Event/ProcessStartEvent.php — line 9
  10. src/Event/TaskStartEvent.php — line 9
  11. src/ServerAlreadyRunningException.php — line 7
  12. src/ServerNotRunningException.php — line 7
  13. src/ServerStopFailedException.php — line 7

Priority

🟡 MEDIUM — code modernization, better encapsulation. These changes improve code readability and clearly communicate class immutability, but are not critical for functionality.

Tests

After making changes:

  1. Run composer install to install dependencies
  2. Run vendor/bin/phpunit to ensure all tests pass
  3. Run vendor/bin/rector process --dry-run to verify no additional changes
  4. Check static code analysis (e.g., PHPStan)

Note: readonly class means that ALL class properties must be readonly. Before making changes, carefully verify each class to ensure it has no hidden mutable properties.

Metadata

Metadata

Assignees

No one assigned

    Labels

    mediumMedium priorityphp82PHP 8.2 modernization

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions