PHP 8.4 / Symfony 6.4 upgrade #20

Merged
mrouissi merged 7 commits from feature/php84-symfony64 into master 2026-05-30 13:14:50 +02:00
Owner

Summary

Upgrades adressermittlung.de from PHP 7.4 / Symfony 3.4 to PHP 8.4 / Symfony 6.4 LTS.

Repository restructure

  • App moved from wf10501/www/ to the repo root (matches server layout + standard Symfony); stop tracking the server home dir and vendor_old/.

Framework migration (3.4 -> 6.4 LTS)

  • Symfony components -> 6.4; Twig 2 -> 3; Doctrine bundle 2.x / migrations 3.x
  • Swiftmailer -> symfony/mailer (MAILER_DSN); mailer pinned to 6.4; PHP >=8.1
  • @Route / @IsGranted annotations -> PHP 8 attributes
  • getDoctrine() -> injected ManagerRegistry; $this->get(session) -> RequestStack
  • UserPasswordEncoderInterface -> UserPasswordHasherInterface
  • SF6 front controller; prod Doctrine cache type: pool; server_version -> mariadb-10.11.17

Database

  • Migration metadata modernized to doctrine-migrations 3.x
  • user.roles legacy json_array -> native json

Testing (dev = https://dev.adressermittlung.de)

  • Prod container compiles, 146 routes load
  • Public + portal pages 200; login + auth redirects OK
  • Mailer SMTP verified; RISER SOAP loads on 8.4; Stripe SDK functional

Planned follow-ups (NOT in this PR)

  • Phase 2: replace abandoned paypal/rest-api-sdk-php
  • Phase 3: bump to Symfony 7.4 LTS (+ residual 6.4/7.x mix & deprecation cleanup)

Prod promotion checklist (wfweb012)

  • Set prod MAILER_DSN (only old Swiftmailer MAILER_URL present)
  • Migrations: sync-metadata-storage -> mark 2019 migrations applied -> migrate
  • composer install on PHP 8.4; switch fpm pool to 8.4
## Summary Upgrades adressermittlung.de from PHP 7.4 / Symfony 3.4 to **PHP 8.4 / Symfony 6.4 LTS**. ### Repository restructure - App moved from `wf10501/www/` to the repo root (matches server layout + standard Symfony); stop tracking the server home dir and `vendor_old/`. ### Framework migration (3.4 -> 6.4 LTS) - Symfony components -> 6.4; Twig 2 -> 3; Doctrine bundle 2.x / migrations 3.x - Swiftmailer -> symfony/mailer (MAILER_DSN); mailer pinned to 6.4; PHP `>=8.1` - `@Route` / `@IsGranted` annotations -> PHP 8 attributes - `getDoctrine()` -> injected ManagerRegistry; `$this->get(session)` -> RequestStack - UserPasswordEncoderInterface -> UserPasswordHasherInterface - SF6 front controller; prod Doctrine cache `type: pool`; server_version -> mariadb-10.11.17 ### Database - Migration metadata modernized to doctrine-migrations 3.x - `user.roles` legacy `json_array` -> native `json` ## Testing (dev = https://dev.adressermittlung.de) - Prod container compiles, 146 routes load - Public + portal pages 200; login + auth redirects OK - Mailer SMTP verified; RISER SOAP loads on 8.4; Stripe SDK functional ## Planned follow-ups (NOT in this PR) - Phase 2: replace abandoned paypal/rest-api-sdk-php - Phase 3: bump to Symfony 7.4 LTS (+ residual 6.4/7.x mix & deprecation cleanup) ## Prod promotion checklist (wfweb012) - Set prod MAILER_DSN (only old Swiftmailer MAILER_URL present) - Migrations: sync-metadata-storage -> mark 2019 migrations applied -> migrate - composer install on PHP 8.4; switch fpm pool to 8.4
Author
Owner

Code review findings

Reviewed via a multi-angle pass and verified against the running dev site. Note: two finder claims of "breaks all routing" were verified falseSymfony\Component\Routing\Annotation\Route still exists as a deprecated alias in routing 7.4, and the missing-TestController route only 500s if that URL is hit (Symfony resolves controllers lazily).

Real bugs — fixed in this PR

  1. Silent RISER email failuresMailer::sendResultEmail() no longer returns a recipient count (Swiftmailer did; symfony/mailer returns void), but GetResultsCommand still did if ($nrMailsSent === 0) to detect failure → always false → a failed result email was logged as "successful". Fixed: send wrapped in try/catch on the thrown TransportException (and no longer aborts the batch).
  2. GetResultsCommand TypeError risk on PHP 8.4setHost(getenv(WEBSITE_HOST)) had no fallback (sibling commands got ?:); getenv returns false when unset → setHost(false) TypeError. Fixed: added ?: localhost / ?: https.
  3. Dead/broken routecreate_test_customer pointed at a non-existent App\Controller\TestController (also a test-data endpoint that should not ship). Fixed: removed.

Security / behaviour — fixed in this PR

  1. Login account-enumeration — the account-disabled check ran in the user loader before password verification, so a disabled account revealed its state to anyone submitting the email with any password. Fixed: moved to App\Security\UserChecker::checkPostAuth(), which runs only after the password is verified.

Deprecations — deferred to Phase 3 (Symfony 7.4)

  1. EntityManager::merge() used ~12x in InquiryController — works on ORM 2.x, removed in ORM 3.
  2. use Symfony\Component\Routing\Annotation\Route in 6 controllers — deprecated alias (works on 7.4, removed in 8.0); inconsistent with Portal/Security which use Attribute\Route.

Cleanup

  1. getDoctrine() shim duplicated across 6 controllers (PortalController injects the EM directly) — a trait/base controller would be cleaner. [deferred]
  2. CustomerController @param docblocks referenced a non-existent FQCN. Fixed.
  3. services.yaml leftover static_route_loader alias + # FIX banners. [deferred]
  4. Stale \Twig_Error_* docblocks; security.yaml ^/login$ rule does not match the /login/ route. [deferred]
## Code review findings Reviewed via a multi-angle pass and verified against the running dev site. Note: two finder claims of "breaks all routing" were verified **false** — `Symfony\Component\Routing\Annotation\Route` still exists as a deprecated alias in routing 7.4, and the missing-`TestController` route only 500s if that URL is hit (Symfony resolves controllers lazily). ### Real bugs — fixed in this PR 1. **Silent RISER email failures** — `Mailer::sendResultEmail()` no longer returns a recipient count (Swiftmailer did; symfony/mailer returns void), but `GetResultsCommand` still did `if ($nrMailsSent === 0)` to detect failure → always false → a failed result email was logged as "successful". Fixed: send wrapped in try/catch on the thrown `TransportException` (and no longer aborts the batch). 2. **`GetResultsCommand` TypeError risk on PHP 8.4** — `setHost(getenv(WEBSITE_HOST))` had no fallback (sibling commands got `?:`); `getenv` returns `false` when unset → `setHost(false)` TypeError. Fixed: added `?: localhost` / `?: https`. 3. **Dead/broken route** — `create_test_customer` pointed at a non-existent `App\Controller\TestController` (also a test-data endpoint that should not ship). Fixed: removed. ### Security / behaviour — fixed in this PR 4. **Login account-enumeration** — the account-disabled check ran in the user loader *before* password verification, so a disabled account revealed its state to anyone submitting the email with any password. Fixed: moved to `App\Security\UserChecker::checkPostAuth()`, which runs only after the password is verified. ### Deprecations — deferred to Phase 3 (Symfony 7.4) 5. `EntityManager::merge()` used ~12x in `InquiryController` — works on ORM 2.x, removed in ORM 3. 6. `use Symfony\Component\Routing\Annotation\Route` in 6 controllers — deprecated alias (works on 7.4, removed in 8.0); inconsistent with Portal/Security which use `Attribute\Route`. ### Cleanup 7. `getDoctrine()` shim duplicated across 6 controllers (PortalController injects the EM directly) — a trait/base controller would be cleaner. [deferred] 8. `CustomerController` `@param` docblocks referenced a non-existent FQCN. Fixed. 9. `services.yaml` leftover `static_route_loader` alias + `# FIX` banners. [deferred] 10. Stale `\Twig_Error_*` docblocks; `security.yaml` `^/login$` rule does not match the `/login/` route. [deferred]
mrouissi merged commit 4c66057ad5 into master 2026-05-30 13:14:50 +02:00
mrouissi deleted branch feature/php84-symfony64 2026-05-30 13:14:55 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Clients/neveling!20
No description provided.