Skip to content

feat: support Symfony 8 - #49

Merged
alxvgt merged 2 commits into
Youtrust:mainfrom
alxvgt:symfony-8
Aug 12, 2026
Merged

alxvgt merged 2 commits into
Youtrust:mainfrom
alxvgt:symfony-8

Conversation

@alxvgt

@alxvgt alxvgt commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Adds Symfony 8 support, so the bundle can be installed on an application running Symfony 8.1 and PHP 8.5.

Same need as safe-migrations#7: a new Yousign service runs ahead of the rest of the estate, and symfony/console: ^6.2|^7.0 blocked the install.

One real behaviour change, not just constraints

Widening the constraints was not enough. Symfony 8 changed how a message that cannot be rebuilt is reported.

MessageDecodingFailedException::wrap() no longer throws. It returns an Envelope whose message is the exception:

// vendor/symfony/messenger/Exception/MessageDecodingFailedException.php
public static function wrap(array $encodedEnvelope, string $message, ...): Envelope
{
    return new Envelope(new self($message, $code, $previous, $encodedEnvelope));
}

ZddMessageMessengerSerializer::deserialize() catches MessageDecodingFailedException, which now never arrives. It returned the exception object as if it were the message, and ZddMessageAsserter then reported:

Class mismatch between $messageFqcn … Please verify your integration.

That is the wrong answer to the right question: a message that no longer deserializes is exactly the zero-downtime breach this bundle exists to catch, and the user was told to check their integration instead. deserialize() now recognises both shapes — the returned envelope on Symfony 8, and the thrown exception on 6.2 and 7.

ZddMessageAsserterTest::testItThrowsExceptionForInvalidPropertyType is what surfaced it.

The rest

  • PHPStan ^1.10 → ^2.1. PHPStan 1.x cannot parse Symfony 8 and reports its classes as unknown (extends unknown class Symfony\Component\Console\Command\Command). Under PHPStan 2 the @var on the json_decode() result no longer holds, so it moves to the assignment it actually describes, and the redundant instanceof Envelope check goes — decode() is typed : Envelope.
  • ReflectionProperty::setAccessible() removed from MessageGenerator. Deprecated in PHP 8.5, and without effect since 8.1. Left in place it makes every PHP 8.5 run noisy.
  • CI matrix gains PHP 8.4 and 8.5, in both high-deps and low-deps. Without them the new support is never exercised.
  • The PHPStan job now runs the project's own PHPStan, with the command from the Makefile. php-actions/phpstan brings its own version, which cannot be kept in step with composer.json. This is the one change I could not run locally, so it is the job to watch on this PR.
  • composer.lock is gitignored here, so it is not part of the diff.

How this was checked

Every command below ran on PHP 8.5.9, in the Docker image of the application that needs this bundle.

Check Result
vendor/bin/phpunit, Symfony 8.1 26 tests, 78 assertions, green
vendor/bin/phpunit, --prefer-lowest (Symfony 6.2) 25 tests, 77 assertions, green
vendor/bin/phpstan analyse src --level=9 no errors
vendor/bin/php-cs-fixer --dry-run fix src no change

The low-deps run first failed with 6 errors. That was a stale var/cache left by the previous run, not an incompatibility — it passes from a clean cache. Worth knowing if you see the same locally.

Widen symfony/console and the Symfony dev dependencies to ^8.0.

Symfony 8 changed how a message that cannot be rebuilt is reported:
MessageDecodingFailedException::wrap() no longer throws, it returns an Envelope
carrying the failure as its message. ZddMessageMessengerSerializer caught an
exception that never arrives, so a broken message was reported as a class
mismatch instead of a deserialization failure — exactly the case this bundle
exists to detect. It now recognises both shapes.

PHPStan goes to ^2.1: 1.x cannot parse Symfony 8 and reports its classes as
unknown. Under PHPStan 2 the @var on the json_decode result no longer holds, so
it moves to the assignment it really describes.

Drops a ReflectionProperty::setAccessible() call, deprecated in PHP 8.5 and
without effect since 8.1.

The test matrix gains PHP 8.4 and 8.5, in both high-deps and low-deps mode.
Without them the new support would never be exercised.
@B-Galati

Copy link
Copy Markdown
Contributor

Would you have time to only allow PHP 8.4+ and Symfony 7.4+ please?

The Test matrix is a bit heavy now 😅

Shrinks the test matrix from ten cells to four, as asked in review.

The compatibility code in ZddMessageMessengerSerializer stays: Symfony 7.4
still throws MessageDecodingFailedException, and wrap() does not exist there.
The returned-envelope shape is Symfony 8 only, so both paths are real. The
low-deps mode now floors at 7.4, which exercises the throwing one.
@alxvgt

alxvgt commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator Author

Done — php: ^8.4, Symfony ^7.4|^8.0, and the matrix goes from ten cells to four.

One thing worth knowing, since it decides whether part of this PR is dead code: the compatibility branch in ZddMessageMessengerSerializer is still needed at 7.4. MessageDecodingFailedException::wrap() does not exist there, and PhpSerializer::decode() throws:

// symfony/messenger 7.4
throw new MessageDecodingFailedException('Could not decode Envelope: '.$e->getMessage(), 0, $e);

Returning an envelope that carries the failure is Symfony 8 only. So both paths are real, and low-deps now floors at 7.4.0, which exercises the throwing one.

Checked on PHP 8.5 with both modes: 26 tests green in each, PHPStan level 9 clean, php-cs-fixer clean. Note that low-deps used to run 25 tests on Symfony 6.2 — the extra one comes back at 7.4.

— 🤖 Claude

@B-Galati B-Galati left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the extra mile 💪 !

@alxvgt
alxvgt merged commit 36f90fa into Youtrust:main Aug 12, 2026
6 checks passed
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.

2 participants