(Attempting to ) Integrating Laravel into a Legacy Codebase
We have a reasonably large codebase for a PHP application that provides the main business functions here at the cookery school. It was written orginally in 2004 when I thankfully decided to see what would happen if I turned our main business app into a web app written in PHP (rather than clasic ASP) instead of another Delphi desktop app which was what I was planning.
The usability and speed that I got up and running using PHP 4 was wonderful but it is very legacy.
All functions to capture logic
Each page has its own php page.
All pages pull in all code (pretty much).
Very little file structure, all files in a two directories. pages and includes
Recently I have been learning an ready about Laravel. This has been on everyone else’s radar for a long time and came on mine about 4 years ago when I was introduced to Lumen by a colleague. Having spent lockdown going through the excellent Laracasts introduction to Laravel 7 I felt like it was time to use Laravel a bit more.
Sure I can use it for any new api’s or apps, but what about leaveraging some of the benefits for our main application. Well its worth a try.
This blog post (possibly posts) tells my story of how I got (or did not get) a legacy codebase working in tandam with Laravel and modern PHP 7.
First things first: get a Laravel App and my primary core application both running on the same domain. As I have mentioned before I use the wonderful CaddyServer to host our sites. I set up a new site and pointed it to a directory on my server.
I created a new Laravel app in the directory and pointed caddy to its ‘public’ directory
Next I cloned my entire core application into the public directory (making sure not to overwrite the index.php file here).
Just like this, Laravel works no problem, you can set a route and as long as the route directory doesnt really exist in my main application, I can get access to a controller and view a new laravel app. I can also access my legacy application on a standard url since the files all exist in the public directory.
However I dont want to rewrite my entire application straight away, so I do want to be able to call functions in my legacy application from Laravel.
First off I tried simply calling the function from the controller.php after include the appropriate files. This inevitably led to an error that the function was not found. This of course was due to there being no namespaces in my legacy code.
The Reason for Namespaces
I immediately got an error saying that
Logger can not be redeclared
My code declared a logger function which unfortunately is pretty common and laravel declares a logger also. Without namespaces I was stuck since PHP didn’t know which logger I wanted. I had come upon the fundamental reason for declaring namespaces in the first place.
So I added a namespace at the beginning of the file that contained my function.
Then I got a different error. Now I need to use Namespaces everywhere.
My code calls PDO but does not call \PDO
So I change the few instances where I find
Then next I get error for functions that my legacy function calls. So I add namespace BCS to those files also.
and it all starts working (for that one function).
Next I got back and try to view my legacy application.
By putting a few namespace BCS in my legacy code, I had broken the app. Namespaces seem to be an all or nothing. My entire legacy app needed to be in a namespace or none of it.
With a quick find and replace on the two primary folders in my application, I inserted the line
at the begining of each and ever file and although there are still a few errors, which I am workgin through, I now have my legacy app up and running again on the BCS namespace and I can call functions if required from my new Laravel app.
I’ll see if I do finally hit a wall I can’t get past or if I can slowly convert my old legacy app into a laravel app, one page at a time.
Next up - Calling Laravel Controllers from my Legacy App!!
Using Laravel Classes in the Legacy Application.
Now that I have the two applications working seperately withing the same file structure and my new Laravel code can call functions in my Legacy application I had a lot of what I need.
This will allow me to create new section of the application and create them in Laravel, calling into the old legacy app when required to provide some logic I do not with to duplicate.
What about the modifications to the legacy appliation though?
I am hoping that using laravel will give me access to all the great features and conventions that Laravel provides. This I can do with new code, but what if I want to add code to an existing feature that cant easily be moved out into the new section?
Calling Laravel Objects from Legacy Code
Wouldnt it be cool if I could declare a Eloquent Class in Laravel and then create an instance of that class in my Legacy Application? That way I could really share code.
The entire Laravel Application is run from a single file public/index.php, which despite a lot of comments is only actually about 5 lines of code
define('LARAVEL_START’, microtime(true));
require __DIR__.’/../vendor/autoload.php’;
$app = require_once __DIR__.’/../bootstrap/app.php’;
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$kernel->terminate($request, $response);
I tried simply including this file. It should load Laravel and allow me to create a new instance of my object right? Well yes, but it just routes to the home page of laravel, which isnt useful.
I took a look at the code in index.php and decided that I probably needed it all except for the last two lines.
$kernel->terminate($request, $response);
I created a new file called loadlaravel.php and put the contents of index.php into it but commented out the last two lines.
So now I have a new laravel app that can call functions on my legacy application, and a legacy application that can use laravel classes.
Now to write the code and see where I go.