Dev Guide to migrate Legacy to Symfony

Introduction

The OpenCATS legacy code is stored in the root of the OpenCATS project, while the code of OpenCATS Symfony it's on the src/ folder.

The legacy application was intended to be light and conceptually to understand. It separated the code in three main areas:

  • Modules: A module consists of the user interface logic and one or more “templates” to render the HTML page. Some of the modules in OpenCATS are Home, Candidates, Contacts, Calendar, etc.

  • Library components: Library components are PHP objects which encapsulate lower-level functionality, such as interfacing with a database, parsing addresses, sending e-mail, etc. For each module, there is a roughly corresponding library component but not all libraries directly correspond to a module.

  • Templates: HTML/CSS/js code with some light logic.

OpenCATS Legacy Request Flow

Most of OpenCATS request went through index.php and ajax.php files which acted as “router” or delegator to the modules.

  1. A page request is sent to index.php or ajax.php file

  2. index.php parses the URL and sends the request to the corresponding module (specified by m= in the URL) for further processing

  3. A module parses the “action” (specified by a= in the URL) and invokes the corresponding method within the module.

  4. The method processes the request, often using library components

  5. The function displays a template file, if necessary, and fills in the appropriate data and renders the HTML page

OpenCATS Legacy URLs

OpenCATS Legacy URLs were designed to be intuitive and easy to use for developers. E.g. HTTP://OpenCATS.org/index.php?m=clients&a=show&clientID=239 means:

m = clients a = show clientID = 329

Translation: index.php sends the URL to the “clients” module. The clients module processes the action “show” for clientID 329. We want to display details of client 239.

Version 0.9.4

This version aims to provide a bridge between Symfony and the legacy code so that the legacy code can be migrated little by little without requiring to rewrite the whole app at a single shot.

In this version, there are no significant changes to the Legacy URLs and the way they are managed from a user point of view. From the request flow, there is an important change. In this version all requests go through a Symfony's front controller.

What's changed?

  • A new docker image: this is required to load the symfony requirements + nginx configuration for the FrontController pattern

  • config.php was changed to get variables from environment, to allow configuring symfony app and legacy configuration from the docker image

  • Changes to all include paths: A new constant called LEGACY_ROOT is prepended to all paths for compatibility

  • Removal of index.php and ajax.php entry points, they are now functions in LegacyController

  • All assets (css, images, javascripts) were relocated into the public assets folder

  • Base composer.json and composer.lock are removed (all migrated to composer.json and composer.lock in Symfony structure)

  • Behat and PHPUnit tests were standardized into a unified testing framework: Codeception and moved out of their legacy structure to Symfony's.

Decisions

In order to simplify deployment and installation, the default mode for running OpenCATS will be docker (on all platforms).

Migration challenges

Configuration

Symfony configuration is managed by a set of yml files while the legacy application utilizes config.php. The first attempt was to migrate all config.php variables to the parameters.yml but it resulted to be a huge task. In order to solve this issue and also following the recommendations of https://12factor.net/, all values were replace with environment variables which are now injectable through docker-compose by replacing the .env file in the folder where the docker-compose file is executed.

Functional test code

90% of the time is spent on updating test code. What's causing the issue? Mainly selenium and the PHP frameworks being used do not play well nor work reliable with:

  • code that's using blocking javascript alert and confirm functions

  • code that's using iframes

Further performance improvements?

  1. https://tideways.io/profiler/blog/5-ways-to-optimize-symfony-baseline-performance

  2. http://symfony.com/doc/current/performance.html

Last updated