Why build your own PHP framework?

There are a lot of PHP frameworks out there, not just PHP, but other programming languages as well. This article is about PHP frameworks because I’m most familiar with the PHP ecosystem, but this approach can be applied to frameworks in other programming languages as well.

Framework is to improve the efficiency of our application development, there are many open source and free frameworks for us to use in the market, we can use them, why do we need to build our own framework? The reason is that the open source framework on the market is for most people to use, for general projects, as the framework developers do not know their own framework users of the specific business, so the open source framework must be to meet the needs of most people, and strive to provide developers with all possible functions.

But for a commercial project or a project you want to do may only use the framework of a small number of functions, or provide you with the framework of things is not the most fit your own needs, you use the framework as part of the function, the other part is useless, so using a framework first is the loss of performance, It’s not appropriate to degrade your application’s performance when you don’t even need it. Or maybe the functionality provided by the framework is not what you want, or the functionality provided by the framework is not what you need, or the functionality must be used according to the framework developer’s specification, which is not consistent with your development philosophy.

Where to start?

Every modern programming language has its own package management tool, PHP is Composer, with which you can build your own framework and organize it well.

How do you start?

How do we start building our own framework? From scratch? There is no right answer to this question, and if you are working on a project that is demanding and requires the most stable and controllable architecture from the ground up, you are advised to start from scratch. If the requirements are not very strict then we should start with the most basic functionality needed to develop an application. Who provides that functionality? PHP has a number of microframeworks that provide the basic functionality for developing an application, and we can start here.

First we initialize a project with composer init:

{
    "name": "dongm2ez/m2ez-framework",
    "description": "a dongm2ez's framework",
    "keywords": ["framework", "m2ez-framework"],
    "license": "MIT",
    "authors": [
        {
            "name": "dongm2ez",
            "email": "[email protected]"
        }
    ],
    "require": {}
}Copy the code

This is a description file of composer. Json that I got, and now we’ll start there. My goal is to build a framework that best fits my development habits and allows me to develop as efficiently as possible.

I chose the Slim framework as my framework foundation framework, which is a micro-framework, and I like it because it’s simple enough to provide the basics of Web development and API development, but also because the author who developed the framework wrote a book called Modern PHP, This book changed my understanding of PHP as a language, and I began to love it and enjoy using it.

Before introducing this framework, I also have a limitation on PHP versions. PHP has progressed from 5.2 to 7.2 since I started using PHP, but I don’t want to use lower versions of PHP anymore. One is that lower versions of PHP will soon lose official payments. The other is that there are some new PHP features that I can’t use, and the performance of the earlier versions is not good. So I’m going to limit my framework to PHP 7.0 and above, and I want my framework to have better Support for Chinese.

So I’ll update my framework composer. Json file:

{ "name": "dongm2ez/m2ez-framework", "description": "a dongm2ez's framework", "keywords": ["framework", "m2ez-framework"], "license": "MIT", "authors": [ { "name": "dongm2ez", "email": "[email protected]"}], "require" : {" PHP ":" > = 7.0.0 ", "ext - mbstring" : "*", "slim/slim" : "^ 3.0"}}Copy the code

This gives me a basic version of my framework, but I haven’t finished yet because we haven’t defined my framework directory structure. I liked the laravel framework’s directory division, but I didn’t like the laravel directory structure completely, and I needed to revamp it.

├ ─ ─ app │ ├ ─ ─ Helpers. PHP │ ├ ─ ─ Http │ │ └ ─ ─ Controllers │ └ ─ ─ Models ├ ─ ─ composer. The json └ ─ ─ testsCopy the code

I set up my directory structure like this and updated my composer. Json:

{ "name": "dongm2ez/m2ez-framework", "description": "a dongm2ez's framework", "keywords": ["framework", "m2ez-framework"], "license": "MIT", "type": "project", "authors": [ { "name": "dongm2ez", "email": "[email protected]"}], "require" : {" PHP ":" > = 7.0.0 ", "slim/slim" : "^ 3.0}", "the require - dev" : {" phpunit/phpunit ": "6.0"}, "autoload" : {" classmap ": [" app/Models"], "PSR - 4" : {" app \ \ ":" app /} ", "files" : [ "app/Helpers.php" ] }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } } }Copy the code

Is such a framework accessible? Obviously not. We need to add something to make our framework actually run, and then iterate over it.

├ ─ ─ app │ ├ ─ ─ Helpers. PHP │ ├ ─ ─ Http │ │ └ ─ ─ Controllers │ └ ─ ─ Models ├ ─ ─ the bootstrap │ ├ ─ ─ app. PHP │ └ ─ ─ autoload. PHP ├ ─ ─ ├─ ├─ all exercises, please click here and click hereCopy the code

We transformed the directory structure into this and wrote some code to start the framework into the corresponding file

// public/index.php <? php require __DIR__.'/.. /bootstrap/autoload.php'; $app = require_once __DIR__.'/.. /bootstrap/app.php'; $app->run(); // bootstrap/app.php <? php $app = new \Slim\App; return $app; // bootstrap/autoload.php <? php define('M2EZ_START', microtime(true)); require __DIR__.'/.. /vendor/autoload.php';Copy the code

Then run composer Install to install the framework’s dependencies. After the installation is complete, there will be a vendor directory and a composer. Lock file in the directory. PHP -s 0.0.0.0:8080 -t public public/index.php PHP -s 0.0.0.0:8080 -t public public/index.php We can add this command to the script of composer. Json.

Access 127.0.0.1:8080 or localhost:8080 to see the following page:

This means that the framework is started correctly, so how can we make sure that the framework is working properly? Here is a simple method:

<? php use Slim\Http\Request; use Slim\Http\Response; require __DIR__.'/.. /bootstrap/autoload.php'; $app = require_once __DIR__.'/.. /bootstrap/app.php'; $app->get('/hello/{name}', function (Request $request, Response $response) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; }); $app->run();Copy the code

For public/index. PHP code modifications, visit http://localhost:8080/hello/dongm2ez right now, so we will see:

The test was successful, but we couldn’t write the routing and logic into the index.php file, so we needed to organize the code better. Let’s make our catalog program work.

To manage the routes separately, I wrote the routes separately in the routers folder. We created two PHP script files in the folder and added two lines of code to the public/index.php:

<? php require __DIR__ . '/.. /bootstrap/autoload.php'; $app = require_once __DIR__ . '/.. /bootstrap/app.php'; require __DIR__ . '/.. /routers/web.php'; require __DIR__ . '/.. /routers/api.php'; $app->run();Copy the code

This way, I can manage the API and WEB project routes separately, and require more routes if there are other routes.

<? php $app->get('/', '\App\Http\Controllers\WelcomeController:index');Copy the code

And what our controller looks like, it looks like this:

<?php

namespace App\Http\Controllers;

use Slim\Http\Request;
use Slim\Http\Response;

class WelcomeController extends Controller
{

    public function index(Request $request, Response $response)
    {
        $response->getBody()->write("Hello, world");

        return $response;

    }

}Copy the code

We know that in the framework of modernization, the container will make us very convenient, we Slim framework provides the basis of the realization of a container, of course you also can use other third parties, then this is clearly what we want as a result, not only using the framework, we can replace the function of the framework at any time, we want the same for functional components.

It is also simple to use, passing the container instance to the Slim framework when it is initialized in the app.php file.

<? php $container = new \Slim\Container; $app = new \Slim\App($container); return $app;Copy the code

Remember that controller inherits from the base class controller, which I wrote myself, that can do some kind of operation encapsulation that any controller might use. For example, I initialized a container instance in the base class to make it easier to use the container.

<?php

namespace App\Http\Controllers;

use Interop\Container\ContainerInterface;

abstract class Controller
{
    protected $ci;

    public function __construct(ContainerInterface $ci)
    {
        $this->ci = $ci;
    }

}Copy the code

Now that I have routing capabilities, I have controller capabilities, and I have operations that request responses, to be a complete framework there must be a way to access the database.

I liked the database ORM component provided by Laravel so MUCH that I decided to use it and perform composer require illuminate/database “~5.5”. I chose the latest Laravel long Term support ORM.

We need to add a new file in config folder called condition.php:

<? php return [ 'settings' => [ 'db' => [ 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'database', 'username' => 'user', 'password' => 'password', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', ]]];Copy the code

Then change to public/index.php:

<? php require __DIR__ . '/.. /bootstrap/autoload.php'; $config = require __DIR__ . '/.. /config/databases.php'; $app = require_once __DIR__ . '/.. /bootstrap/app.php'; require __DIR__ . '/.. /routers/web.php'; require __DIR__ . '/.. /routers/api.php'; $app->run();Copy the code

Modify the bootstrap/app. PHP:

<? php $container = new \Slim\Container($config); $app = new \Slim\App($container); // Service factory for the ORM $container['db'] = function ($container) { $capsule = new \Illuminate\Database\Capsule\Manager; $capsule->addConnection($container['settings']['db']); $capsule->setAsGlobal(); $capsule->bootEloquent(); return $capsule; }; return $app;Copy the code

Then we can use the ORM functionality in the controller.

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\DB;
use Interop\Container\ContainerInterface;
use Slim\Http\Request;
use Slim\Http\Response;

class WelcomeController extends Controller
{

    public function index(Request $request, Response $response)
    {
        /** @var DatabaseManager $db */
        $db = $this->ci->get('db');
        $user = $db->table("user")->first();
        var_dump($user);
        $response->getBody()->write("Hello, world");

        return $response;

    }

}Copy the code

At this point, the framework is already a framework for developing API functionality. If I want to develop a Web site, I may need to add a rendering template component, whether it’s Twig, Smarty, Haml or Blade, depending on your preference. Of course, I think I can do this, enough for me, because I prefer to use React or Vue to implement the front end.

Need to be more convenient operation session, cookie, then we can also add the corresponding components, all kinds of existing framework provides such components, and see which one do you prefer, the framework of your family now, you can add whatever you want to add components, after such a custom frame must be the most fit your development needs.

I’m here just for existing components configured assembly, once you discover one day all of the open source components can’t satisfy the needs of you, because you know about your framework, you can make a wheel for their own framework, if you write well so you will create a very useful framework, now the most popular PHP framework, You can check out its composer. Json file. It was developed and maintained on the basis of previous works.

And I’m not using too many design patterns here, you can also adapt your framework, using PHP magic, reflection, SPL and so on to make your framework better, easier to expand, easier to configure.

conclusion

Is the frame mysterious? I’m sure you won’t feel that way after reading this article.

Is it hard to build a frame? Yes it is, because everything is hard to go from zero to one, but do we need to go from zero to one now? Almost not! It’s easier to do things on top of giants, and remember, you’ll find it’s better to try than to hesitate to do anything until you get started. Start small, do small things, and one day the small things will become big things. A long journey begins at a single step.

Laravel is popular because the author is a.NET developer who came up with the idea to create a more concise and flexible framework while using CI frameworks. Is his thinking really advanced?

You are not a PHP programmer, you are a developer. We should understand and master anything related to development. Labels can only be pasted by others, not by ourselves.

Finally, this code has been uploaded to GitHub. If you are interested, you can fork and refine it, develop and configure your own framework, and choose your favorite technologies and components based on your needs.

Address: github.com/dongm2ez/m2…