Simple MVC Framework with PHP — Middlewares(A Chain of Responsibility Design Approach)

Chibuzo Miracle
4 min readOct 11, 2022

--

NB: First I will like to warn you that I used a code-as-you-think approach in writing this 😊. It would be to your interest if you use this article for educational purposes only and not in production. Thanks.

Now you remember that PHP framework we have been coupling for quite some time now, right? If you don’t, or you haven’t been following, you should take a look at the very first tutorial on this over here.

Alright having said that, we made alterations to the base codebase, yeah I know I haven’t provided us a repository link yet, I will do that after the last session on this tutorial.

The alterations we made included altering our Core\Framework class, created a middlewares.php file in our config folder, created a Core\MiddlewareEngine which obviously gets the bulk work in processing the middlewares, created a Core\Middleware abstract class and created a Core\MiddlewareInterface.

Before I continue, let me explain the Chain of Responsibility Design Principle, or at least define it. According to javacodegeeks.com, we can define Chain of Responsibility Design Principle as:

“A behavior pattern in which a group of objects is chained together in a sequence and a responsibility (a request) is provided in order to be handled by the group. If an object in the group can process the particular request, it does so and returns the corresponding response. Otherwise, it forwards the request to the subsequent object in the group.”

How is the middleware exampling the better approach to explaining this? Let’s start out by knowing how middlewares function in modern day frameworks.

Middleware according to Wikipedia is defined as a type of computer software that provides services to software applications beyond those available from the operating system. It can be described as “software glue”

middleware illustration

Now, the middleware approach might not be the most efficient means to communicate this principle across, but it was the most efficient in communicating it across to me and … come on, I know you will find this read fun.

Before we proceed, I would like you to have a mental picture of what we plan to achieve, below is a middleware class that was created for test purposes.

We hope to achieve the middleware structure by the end of this tutorial. This middleware would be located inside the app/Middlewares directory of your framework.

Step 1: middlewares.php

This file as specified earlier should seat in your config folder. Take note of the commented line of code (line 3), this comment will be removed before testing as the defined class will be our go-to class to ensure this works.

Step 2: MiddlewareEngine.php

This will seat in your core folder, this file has three methods that carry out specific functions:

a. Run method is designed to be called from our Framework.php file just before instantiating the class that matches the route, just to make sure all middleware conditions passed so as not to put the application at risk.

b. Handler method takes a class name (obviously with its namespace included), matches it with the middlewares defined, gets the current middleware pointer, looks for a possible next middleware with the current pointer and returns an instance of the next middleware, or it returns false when nothing is found.

c. loadMiddleware method literally reads the array in the config/middlewares.php file into a variable.

Step 3: MiddlewareInterface.php

As the name implies, this is an interface used for abstraction purposes.

Step 4: Middleware.php

This would be an abstract class that can be extended by custom middleware classes.

This abstract class has four methods, out of which two are setter methods. I know you are confused at this point… yeah I get it, why have two setter functions to literally set one property?

The answer I guess should come now before I go ahead to finish my explanations. In my defense:

The Middleware class is bound by reason of implementing MiddlewareInterface to have a setNext method, now but this setNext method has a defined input type and output type, if you are familiar with SOLID design principles, you should know that Liskov substitution principle has it that.

i. child function argument must match function argument of parents

ii. child function return type must match function return type of parents

Now we have a $nextHandler property that needs to be set, this property can either be an instance of the MiddlewareInterface or NULL, we would be going against SOLID by forcing setNext() to set $nextHandler directly, so we use the setNextHandler() method to set the $nextHandler property and use the setNext() method to call the setNextHandler() method passing in only an instance of MiddlewareInterface. come on… I know I have not been the most SOLID complaint but a little SOLID would not hurt would it?

Having said all that, let’s go ahead and explain the other two functions/methods.

i. implementHandler(): This method calls the handler method in the MiddlewareEngine class, passing in the current class ($this), remember the handler method returns an instance of a class or false. If false, it calls the setNext() passing in the instance or calls setNextHandler() and pass in NULL.

ii. handle(): this method takes in an instance of the Request class and returns the next middleware class and the handle method or return null if there is no next middleware.

--

--

Chibuzo Miracle

B Eng A&B Engineering || Software Developer || Technical Writer