Write Your Own PHP Framework & CMS, Part 1

So, you are wanting to write your own framework. Maybe you are tired of the breaking changes introduced into the framework you are currently using. Maybe, you realized how slow Symfony and Laravel frameworks actually are. (They are ridiculously SLOW, if you didn't know, check out our Laravel Benchmarks and Symfony Benchmarks; for more detailed information). Maybe, you have a desired API and code design or esthetic, which you wish you could use, but your framework doesn't allow or is incapable of this change. Or maybe, you just want to write your own framework; let's pause for a few seconds for a Public Safety Announcement.

Do not think that you are unqualified, to write your own framework. Many developers say 'Don't write your own X, use the better one someone else who is better than you, already created'; this is patently wrong, misleading, and misguided. I will explain throughout the rest of this article series, why I believe the, and why you should create your own systems (including frameworks) whenever you can. Please just remember, if you don't write challenging code, you cannot get better. Write your own framework, become better, and become more effective and efficient as a software engineer. Write your own code.

Let's start the process of writing your Framework and CMS with some requirements for our resulting system. I already have a few Framework + CMS projects to base this off from, and am utilizing a few in production, while others are more research and test oriented. This framework and CMS however, is intended not only for learning how to create such a codebase, but also a starting point for your custom production ready CMS. Be it for you to use for your clients' sites (instead of WordPress) or for your own projects. But it will be production ready in the end; maybe 15 or more articles down the road.

Technical Feature Requirements

Despite what many developers espouse, by "rolling your own" you do not need to lose features or capabilities, you do not instantly become less secure, and you do not waste precious time 'reinventing the wheel'. Our goal is going to be to complete this framework, with a feature set that will compare to the current trendy frameworks, with two specific advantages: First, we will have created, and understand the entire codebase, and Second, we will focus on performance, both of development and execution. On to the specifics:

API by Default, We want to develop our projects and systems to always create an API which is available for direct calling (if desired) cutting out the UI.
Model-View-Controller like CodeLayout, To keep everything organized, we will utilize an MVC inspired pattern for our code layout. While it might not be exactly an MVVC, MVC, or HMVC pattern, it will be reminiscent of one. Giving us nearly always, a clear place to put all of our code.
Content Management Built-In, While we are first building a "Framework", but the end we want a portable module which allows for content management without writing any additional code in our framework. (think of a refined WordPress here, many people treat it as an application platform. It isn't, but our will be)
Defined Interoperability Specifications, I want your code that you build, to run modules/applications which I create for my framework. We are going to define a global Module specification. If you and I follow this specification, both our systems, different as they may be, will be able to run the portable module. This should allow for a Module Market, which we can share and sell our modules to others with compatible systems, giving clients even more benefit for using your in-house system. Also giving each contractor/consultant the ability to create benefits for their clients, while not losing the ability to run existing code modules. (There will be entire articles on this subject, and system, probably many articles) This is going to be the Portable Application Module System (PAMS) 'not the same as linux pams'
Dependency Injection (or SigSlot and PubSub), we are going to need to have a method or pattern for dependency injection of a sort. Allowing different Servers to facilitate or execute their specialization of a method or process. This is a terrible explanation, however; we want modules to be able to attach to, run and issue events from any other system or module's code. Since this will be a central or core system in our codebase, we need it to be fast. Here over thinking the performance concerns is not possible. We will do everything we can, to make this fast.
Execution Speed, many systems offer good performance for a hand full of visitors. Like Laravel, where you can get page loads sub second rather easily. What you cannot do easily, is scale you sub-second load times to 100+ concurrent visitors. This is a problem with WordPress, Drupal, Symfony, and so many others. They are resource hogs, and do not scale nicely. And when they do, it is via distributed load balancing and running multiple app instances across many app servers. While we will support this, we want to be certain, our code is minimalistic; in execution time, dependencies, and resource allocations. We will by default, support multiple app server (horizontal) scaling! But we want to make vertical scaling to a point, possible and easily attainable.
Database Agnostic? I am not sold on this yet. I am seriously considering building a Database Abstraction layer, which allows our system to run on different database servers. This layer will be smart enough to take advantage of the specific database's advantages and features, however, it may not be possible to utilize different types of data storage service (Document, Relational, Node, Graph, etc). We might be able to efficiently support multiple servers of the same class or type (MySQL, PostgreSQL, SQLite, Microsoft SQL Server, Sybase, FirdbirdSQL, Oracle DB, and others) while still taking advantage of each server's unique advantages. This will require an intelligent db driver layer, which might take a lot of time to develop. We will decide as we get closer to this requirement.

The Structure of Our System

Our system needs to be fast over elegant, simple over complicated, and interoperable over all else. While these might seem conflicting on the surface, at least the way I envision them, they are not. When we choose a feature say for Routing requests, it should be fast instead of elegant (to a degree), but it should remain simple in theory and execution, even if the complicated solution might be faster (it rarely is!) and the routing needs to be interoperable with the PAMS system and allow you to develop a compatible Framework and CMS. We need to define a Standard, and implement that however we wish. If you implement it differently (more elegant, or more security hardened) it should follow the interoperability standard above all else. (This lengthy explanation probably did no good.) So on to the structure and start of our standards.

Request Handling, Routing, Execution and Response.

At the heart of our system, we are creating a pipeline which a Request will flow through. Out of the other end a Response will be given as a result of the Request. This is sometimes hard to encapsulate in a single idea, since PHP is not designed to operate at this "Hypervisor" like position. Usually the Request is entirely an HTTPd concept, and PHP is running in response to a Request. While this is technically still the case, we need our system to act as if it is always running, and a Request is an object that flows through it. This approach gives us some interesting capabilities, while keeping our code very clean.

Browser HTTP Request --> NGINX server conf --> PHP-FPM --> public/index.php --> new RequestObject(..., new ResponseObject(NULL)) --> RequestPipeline ( $req ) --> routed_and_handled_by_application_specific_code_and_modules --> Render( $response ) --> PHP-FPM --> NGINX --> Browser HTTP Response

While this is not entirely accurate or easy to follow, it should give you an idea of the flow we expect from the Visitor loading a page to the Visitor receiving a response and the browser rendering it. Every single request, API or Page request alike, will follow this exact flow. There is no reason that I can think, to change it. The only difference is in the Render system. On a Page, the Render might grab a template, and generate the entire HTML to send down to the browser; while the API, might have a JSON Renderer which will generate a valid JSON object to send as an AJAX response, or maybe to an application (mobile or otherwise) which initiated the request.

Routing VS Application Handling

I usually clearly distinguish an Application Handle and a Route, but sometimes I might blur the lines. Routing in our framework will be the core system, which allows a Request and Response to travel the Pipeline, flowing to all the necessary application and module methods, as needed, and even looping back if needed, It might even generate multiple requests to be ran while the initial waits for the needed responses of the additional requests. (I don't think this is actually part of the Hierarchical MVC pattern, but I would like to imagine it were) Treating this Request/Response like such, we can have a Page Request (for a LaserPrinter Product Page) that might need data from the Products Module, for a "Related Products" widget, or similar; it can initiate a Request (API) to the system, which pauses the initial Request while it waits for the Response with the needed data (maybe as HTML or just JSON) after which it can finalize the Response that will be send to the Browser.

The Application Handlers, are the code which handle a Request, and the Routes, are the pipes, configuration, and code that get the requests to the Handlers.

Any Code, For This Article?

I have really been trying to get this article to be purely an introduction to the ideas and intentions for the series and system. But, I cannot do that. Let's get our project started. And let's get to writing some code. However, I want to do this in a mixed media publication. I want to create a Tutorial Video Series of the creation of the project, and support that by this article series. Here we will Write about the system and it's design, while in each article, we will include a video with the entire creation of the code up to that point. I really hope this works, and that I can stick to it.

Video Coming Soon!