A problem that we have currently is that our entire system is written on Symfony 1.4 (well, it’s still the bridging 1.3 actually, but who’s counting). Migrating a system that’s been in development for 4+ years with thousands of lines of code and a lot of not-so-MVC-code is a nightmare, and in fact in the modern fast-to-market environment it is impossible to spend a year, or even 6 months, re-developing a system like this only to launch it and find it’s not only outdated once again but you missed a years worth of opportunities.

The solution? Run two systems next to each other! Easier said than done though, because when we look at the software, it is our customer zone and runs off a subdomain. So how do you run zone.domain.com and use both Symfony 1.4 (old code) and write new code in Symfony 2?

The solution? Fool the world a little bit! Put something into your Symfony 2 URL’s that uniquely identify them. Let’s fool the world into thinking we are going to be moving to internationalization. Let’s say all Symfony 2 URL’s will have a …./en/… between the domain name, and the route. So, URL’s will look like this in future:

  • zone.domain.com – goes to front page of Symfony 1.4 system
  • zone.domain.com/products/list – goes to page listing the clients products Symfony 1.4 style
  • zone.domain.com/en/products/list – goes to new-school and new-style Symfony 2 listing of the products (the cool thing about this is, that we can test the new products listing page extensively – even live! In fact, we can even start a beta program where certain clients/customers (say 5%) are given the opportunity to see new things before it’s launched)

Now, how do we do this? Options, anybody?

  1. Option 1: PHP Hacking
  2. Option 2: Apache Virtual Host Hacking
  3. Option 3: .htaccess hacking – this is the option we went with

In short, PHP Hacking involves us taking our app.php controller file on Symfony 1.4 (which everything is linked to) and checking for the /en/ at the start of the route, if we find it we go and include the Symfony 2 app.php file instead. This gets messy, because you now have to change current-working-directories, you have to keep track of things to avoid infinite looping, etc. It generally sucked when we tried it.

Option 2 and 3 is basically the same from what we did, but hacking away at the vhost means each change you’ll have to restart apache – not a great idea if you have to make a change on a live system with thousands of users logged in and trying to do something at that time.

Let’s then look at what we did with Option 3: .htaccess hacking:

First, let’s explain the old and new directory structures:

  • /home/public_html
    • symfony1.4projectname
      • apps/
      • cache/
      • config/
        • databases.yml – config file holding database names, server addresses, usernames and passwords!
      • lib/
      • log/
      • web/
        • app.php
        • images/
        • js/
        • css/
    • symfony2projectname
      • app/
        • config/
      • bin/
      • src/
      • web/
        • app.php

The old system, had a virtual host set up for zone.domain.com to point to /home/public_html/symfony1.4projectname/web/app.php. Thus, if you go to say zone.domain.com/products/list it would translate into loading the php file at /home/public_html/symfony1.4projectname/web/app.php and appending to it the URI of /products/list. We want to keep the system the same and have it still use that controller file for the old-school system.

With the new system, we’d like the exact same to happen, but instead of pointing it to ..symfony1.4projectname/web/app.php we want to point it to ..symfony2projectname/web/app.php (note the 2 instead of 1.4).

Easy (and wrong) way of doing this, is to have the vhost point not to /home/public_html/symfony1.4projectname/web/ but to /home/public_html/ and then have the .htaccess file make the call of where it’s going. This, however, opens up your entire folder structure to the world (if you’re not very very careful) which kind of voids one of the big reasons for using frameworks like Symfony with a single controller file for your application inside a single non-connected web folder.

Better: Create a “switching” folder, and point vhost there!

We created the following new folder structure (new is in green):

  • /home/public_html
    • symfony1.4projectname/
    • symfony2projectname/
    • switch/
      • s1.4/
        • Symbolic link to: ../../symfony1.4projectname/web
      • s2/
        • Symbolic link to: ../../symfony2projectname/web
    • .htaccess
Now, with our vhost pointing to /home/public_html/switch/ we can safely say that we are still secure, however nothing is working :) This is where the .htaccess file comes in:
The .htaccess file now has to figure out where to send us, first let’s make it work as it did in the past, here’s the file then:

Let’s look at this, all we’re basically saying is, whatever URI we call, send it to the destination of the symbolic link of 1.4 and load the app.php file with whatever parameters was given afterward.

Now that that’s working, let’s put in the /en/ rules:

The .htaccess file now changes to this (green is new code):

Here you can see, that the rule states that “if the URI begins with /en, then send it to the symbolic destination folder sitting at s2/web and load the app.php controller file, appending whatever parameters was given at the end”.

That worked great, except none of the images, css and js was loading. The great thing about Symfony 2 is that it has a /bundles folder inside web which holds all the assets. This is nice and identifiable of symfony 2 (granted that you don’t have that foldername in Symfony 1.4 though). Therefore, we just have to add another rule in for that. Here’s the new .htaccess file (again, green is new code):

And that, as they say, is that! Now all css, images, js etc is loading fine in Symfony 2 as well as the old-school Symfony 1.4 project is still working, and the best thing: Your PHP code doesn’t even know it’s been fooled! :) Neither does the public users of your system, by the way.

The only drawback of this is, that all your routes in Symfony 2 now has to be prefixed by /en/. The solution to this, though, sits in the word “prefix” – the great thing about symfony2 is that it has that ability! Open your routing file (that should be in app/config/routing.yml) and merely change the line that says:

… to be:

Done! :) Enjoy and please comment if you have some insight to give on this matter!