Skip to content
N1
Legacy · Symfony · stack upgrade

Modernizing a Symfony application: from a 2023 project to a current stack

Client: Personal project Category: Legacy Stack: PHP 8.3, Symfony 6.4, Symfony Security, Doctrine ORM 3.6 and Migrations, PostgreSQL 18, PHPUnit, Twig, Bootstrap 5, Docker Compose, GitHub Actions, GHCR Timeline: original version — 2023, modernization — July 2026
Problem

A mini social network on Symfony, written in 2023, was stuck on an outdated stack: passwords were stored as md5, authentication was home-grown, and there were no tests or automated checks — any upgrade risked breaking the app.

Constraints

The stack had to be upgraded without losing existing users: old md5 passwords had to keep working until they moved to a modern hash. There were no tests, so functional tests were written before the authentication rework.

What I did
  • Upgrade to PHP 8.3, Symfony 6.4 LTS and Doctrine ORM 3.6 in one consistent step: +2226/−2058 lines, packages and configuration brought up to the new versions
  • Home-grown authentication replaced with Symfony Security: sessions and CSRF protection on all POST actions
  • Passwords moved from md5 to modern hashing with Symfony PasswordHasher; the old hash is transparently rehashed on the first successful login
  • 7 functional tests for key scenarios: feed, registration and login, posting, comments, likes, logout, language switch
  • CI/CD in GitHub Actions: Composer and syntax checks, YAML/Twig/container linters, migrations and PHPUnit on PostgreSQL, Docker image publishing to GHCR
  • Russian and English interface, the Doctrine schema synced with the model, the demo module removed, post likes added
Architecture
Symfony 6.4 / PHP 8.3 → Symfony Security → Doctrine ORM 3.6 + migrations → PHPUnit on PostgreSQL → GitHub Actions → GHCR
Result

The project moved to a supported stack without losing users: old passwords are rehashed on login, and every change passes linters, migrations and tests in CI before the image is built.

What can be reused
Transparent password migration from md5 to a modern hash on login Symfony CI pipeline: linters, migrations, PHPUnit on PostgreSQL, image in GHCR Legacy upgrade order: tests first, then rework