Skip to content

PHP 8.2+ support: Remove annotations and improve type safety#186

Merged
koriym merged 7 commits into1.xfrom
php82
Nov 11, 2025
Merged

PHP 8.2+ support: Remove annotations and improve type safety#186
koriym merged 7 commits into1.xfrom
php82

Conversation

@koriym
Copy link
Member

@koriym koriym commented Nov 11, 2025

Summary

  • Migrate from Doctrine annotations to PHP 8 attributes
  • Minimum PHP version raised to 8.2
  • Fix all Psalm and PHPStan errors for improved type safety
  • Add PHP 8.5 compatibility

Changes

Type Safety Improvements

  • Remove all Doctrine annotation dependencies
  • Fix Psalm and PHPStan errors across the codebase
  • Add proper type hints and return types
  • Remove unused variables and imports

PHP Version Support

  • Update minimum PHP requirement to 8.2
  • Add symfony/polyfill-php83 for PHP 8.3 feature support
  • Configure CI to test PHP 8.2-8.5
  • Move PHP 8.2 to old_stable versions in CI workflow

Development Tools

  • Move static analysis tools to vendor-bin/tools for PHP 8.5 compatibility
  • Keep only bamarni/composer-bin-plugin and phpunit in main require-dev

Configuration Updates

  • Update Scrutinizer config for PHP 8.4 and jammy image
  • Improve static analysis configurations (psalm.xml, phpstan.neon)

Breaking Changes

  • Minimum PHP version is now 8.2 (was 8.1)
  • Doctrine annotations removed in favor of PHP 8 attributes

Test Plan

  • All PHPUnit tests passing on PHP 8.2-8.5
  • Static analysis (Psalm, PHPStan) passes without errors
  • Code style checks passing

Summary by Sourcery

Upgrade the codebase to PHP 8.2+ by replacing Doctrine annotations with native attributes, strengthening type safety, reorganizing development tooling, and updating CI to cover PHP 8.2–8.5.

New Features:

  • Migrate from Doctrine annotations to PHP 8 attributes.

Bug Fixes:

  • Fix path parsing in WebRouter and add null coalescing fallback in HttpResponder.
  • Handle PHP Error conversion in ThrowableHandler without relying on assert.

Enhancements:

  • Add stricter type hints and return types, remove unused code, and resolve all Psalm/PHPStan issues.
  • Include symfony/polyfill-php83 for PHP 8.3 compatibility.

Build:

  • Raise minimum PHP requirement to 8.2 and streamline composer.json dependencies.
  • Move static analysis tools into vendor-bin/tools and reduce main require-dev to phpunit and composer-bin-plugin.

CI:

  • Configure GitHub CI to test PHP 8.2–8.5 and adjust old_stable matrix.
  • Update Scrutinizer settings to use jammy image and PHP 8.4.

Tests:

  • Update tests and bootstrap for attribute reader usage and modern syntax.
  • Remove redundant assertions and adapt resource instantiation in tests.

- Update vendor-bin/tools dependencies to latest versions
- Remove Doctrine annotations from DefaultSchemeHost, use PHP 8 attributes only
- Add #[Override] attributes and final keywords to reduce Psalm errors from 62 to 27

Fix all Psalm errors and improve type safety

- Update Psalm target PHP version from 7.4 to 8.2
- Suppress Unused* errors in psalm.xml (library code)
- Fix null/false handling in WebRouter::match()
- Replace ?: with ?? operator in HttpResponder for type safety
- Psalm errors reduced from 27 to 0

Fix all PHPStan errors in src directory

- Remove unnecessary assert() from ThrowableHandler
- Add proper type annotations and @phpstan-ignore for parse_str()
- Suppress trait.unused errors in phpstan.neon for deprecated traits
- PHPStan errors in src: 10 → 0
- All tests passing (28 tests, 59 assertions)
Add symfony/polyfill-php83 and update dev dependencies

- Add symfony/polyfill-php83 ^1.31 to support #[Override] in PHP 8.2
- Update vimeo/psalm from ^4.2 to ^6.0
- Update phpstan/phpstan from ^1.3 to ^2.0
- Update rector/rector from ^1.2.4 to ^2.0
- Update psalm/plugin-phpunit from ^0.13 to ^0.19
- All tests passing
- Remove static analysis and dev tools from main composer.json
- Keep only bamarni/composer-bin-plugin and phpunit in require-dev
- Tools (psalm, phpstan, phpcs, rector, etc.) managed in vendor-bin/tools
- Add post-install/update commands with --ignore-platform-req=php
- Set platform.php to 8.4.99 in vendor-bin/tools for compatibility
- Set build image to default-jammy.
- Update environment to use PHP 8.4.
- Simplify php-scrutinizer-run command.
- Retain src/* path filter.
- Simplify `catch` blocks by omitting unused exception variables.
@sourcery-ai
Copy link

sourcery-ai bot commented Nov 11, 2025

Reviewer's Guide

This PR replaces Doctrine annotations with native PHP attributes, raises the minimum PHP requirement to 8.2 (with polyfill support through 8.5), restructures development tooling and composer configurations, and resolves all static analysis issues by improving type safety and configuration files.

Entity relationship diagram for updated composer dependencies

erDiagram
    COMPOSER_JSON {
        string php
        string bear_resource
        string psr_log
        string ray_aop
        string ray_di
        string symfony_polyfill_php83
    }
    COMPOSER_JSON ||--o| COMPOSER_DEV_DEP : has
    COMPOSER_DEV_DEP {
        string bamarni_composer_bin_plugin
        string phpunit_phpunit
    }
    TOOLS_VENDOR_BIN {
        string doctrine_coding_standard
        string phpmd_phpmd
        string phpmetrics_phpmetrics
        string phpstan_phpstan
        string ray_rector_ray
        string rector_rector
        string squizlabs_php_codesniffer
        string vimeo_psalm
    }
    COMPOSER_DEV_DEP ||--o| TOOLS_VENDOR_BIN : manages
Loading

Class diagram for migration from Doctrine annotations to PHP 8 attributes

classDiagram
    class DefaultSchemeHost {
        <<Attribute>>
        <<Qualifier>>
    }
    class ThrowableHandler {
        +handle(Throwable $e, Request $request): ThrowableHandlerInterface
        +transfer(): void
    }
    class WebRouter {
        +match(array $globals, array $server)
        +generate($name, $data)
        -getQuery(string $method, array $globals, array $server): array
    }
    class NullHttpCache {
        +isNotModified(array $server): bool
        +transfer(): void
    }
    class NamedModule {
        +__construct(array $names)
        +configure(): void
    }
    class SundayModule {
        +configure(): void
    }
    class ErrorModule {
        +configure(): void
    }
    class RepresentationModule {
        +configure(): void
    }
    class RouterModule {
        +configure(): void
    }
    class HttpCacheModule {
        +configure(): void
    }
    class HttpResponder {
        +__invoke(ResourceObject $ro, array $server): void
        -getOutput(ResourceObject $ro, array $server): Output
    }
    class HttpResponderModule {
        +configure(): void
    }
    class NullError {
        +handle(Exception $e, Request $request)
        +transfer(): void
    }
    class VndError {
        +handle(Exception $e, Request $request)
        +transfer(): void
    }
    class ConditionalResponse {
        +isModified(ResourceObject $ro, array $server): bool
        +getOutput(array $headers): Output
    }
    class NullMatch {
    }
    class RouterMatch {
        +__toString(): string
    }
    class NullTransfer {
        +__invoke(ResourceObject $ro, array $server): void
    }
    class ErrorPage {
    }
    class Header {
        +__invoke(ResourceObject $ro, array $server): array
    }
    class BadRequestJsonException {
    }
    class LogicException {
    }
    class RuntimeException {
    }
    DefaultSchemeHost --|> Attribute
    DefaultSchemeHost --|> Qualifier
    BadRequestJsonException --|> ExceptionInterface
    LogicException --|> ExceptionInterface
    RuntimeException --|> ExceptionInterface
    NullMatch --|> RouterMatch
    ErrorPage --|> ResourceObject
    ThrowableHandler --|> ThrowableHandlerInterface
    NullHttpCache --|> HttpCacheInterface
    NullError --|> ErrorInterface
    VndError --|> ErrorInterface
    ConditionalResponse --|> ConditionalResponseInterface
    NullTransfer --|> TransferInterface
    Header --|> HeaderInterface
    HttpResponder --|> TransferInterface
    WebRouter --|> RouterInterface
    NamedModule --|> AbstractModule
    SundayModule --|> AbstractModule
    ErrorModule --|> AbstractModule
    RepresentationModule --|> AbstractModule
    RouterModule --|> AbstractModule
    HttpCacheModule --|> AbstractModule
    HttpResponderModule --|> AbstractModule
Loading

File-Level Changes

Change Details Files
Migrate from Doctrine annotations to PHP 8 attributes
  • Apply #[Attribute] and #[Override] to override methods
  • Remove Doctrine annotation imports and metadata comments
  • Mark key classes and modules as final for stricter inheritance control
src/Annotation/DefaultSchemeHost.php
src/Provide/Error/ThrowableHandler.php
src/Provide/Router/WebRouter.php
src/Module/*
src/Extension/*
src/Provide/*
Enhance type safety and fix static analysis errors
  • Add explicit type hints, return types, and readonly properties
  • Replace assert() calls with conditional logic or typed comments
  • Adjust DataObject and HTTP response handling for nullable and union types
src/Provide/Transfer/HttpResponder.php
tests/Inject/*
tests/Module/*
tests/Fake/Apps/*
tests/bootstrap.php
Raise PHP version support and adjust CI matrix
  • Update composer.json minimum php to ^8.2 and add symfony/polyfill-php83
  • Configure CI to run on PHP 8.2–8.5 and demote 8.2 to old_stable
  • Switch Scrutinizer image to jammy with PHP 8.4
composer.json
.github/workflows/continuous-integration.yml
.scrutinizer.yml
Restructure development tooling and composer scripts
  • Move static analysis tools into vendor-bin/tools composer.json
  • Reduce main require-dev to only bin-plugin and PHPUnit
  • Add post-install/update scripts to bootstrap vendor-bin tooling
composer.json
vendor-bin/tools/composer.json
Update static analysis configurations
  • Bump psalm.xml phpVersion to 8.2 and suppress unused issues
  • Add new phpstan.neon configuration file
  • Refine CI static analysis settings
psalm.xml
phpstan.neon

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

PHP minimum version bumped to 8.2 with updated configurations. Classes made final throughout, #[Override] attributes added to override methods. Development dependencies moved to vendor-bin tools directory with bamarni/composer-bin-plugin. Minor code cleanup: removed unused catch variables, legacy annotations, and rector configuration.

Changes

Cohort / File(s) Summary
Platform & Version Configuration
.github/workflows/continuous-integration.yml, composer.json, .scrutinizer.yml, phpstan.neon, psalm.xml
Updated PHP minimum requirement from ^8.0 to ^8.2. Adjusted CI workflow to remove PHP 8.1 from old_stable list. Updated Psalm configuration to PHP 8.2 and added issue handler suppressions. Updated Scrutinizer build image to default-jammy with PHP 8.4. Added dependency: symfony/polyfill-php83.
Exception Classes – Finalization
src/Exception/BadRequestJsonException.php, src/Exception/LogicException.php, src/Exception/RuntimeException.php
Made classes final to prevent further extension while preserving inheritance hierarchy and interfaces.
Module Classes – Finalization with Override
src/Module/Constant/NamedModule.php, src/Module/SundayModule.php, src/Provide/Error/ErrorModule.php, src/Provide/Representation/RepresentationModule.php, src/Provide/Router/RouterModule.php, src/Provide/Transfer/HttpCacheModule.php, src/Provide/Transfer/HttpResponderModule.php
Made all module classes final and added #[Override] attribute to configure() methods to mark inherited method overrides.
Error Handling Classes
src/Extension/Error/NullError.php, src/Provide/Error/ErrorPage.php, src/Provide/Error/ThrowableHandler.php, src/Provide/Error/VndError.php
Added #[Override] attributes to public handler and transfer methods; made ErrorPage final. Refactored ThrowableHandler with explicit if-block for Error type checking and added docblock annotations.
Transfer & Router Classes – Override Attributes
src/Extension/Transfer/NullHttpCache.php, src/Extension/Transfer/NullTransfer.php, src/Extension/Router/NullMatch.php, src/Extension/Router/RouterMatch.php, src/Provide/Transfer/ConditionalResponse.php, src/Provide/Transfer/Header.php, src/Provide/Transfer/HttpResponder.php, src/Provide/Router/WebRouter.php
Added #[Override] attributes to override methods and made NullMatch final. Updated WebRouter with path extraction refactoring and null-coalescing operator for view property. Updated HttpResponder to use null-coalescing for fallback logic.
Legacy Code Cleanup
src/Annotation/DefaultSchemeHost.php, demo/public/index.php, rector.php
Removed Doctrine annotation imports and legacy PHPDoc from DefaultSchemeHost. Removed unused catch variables from exception handlers. Deleted rector.php configuration file.
Dependency Management
composer.json, vendor-bin/tools/composer.json
Reorganized development dependencies into vendor-bin/tools structure using bamarni/composer-bin-plugin. Removed: doctrine/coding-standard, phpmd/phpmd, phpmetrics/phpmetrics, phpstan/phpstan, psalm/plugin-phpunit, ray/rector-ray, rector/rector, squizlabs/php_codesniffer, vimeo/psalm. Added post-install-cmd and post-update-cmd hooks for composer bin operations.
Test Files
tests/Provide/Error/ThrowableHandlerTest.php, tests/Inject/PsrLoggerInjectTest.php, tests/Module/Constant/NamedModuleTest.php, tests/bootstrap.php, tests/Fake/Apps/FakeVendor/HelloWorldX/Resource/App/Greeting.php
Removed assert import and runtime assertions from test setup. Changed test echo value from hello to HELLO. Updated callback from string 'unlink' to unlink(...) variadic form. Added readonly modifier to promoted constructor property.

Sequence Diagram

sequenceDiagram
    participant Client
    participant WebRouter
    participant PathParser as Path Parser
    participant Matcher as Route Matcher
    participant Handler as Error Handler

    Note over Client,Handler: WebRouter::match() - Path Extraction Refactoring
    Client->>WebRouter: match($globals, $server)
    WebRouter->>PathParser: parse_url($uri, PHP_URL_PATH)
    PathParser-->>WebRouter: $path (or null)
    alt Path is null/false
        WebRouter->>WebRouter: $path = '/'
    end
    WebRouter->>Matcher: match with $path
    Matcher-->>WebRouter: route match result
    WebRouter-->>Client: matched route

    Note over Client,Handler: ThrowableHandler - Error Type Checking
    Client->>Handler: handle($e, $request)
    alt $e instanceof Error
        Handler->>Handler: wrap Error in ErrorException
    else
        Handler->>Handler: use Exception as-is
    end
    Handler->>Handler: $this->error->handle($e, $request)
    Handler-->>Client: ThrowableHandlerInterface
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Dependency reorganization: vendor-bin/tools structure and composer plugin configuration requires careful validation
  • Finalization strategy: Review ~20 classes made final to ensure no external subclassing dependencies exist
  • Override attributes: Verify all #[Override] attributes are applied to actual parent method overrides (40+ occurrences)
  • WebRouter path logic: Path normalization and null-coalescing changes impact routing behavior
  • HttpResponder view handling: Null-coalescing operator changes empty-string handling semantics
  • ThrowableHandler refactoring: Error-to-ErrorException wrapping logic with new if-block structure
  • Configuration migration: PHP 8.2+ compatibility in phpstan.neon and psalm.xml with new suppression rules

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main changes: migrating to PHP 8.2+, removing Doctrine annotations, and improving type safety—all core objectives of the changeset.
Description check ✅ Passed The PR description is comprehensive and directly related to the changeset, covering migration to PHP 8 attributes, minimum PHP version changes, type safety improvements, and tooling reorganization.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (d044de5) to head (e8bd1f9).
⚠️ Report is 8 commits behind head on 1.x.

Additional details and impacted files
@@             Coverage Diff             @@
##                 1.x      #186   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
- Complexity        51        52    +1     
===========================================
  Files             18        18           
  Lines            141       123   -18     
===========================================
- Hits             141       123   -18     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Make sure the Override attribute has a valid namespace and class definition since use Override; alone may not resolve to an actual attribute.
  • Confirm that moving static analysis tools into vendor-bin/tools still installs and executes them properly in your CI and local workflows.
  • Consider reducing the number of suppressed Psalm issue handlers to avoid masking potential problems introduced in this migration.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Make sure the Override attribute has a valid namespace and class definition since `use Override;` alone may not resolve to an actual attribute.
- Confirm that moving static analysis tools into `vendor-bin/tools` still installs and executes them properly in your CI and local workflows.
- Consider reducing the number of suppressed Psalm issue handlers to avoid masking potential problems introduced in this migration.

## Individual Comments

### Comment 1
<location> `src/Provide/Router/WebRouter.php:51-55` </location>
<code_context>
     public function match(array $globals, array $server)
     {
         $method = strtolower($server['REQUEST_METHOD']);
+        $path = parse_url($server['REQUEST_URI'], PHP_URL_PATH);
+        $path = $path === false || $path === null ? '/' : $path;

         return new RouterMatch(
</code_context>

<issue_to_address>
**suggestion:** Consider normalizing the path to avoid double slashes when concatenating with schemeHost.

Trim the trailing slash from schemeHost or the leading slash from path before concatenation to prevent double slashes in the URI.

```suggestion
        // Normalize schemeHost and path to avoid double slashes
        $schemeHost = rtrim($this->schemeHost, '/');
        // Only trim leading slash if path is not just "/"
        $normalizedPath = $path === '/' ? '' : ltrim($path, '/');
        $uri = $schemeHost . '/' . $normalizedPath;

        return new RouterMatch(
            $method,
            $uri,
            $this->getQuery($method, $globals, $server),
        );
```
</issue_to_address>

### Comment 2
<location> `src/Provide/Transfer/HttpResponder.php:43-45` </location>
<code_context>
     {
         $ro->toString(); // render and set headers

-        return new Output($ro->code, ($this->header)($ro, $server), $ro->view ?: $ro->toString());
+        return new Output($ro->code, ($this->header)($ro, $server), $ro->view ?? $ro->toString());
     }
 }
</code_context>

<issue_to_address>
**question:** Switching from ?: to ?? may change behavior if $ro->view is set but falsy.

If you intend to fallback only when $ro->view is null, this change is correct. Otherwise, revert to ?: to handle all falsy values.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@koriym
Copy link
Member Author

koriym commented Nov 11, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d044de5 and bc85356.

⛔ Files ignored due to path filters (1)
  • vendor-bin/tools/composer.lock is excluded by !**/*.lock
📒 Files selected for processing (36)
  • .github/workflows/continuous-integration.yml (1 hunks)
  • .scrutinizer.yml (1 hunks)
  • composer.json (2 hunks)
  • demo/public/index.php (1 hunks)
  • phpstan.neon (1 hunks)
  • psalm.xml (2 hunks)
  • rector.php (0 hunks)
  • src/Annotation/DefaultSchemeHost.php (0 hunks)
  • src/Exception/BadRequestJsonException.php (1 hunks)
  • src/Exception/LogicException.php (1 hunks)
  • src/Exception/RuntimeException.php (1 hunks)
  • src/Extension/Error/NullError.php (1 hunks)
  • src/Extension/Router/NullMatch.php (1 hunks)
  • src/Extension/Router/RouterMatch.php (2 hunks)
  • src/Extension/Transfer/NullHttpCache.php (1 hunks)
  • src/Extension/Transfer/NullTransfer.php (2 hunks)
  • src/Module/Constant/NamedModule.php (2 hunks)
  • src/Module/SundayModule.php (1 hunks)
  • src/Provide/Error/ErrorModule.php (1 hunks)
  • src/Provide/Error/ErrorPage.php (1 hunks)
  • src/Provide/Error/ThrowableHandler.php (2 hunks)
  • src/Provide/Error/VndError.php (3 hunks)
  • src/Provide/Representation/RepresentationModule.php (1 hunks)
  • src/Provide/Router/RouterModule.php (2 hunks)
  • src/Provide/Router/WebRouter.php (4 hunks)
  • src/Provide/Transfer/ConditionalResponse.php (3 hunks)
  • src/Provide/Transfer/Header.php (1 hunks)
  • src/Provide/Transfer/HttpCacheModule.php (1 hunks)
  • src/Provide/Transfer/HttpResponder.php (3 hunks)
  • src/Provide/Transfer/HttpResponderModule.php (2 hunks)
  • tests/Fake/Apps/FakeVendor/HelloWorldX/Resource/App/Greeting.php (1 hunks)
  • tests/Inject/PsrLoggerInjectTest.php (0 hunks)
  • tests/Module/Constant/NamedModuleTest.php (0 hunks)
  • tests/Provide/Error/ThrowableHandlerTest.php (1 hunks)
  • tests/bootstrap.php (1 hunks)
  • vendor-bin/tools/composer.json (1 hunks)
💤 Files with no reviewable changes (4)
  • tests/Inject/PsrLoggerInjectTest.php
  • rector.php
  • tests/Module/Constant/NamedModuleTest.php
  • src/Annotation/DefaultSchemeHost.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (34)
src/Provide/Transfer/Header.php (1)

8-15: Verified: Polyfill is properly configured and Override attributes are correctly used.

The symfony/polyfill-php83 (^1.31) is configured in composer.json, and all 17 files using the #[Override] attribute have the corresponding use Override; import statement. The implementation in src/Provide/Transfer/Header.php is correct and follows the established pattern across the codebase.

phpstan.neon (1)

9-11: The original review comment is incorrect. The traits are actively used—specifically in tests/Fake/Inject/ test files. However, since that directory is explicitly excluded from PHPStan analysis via excludePaths: */tests/Fake/*, PHPStan cannot see the usage and incorrectly reports them as unused.

The suppression in phpstan.neon is a legitimate workaround for this false positive, not a mask for genuinely unused code. No changes are needed.

Likely an incorrect or invalid review comment.

.github/workflows/continuous-integration.yml (1)

12-12: LGTM! PHP 8.1 removal aligns with minimum version bump.

Removing PHP 8.1 from the CI test matrix is consistent with the PR objective to raise the minimum PHP requirement to 8.2.

demo/public/index.php (1)

29-29: LGTM! Non-capturing catch syntax improves clarity.

Removing unused exception variables is a good cleanup that leverages PHP 8.0+'s non-capturing catch syntax.

Also applies to: 32-32

psalm.xml (2)

4-4: LGTM! PHP version updated correctly.

Updating the Psalm PHP version target to 8.2 aligns with the minimum version requirement.


21-24: Consider reviewing the need for these suppressions.

Adding suppressions for UnusedClass, PossiblyUnusedMethod, PossiblyUnusedProperty, and PossiblyUnusedReturnValue may hide legitimate dead code or API design issues. These are typically valuable signals during refactoring.

Were these suppressions added to work around specific false positives, or to silence warnings on intentionally exported public API? If the latter, consider documenting which public APIs are intentionally unused internally.

tests/bootstrap.php (1)

9-9: LGTM! First-class callable syntax is cleaner.

Using unlink(...) leverages PHP 8.1's first-class callable syntax, which is more explicit and type-safe than passing the function name as a string.

.scrutinizer.yml (1)

2-4: LGTM! Updated to Ubuntu Jammy with PHP 8.4.

The upgrade to default-jammy (Ubuntu 22.04) with PHP 8.4 aligns with the PHP version modernization in this PR.

src/Extension/Router/NullMatch.php (1)

7-7: LGTM! Making leaf class final is good practice.

Declaring NullMatch as final prevents unintended inheritance and clearly communicates design intent.

vendor-bin/tools/composer.json (1)

1-22: LGTM with verification suggestion.

The tooling configuration follows best practices for isolated vendor-bin setup. All dependency versions are current and appropriate for PHP 8.2+ static analysis.

The platform lock to "php": "8.4.99" at line 19 is unusually forward-looking. Verify this is intentional for testing against PHP 8.4 features, as it may cause compatibility warnings if any dependencies have strict PHP version constraints.

src/Module/Constant/NamedModule.php (1)

7-7: LGTM! Excellent modernization improvements.

The addition of final class modifier and #[Override] attribute enhances type safety and prevents unintended inheritance. These changes follow PHP 8.3+ best practices with no behavioral impact.

Also applies to: 10-10, 19-19

tests/Fake/Apps/FakeVendor/HelloWorldX/Resource/App/Greeting.php (1)

12-12: LGTM! Good use of readonly for immutability.

The readonly modifier on the injected ResourceInterface dependency prevents accidental mutation and leverages PHP 8.1+ immutability features. This is appropriate for constructor-injected dependencies.

src/Extension/Transfer/NullHttpCache.php (1)

7-7: LGTM! Proper use of Override attribute.

The #[Override] attributes on both interface implementation methods provide compile-time verification and improve code clarity. No behavioral changes.

Also applies to: 14-15, 20-21

src/Exception/LogicException.php (1)

7-9: LGTM! Appropriate use of final modifier.

Making the exception class final is a best practice that prevents unintended inheritance while preserving functionality. This aligns with the project-wide pattern of finalizing exception classes.

src/Provide/Transfer/HttpResponder.php (1)

9-9: LGTM! Proper Override attribute usage.

The #[Override] attribute on the __invoke() method provides compile-time verification of interface implementation with no behavioral changes.

Also applies to: 22-23

src/Provide/Transfer/ConditionalResponse.php (1)

8-8: LGTM! Correct Override attribute usage.

The #[Override] attributes on both interface implementation methods (isModified() and getOutput()) provide compile-time verification with no behavioral impact.

Also applies to: 27-28, 36-37

src/Module/SundayModule.php (1)

12-12: LGTM! Excellent modernization improvements.

The combination of final class modifier and #[Override] attribute enhances type safety and prevents unintended inheritance. These PHP 8.3+ improvements have no behavioral impact and align with project-wide modernization efforts.

Also applies to: 18-18, 20-21

src/Extension/Transfer/NullTransfer.php (1)

8-8: LGTM! Override attribute correctly applied.

The #[Override] attribute properly marks the interface implementation.

Also applies to: 17-17

src/Extension/Error/NullError.php (1)

9-9: LGTM! Override attributes correctly applied.

The #[Override] attributes properly mark the interface implementations.

Also applies to: 16-16, 22-22

composer.json (2)

24-24: Breaking change: PHP 8.2 minimum requirement.

This aligns with the PR objectives but is a breaking change for users on PHP 8.0 or 8.1.


32-33: Vendor-bin tooling setup is correctly configured. The migration is complete with all dev tools properly moved to vendor-bin/tools/composer.json, post-install/post-update hooks correctly configured in the root composer.json to manage the vendor-bin dependencies, and the root composer.json appropriately reduced to only the bin-plugin and phpunit.

src/Provide/Router/WebRouter.php (2)

11-11: LGTM! Override attributes correctly applied.

The #[Override] attributes properly mark the interface method implementations.

Also applies to: 44-44, 61-61


92-92: PHPStan ignore annotation added for parse_str output.

The @phpstan-ignore varTag.nativeType annotation suppresses a type mismatch warning for the $put variable populated by parse_str(). This is acceptable since parse_str() doesn't have precise type information.

src/Provide/Router/RouterModule.php (2)

20-20: LGTM! Module class made final.

Making the module class final prevents unintended inheritance and aligns with best practices.


9-9: LGTM! Override attribute correctly applied.

The #[Override] attribute properly marks the AbstractModule::configure() override.

Also applies to: 22-22

src/Provide/Error/ErrorPage.php (1)

9-9: LGTM! Error page class made final.

Making the class final prevents unintended inheritance and is consistent with the broader refactoring in this PR.

tests/Provide/Error/ThrowableHandlerTest.php (1)

43-43: Cosmetic test change: helloHELLO.

Both echo hello; and echo HELLO; trigger an Error for an undefined constant in PHP 8.2+, so this change doesn't affect the test behavior. The uppercase version may be more conventional for constants.

src/Exception/BadRequestJsonException.php (1)

9-9: LGTM! Exception class made final.

Making the exception class final prevents unintended inheritance and is consistent with the broader refactoring pattern in this PR.

src/Exception/RuntimeException.php (1)

7-7: LGTM! Final exception class aligns with best practices.

Making the exception class final prevents unintended inheritance and is a sensible design choice for framework exception types. This breaking change is appropriately documented in the PR objectives.

src/Provide/Error/VndError.php (1)

15-15: LGTM! Override attributes correctly applied.

The #[Override] attributes on handle() and transfer() correctly indicate these methods implement the ErrorInterface. This improves type safety by ensuring the signatures remain synchronized with the interface.

Also applies to: 47-47, 65-65

src/Provide/Representation/RepresentationModule.php (1)

9-9: LGTM! Consistent module hardening pattern.

The combination of final class declaration and #[Override] attribute on configure() follows the project-wide pattern for DI modules. This prevents unintended inheritance while ensuring the method signature stays synchronized with AbstractModule.

Also applies to: 13-13, 15-15

src/Provide/Error/ErrorModule.php (1)

9-9: LGTM! Follows the established module pattern.

Consistent with other modules in this PR: final class and #[Override] on configure().

Also applies to: 12-12, 14-14

src/Provide/Transfer/HttpCacheModule.php (1)

9-9: LGTM! Consistent module hardening.

Same pattern applied: final class and #[Override] on configure().

Also applies to: 15-15, 17-17

src/Provide/Error/ThrowableHandler.php (1)

13-13: LGTM! Override attributes correctly applied.

The #[Override] attributes on handle() and transfer() correctly indicate these methods implement ThrowableHandlerInterface.

Also applies to: 25-25, 38-38

Remove trailing slashes from schemeHost in constructor to ensure
$this->schemeHost . $path never produces double slashes
Pass original Error as $previous parameter to maintain stack trace
and chained exception handling
@koriym koriym merged commit 589bd9b into 1.x Nov 11, 2025
34 checks passed
@koriym koriym deleted the php82 branch November 11, 2025 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant