Legacy App - do I rewrite using Mezzio stack, or do I use Mezzio to run the legacy app separately?

I have a legacy app that was built on top of an older-version OsTicket. OsTicket is essentially its own framework with authentication, authorization, usernames, session handling, etc. with all the legacy artifacts such as $_SESSION, $_GET, $_POST, including some old jQuery and JS AJAX code. Every path is a hardcoded URL, in PHP, HTML, and AJAX. It is also an app with a bad design, god objects, spaghetti code, and global variables, and lack of separation of concerns.

I need to port this app to Mezzio
I started rewriting the app using Mezzio stack, hoping that I could port some of the existing code over, but I am finding that I have to rewrite or build from scratch pretty much everything - every hardcoded legacy URL needs to be routed to a new URL, and each requires a Handler & in some cases, Handler Factory . There are thousands of URLs for which I need to create Request Handlers and make the updates. For each Request Handler, I can’t simply port legacy code, I have to read it for comprehension, extract relevant HTML that is intermixed with PHP code and database code, and port them into .phtml. I also need to separate concerns, since for example, Mezzio does not allow one to echo or print output from the handler, where legacy code did whatever it wanted without punishment. I need to separate database code as well and work with all of the legacy code artifacts that you could image.

The goal is to get rid of OsTicket stack and use Mezzio stack and do it in a relatively short time frame. Going about it brute force way, as I described above, is getting to be prohibitively expensive and is taking a long time.

What can I do, what are my options?
Is there an option to run my OsTicket app as part of Mezzio as an intermediate step that will work now while I could take a longer time for refactoring to full Mezzio stack later? Is that going to be the best way? If yes, what is the process to make it happen?

Is the best way to bite the bullet and keep refactoring to Mezzio?

Is there something else I haven’t thought of? Has someone dealt with ugly legacy code and successfully moved it to Mezzio?

I’ve been having some success with a long-term project by wrapping the legacy app with a Mezzio app and using a “legacy middleware” much like a 404 handler - Mezzio then answers the routes that it knows about eventually dropping through to the legacy application for routes/paths it can’t handle.

In my case, it’s a ZF1 app with a similar list of problems, but at least it’s relatively self-contained.

My approach was to essentially write a middleware, retrieved from the DI container that performs all the bootstrapping necessary to setup the environment for the legacy app and then insert this middleware as the last thing in the pipeline. HTH

1 Like

Thanks

When you were setting up environment for the legacy app, what did that entail? Did you have to for example connect Mezzio Session to legacy session, and do the same for GET, POST, and other such mappings?

To give more detail, my concern is that Mezzio the way I’ve set it up has its own authentication and authorization. Will that be something I will need to map to the legacy app, or will legacy app in this case do its own original authentication and authorization, without relying on the Mezzio app?

Aside from that, are there any examples of such Middleware that you or someone could share?
Is such Middleware more or less boilerplate code with i.e. 10-30 lines of code, or do I expect it to become very custom and based on my legacy app and span 100 lines or more?

Thanks!

Well, in ZF1, which uses superglobals like $_GET and $_SESSION, there’s no mapping required in a web environment because being superglobals, they’re all still there, so the ZF1 app just reads them like before.

Authentication is a bigger problem - IMO, you should move authentication to Mezzio as the request hits that first, then you’d have to “fake” that successful authentication in the legacy app, however that might work. If auth is simply “logging in gives you access to everything” then you might possibly re-implement auth in Mezzio and then disable it completely in the legacy app - I of course have no idea what you’re facing there.

The strangler middleware I wrote for the ZF1 app is very small:

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Zend_Application;

class LegacyStrangler implements MiddlewareInterface
{
    /** @var Zend_Application */
    private $zf1Application;

    public function __construct(Zend_Application $zf1Application)
    {
        $this->zf1Application = $zf1Application;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $this->zf1Application->bootstrap()->run();
        exit;
    }
}

The factory to setup the legacy app in the first place performs jobs like setting the include path and anything else required. This is pretty straightforward because a ZF1 app always had a single entry point.

2 Likes

Thanks! I want to ask - why didn’t you go the route of rewriting the app into native Mezzio in the first place?

Were you facing similar issues like mine? Were there any other considerations in play?

In this case, I had loads of fat controllers, active record and the domain was severely coupled to the framework. It was more important to decouple, improve and test the domain over time so I could get to a place where throwing away the framework was a non-issue - time/cost are the big barriers to a complete re-write here - the app has to continue working in prod rather than just spending a year or so doing a re-write whilst prod limps along on the old stuff, I chose to improve everything gradually…

1 Like