legecha's avatar

Incrementally implement Laravel into legacy system - consuming API?

I've recently started learning Laravel and so far, I love it. One of my upcoming projects is to take a very old eCommerce system (started off in PHP 4, hacked to death over the years) and end up, over as long a period of times as needs be, with a comparable system that runs entirely in a new framework (i.e. Laravel). This is while the old system has fixes and updates alongside too.

I've been looking into ways of doing this without an all-or-nothing approach. I want to replace smaller parts of the system, modularising as much as I can with my team, until we feel confident that enough of the functionality is in place for us to make a final big push to move over things like web routes and use Laravel as one would traditionally expect. Bear in mind that this current system has very few classes or separation of concerns, tons of functions with global variables, etc. For all intents and purposes it is removing chunks of procedural code with calls to Laravel. We don't care about the old system getting (more) hack, but the new system we want to be clean and reusable, regardless.

I was wondering if anyone had any thoughts or could point me towards relevant reading for this sort of thing. I was thinking that if I created new features that could be accessed through an API (for instance shipping functionality, stock control, etc), then the existing system could make calls to that API and this same API would be used in the final system. Can that be done from other, non-laravel apps, without an actual HTTP request? Note: they will be on the same server, of course.

Unfortunately we don't currently have the resources to make a system from scratch to do a full on replacement, and the risks would be huge here too. Has anyone got any experience, tips, tricks or warnings for tackling our problem of a very old system this way?

Many thanks!

0 likes
4 replies
danmatthews's avatar

I was actually in your position a few months ago - a client had no budget to do a full on replacement of a six-year old system written in Drupal 7, but it was in dire need of some performance gains - i knew we could achieve those by bypassing Drupal in certain areas, routing requests through Laravel, and hitting the same database drupal was talking to (we had custom tables in drupal anyway, so updating them directly was never going to cause problems).

So the plan was to place, as you said, a Laravel/Lumen instance alongside the current app, talking to the same database, but taking advantage of the fact that Laravel's request bootstrapping time was something like 100ms rather than Drupal's 3 seconds.

Can that be done from other, non-laravel apps, without an actual HTTP request?

It can definitely be done from other non-laravel apps, but you will probably need a HTTP request, particularly if you're building an API, and one that you'll want to be able to re-use with a completely new app in the end.

You can definitely do this modular step by step replacement technique - just watch out for:

  • Interaction between the old platform and the new platform's data - it could cause problems.
  • Authentication is a major consideration - how can you ensure that the person calling the new API is who they say they are in the context of the old system.
  • It's definitely going to increase the amount of maintenance you need, as you're adding in a new codebase.
  • Measure any improvements the new parts of the system give you - speed, conversions etc.
1 like
legecha's avatar

Thanks @danmatthews some really good points to note - nice to see we're not alone in this scary position ;) One thing I should have pointed out is that we're tempted to separate data away as well - two separate databases might sound a little sinister but if I showed you some of the database "conventions" used on the current project you'd understand what I'm getting at... let's just say the system rewrites database structure on the fly and there's a lot of "pruning" needed to maintain it currently :|

As for the web request, I see what you're saying. But can this be mocked in any way? I have seen things like $request = Request::create(...); $response = Route::dispatch($request) and app()->handle() suggest but I'm not quite at the point I can say whether they're going to be options for us yet, but potentially could they improve speed? I don't like the idea of relying on an HTTP request inside a page load if I can help that kind of thing. Tell me if I'm barking up the wrong tree here!

danmatthews's avatar

the system rewrites database structure on the fly.

Been there dude! Legacy systems have a lot to answer for sometimes!

The code example you've given could be used to send HTTP requests internally between a say a page in the Laravel app and your separate API on the same Laravel app - it's internally routed rather than sending over HTTP.

But if you want to talk to the laravel API from your legacy app obviously you'll need to do it over HTTP.

The other option (inside Laravel) is to abstract away data into something like a Repository pattern or Services, so you can call those from both your API and your web app and get the same data back without having to make internal requests.

1 like
legecha's avatar

So there's nothing I could do like this, which can be done with the Slim framework:

$env = \Slim\Http\Environment::mock([
    'REQUEST_METHOD' => 'PUT',
    'REQUEST_URI' => '/foo/bar',
    'QUERY_STRING' => 'abc=123&foo=bar',
    'SERVER_NAME' => 'example.com',
    'CONTENT_TYPE' => 'application/json;charset=utf8',
    'CONTENT_LENGTH' => 15
]);

https://www.slimframework.com/docs/cookbook/environment.html

Please or to participate in this conversation.