Frameworks for microservices

A framework is a skeleton that we can use for sofware development. Using a framework will help us use standard and robust patterns in our application, making it more stable and well known by other developers. PHP has many different frameworks you can use in your daily work. We will see some standards used on the most common frameworks so that you can pick the best for your project.

PHP-FIG

For years, the PHP community has been working on their own projects and following their own rules. Thousands of different projects with different developers have been released since the first years of PHP, and none followed any common standards.

This was a problem for PHP developers, firstly because there was no way of knowing if the steps they were following to build applications were the correct ones. Only their own experience and the Internet could help the developer guess if their code was written properly and if it would be readable by other developers in the future.

Secondly, the developers felt that they were trying to reinvent the wheel. Developers were making the same existing applications for their projects because there was no standard to fit third-party application into their projects.

In 2009, the PHP Framework Interoperability Group (PHP-FIG) was born with the main goal of creating a unique standard for development in PHP. PHP-FIG is a big community of members that works on the PHP Standards Recommendation (PSR), discussing what the best way to use the PHP language is.

PHP-FIG is supported by big projects such as Drupal, Magento, Joomla!, Phalcon, CakePHP, Yii, Zend, and Symfony and that is the reason the PSRs they propose are implemented by the PHP frameworks.

Some standards, such as PSR-1 and PSR-2, are about the use of code and its style (using tabs or spaces, opening tags of PHP, using camelCasing or filenames) and others are about the autoloading (PSR-0 and then PSR-4). Since PHP 5.3, namespaces were included and it was the most important thing to implement autoloading.

The autoloading was possibly one of the most important improvements to PHP. Before PHP-FIG, frameworks had their own methods to implement the autoloading, their own way to format them, initialize them, and name them, and each one was different, so it was a disaster (Java already solved this problem using its beans system).

Finally, Composer implemented autoloading, which was written by PHP-FIG. So, developers don't need to worry about require_once(), include_once(), require(), or include() anymore.

You can find more information about PHP-FIG at http://www.php-fig.org/.

PSR-7

In this book, we will use the PHP Standard Recommendation 7 (PSR-7). It is about the HTTP messages interfaces. This is the essence of web development; it is the way to communicate with a server. An HTTP client or web browser sends an HTTP request message to a server and it replies with an HTTP response message.

These kinds of messages are hidden from normal users, but developers need to know the structure to manipulate them. The PSR-7 talks about the recommended ways to manipulate them, doing it simply and clearly.

We will use HTTP messages to communicate with microservices, so it is necessary to know how they work and what their structure is.

An HTTP request has the following structure:

    POST /path HTTP/1.1 Host: example.com
    foo=bar&baz=bat

In the request, there are all the necessary things to allow the server to understand the request message and to be able to reply with a response. In the first line, we can see the method used for the request (GET, POST, PUT, DELETE), the request target, and the HTTP protocol version, and then one or more HTTP headers, an empty line, and the body.

And the HTTP response will look like this:

    HTTP/1.1 200 OK Content-Type: text/plain

This is the response body. The response has the HTTP protocol version, such as the request and the HTTP status code, followed by a text to describe the code. You will find all the available status codes in the next chapters. The rest of the lines are like the request: one or more HTTP headers, an empty line, and then the body.

Once we know the structure of HTTP request messages and HTTP response messages, we will understand what the recommendations of PHP-FIG on PSR-7 are.

Messages

Any message is an HTTP request message (RequestInterface) or an HTTP response message (ResponseInterface). They extend MessageInterface and may be implemented directly. Implementors should implement RequestInterface and ResponseInterface.

Headers

Case-insensitive for header field names:

    $message = $message->withHeader('foo', 'bar');
    echo $message->getHeaderLine('foo');
    // Outputs: bar
    echo $message->getHeaderLine('FoO');
    // Outputs: bar

Headers with multiple values:

    $message = $message ->withHeader('foo', 'bar') ->
    withAddedHeader('foo', 'baz');
    $header = $message->getHeaderLine('foo'); 
    // $header contains: 'bar, baz'
    $header = $message->getHeader('foo'); // ['bar', 'baz']

Host header

Usually, the host header is the same as the host component of the URI and the host used when establishing the TCP connection, but it can be modified.

RequestInterface::withUri() will replace the request host header.

You can keep the original state of the host by passing true for the second argument; it will keep the host header unless the message does not have a host header.

Streams

StreamInterface is used to hide the implementation details when a stream of data is read or written.

Streams expose their capabilities using the following three methods:

    isReadable()
    isWritable()
    isSeekable()

Request targets and URIs

A request target is in the second segment of the request line:

    origin-form
    absolute-form
    authority-form
    asterisk-form

The getRequestTarget() method will use the URI object to make the origin-form (the most common request-target).

Using withRequestTarget(), the user can use the other three options. For example, an asterisk-form, as illustrated:

    $request = $request
    ->withMethod('OPTIONS')
    ->withRequestTarget('*')
    ->withUri(new Uri('https://example.org/'));

The HTTP request will be as follows:

    OPTIONS * HTTP/1.1

Server-side requests

RequestInterface gives the general representation for an HTTP request, but the server-side requests needs to be processed into an account Common Gateway Interface (CGI). PHP provides simplification via its superglobals:

    $_COOKIE
    $_GET
    $_POST
    $_FILES
    $_SERVER

ServerRequestInterface provides an abstraction around these superglobals to reduce coupling to the superglobals by consumers.

Uploaded files

The $_FILES superglobal has some well-known problems when working with arrays or file inputs. For example, with the input name files, submitting files[0] and files[1], PHP will be represented like this:

    array(    
      'files' => array(        
        'name' => array(            
          0 => 'file0.txt',              
          1 => 'file1.html',        
        ),
        'type' => array(
          0 => 'text/plain',             
          1 => 'text/html',
        ),        
    /* etc. */    ), )

The expected representation is as follows:

 
    array( 
      'files' => array(
        0 => array(
        'name' => 'file0.txt',
        'type' => 'text/plain',
      /* etc. */        ),
      1 => array(
        'name' => 'file1.html',
        'type' => 'text/html',
        /* etc. */        
      ),    
    ), )

So, the customers need to know these kinds of problems and write code to fix the given data.

getUploadedFiles() provides the normalized structure for consumers.

You can find more detailed information and the interfaces and classes that we discussed at http://www.php-fig.org/psr/psr-7/.

Middleware

A middleware is a mechanism to filter the HTTP requests on an application; it allows you to add additional layers to the business logic. It executes before and after the piece of code we want to reach to handle input and output communication. The middleware uses the recommendations on PSR-7 to modify the HTTP requests. This is the reason PSR-7 and middleware are united.

The most common example of middleware is on the authentication. In an application where it is necessary to log in to get user privileges, the middleware will decide if the user can see specific content of the application:

Middleware

In the preceding image, we can see a typical PSR-7 HTTP REQUEST and RESPONSE with two MIDDLEWARE. Usually, you will see the middleware implementations as lambda (λ).

Now, we will take a look at some examples of typical implementations of middlewares:

    use PsrHttpMessageResponseInterface; 
    use PsrHttpMessageServerRequestInterface;  
    function (ServerRequestInterface $request, ResponseInterface $response, 
    callable $next = null) 
    {    
      // Do things before the program itself and the next middleware   
      // If exists next middleware call it and get its response    
      if (!is_null($next)) {  
      $response = $next($request, $response);    }    
      // Do things after the previous middleware has finished    
      // Return response    
      return $response; 
    }

The request and response are the objects, and the last param $next is the name of the next middleware to call. If the middleware is the last one, you can leave it empty. In the code, we can see three different parts: the first one is to modify and do things before the next middleware, in the second one the middleware calls the next middleware (if it exists), and the third one is to modify and do things after the previous middleware.

It is a good practice to see the code before and after the $next($request, $response) form as onion layers around the middleware, but it is necessary to be on the ball regarding the order of execution of the middlewares.

Another good practice is looking at the real application (the part of code the middlewares reach, usually a controller function) as a middleware too, because it receives a request and a response and it has to return a response, but this time without the next param because it is the last one; however, the execution continues after this. This is the reason we have to look at the end code in the same way as the last middleware.

We will see a complete example to understand how you can use it on your application based on microservices. As we saw in the preceding image, there were two middlewares, we will call them first and second, and then the end function will be called endfunction:

    use PsrHttpMessageResponseInterface; 
    use PsrHttpMessageServerRequestInterface; 
    $first = function (ServerRequestInterface $request, 
    ResponseInterface $response, callable $next) 
    {
      $request = $request->withAttribute('word', 'hello');   
      $response = $next($request, $response);    
      $response = $response->withHeader('X-App-Environment', 
      'development');
      return $response; 
    } class Second {    
      public function __invoke(ServerRequestInterface $request, 
      ResponseInterface $response, callable $next) 
      {
        $response->getBody()->write('word:'. 
        $request->getAttribute('word'));        
        $response = $next($request, $response);       
        $response = $response->withStatus(200, 'OK');
        return $response;    
      } 
    }
    $second = new Second; $endfunction = function (
    ServerRequestInterface $request, ResponseInterface $response) 
    {
      $response->getBody()->write('function reached');   
      return $response; 
    }

Every framework has its own middleware handler, but each one works very similarly. The middleware handler is used to manage the stack, so you can add more middleware on it and they will be called sequentially. This is a generic middleware handler:

    class MiddlewareHandler {
    public function __construct()
    { //this depends the framework and you are using
        $this->middlewareStack = new Stack; 
        $this->middlewareStack[] = $first;        
        $this->middlewareStack[] = $second; 
        $this->middlewareStack[] = $endfunction;
    }
    ... }

The execution track will be something like this:

  1. The user requests a specific path to the server. For example, /.
  2. The first middleware is executed adding word equals to hello.
  3. The first middleware sends the execution to second.
  4. The second middleware adds the sentence word: hello.
  5. The second middleware sends the execution to the end function.
  6. The end function adds the sentence function reached and finishes its own job.
  7. The execution continues by the second middleware and this one sets the HTTP status 200 to response.
  8. The execution continues by the first middleware and this one adds a custom header.
  9. The response is returned to the user.

Of course, if you get an error during the middleware execution, you can manage it using the following common code:

    try { // Things to do } 
    catch (Exception $e) { 
      // Error happened return 
      $response->withStatus(500); 
    }

The response will be sent immediately to the user without ending the entire execution.

Available frameworks

There are hundreds of frameworks available to develop your application, but when you need one to be used to make microframeworks, it is necessary to look for some characteristics:

  • A microframework able to process the maximum requests per second
  • Lightweight in terms of memory
  • If it is possible, with a great community developing applications for that framework

Now we will look at possibly the five most-used frameworks at the moment. Finding the best framework is not a unique opinion, every developer has their own opinion, so let me introduce you to the following ones:

Framework

Request per second

Peak memory

Phalcon 2.0

1,746.90

0.27

Slim 2.6

880.24

0.47

Lumen 5.1

412.36

0.95

Zend Expressive 1.0

391.97

0.80

Silex 1.3

383.66

0.86

Source: PHP Framework Benchmark. The project attempts to measure minimum overhead PHP frameworks in the real world.

Phalcon

Phalcon is a popular framework, it gained fame because its speed made it the fastest framework. Phalcon is very optimized and modular; in other words, it only uses the things that you need or want, without adding extra things that you won't use.

The documentation is excellent, but its disadvantage is that the community is not as big as Silex or Slim, so the third-parties' community is small and it is sometimes a little difficult to find fast solutions when you have issues.

Phalcon ORM is based on the C language. This is really important if you are developing a microservice based on databases.

To sum up, it is the best framework; however, it is not recommended for beginners.

You can visit the official website at https://phalconphp.com.

Slim framework

Slim is one of the fastest micro RESTful frameworks available. It provides you with every feature that a framework should have. Also, Slim framework has a very big community: you can find a lot of resources, tutorials, and documentation on the Internet because there are a lot of developers using it.

Since the release of version 3, the framework has a better architecture, making it better in terms of overall architecture and security. This new version is a little slower than version 2, but all the introduced changes make this framework suitable for projects of all sizes.

The documentation is not bad, but it could be better. It is too short.

It is a good microframework for beginners.

Refer to the official website at http://www.slimframework.com/.

Lumen

Lumen is one of the fastest micro RESTful frameworks made by Laravel. This microframework was specially made to work with ultra fast microservices and APIs. Lumen is really fast, but there are some microframeworks that are faster, such as Slim, Silex, and Phalcon.

This framework became famous because it was pretty similar to CodeIgniter syntax, and it is very easy to use, so maybe this is why Lumen is the best microframework to start working with microservices using a microframework. Also, Lumen has very good and clear documentation; you can find it at https://lumen.laravel.com/docs. If you use this framework, you can start to work in little time as the setup is really fast.

Another advantages of Lumen is that you can start working with it and then, if you need the complete Laravel in the future, it is very easy to transform and update the framework into Laravel.

Please note that Lumen still enforces an application structure (convention over configuration) that might limit your options when you design your application.

If you are going to use Lumen, it is because you have used Laravel and you liked it; if you do not like Laravel, Lumen is not the best solution for you.

You can visit the official website at https://lumen.laravel.com/.

Zend Expressive

Lumen is the equivalent of Laravel and Zend Expressive is for Zend Framework. It is a microframework built to make microservices and is prepared to be used exclusively following PSR-7 and based on middleware.

It is possible to set it up in a few minutes and you have all the advantages of Zend Framework on it in terms of community. Also, being a product of Zend is a synonym of quality and security.

It comes with a minimal core and you can choose what components you want to include. It has very good flexibility and ability to extend it too.

Visit the official website at https://zendframework.github.io/zend-expressive/.

Silex (based on Symfony)

Silex is also a very good micro RESTful PHP framework. It is one of the five fastest microframeworks and currently, it is one of the best known because the Silex community is one of the bigger ones and they develop really good third parties, so developers have many solutions for their projects.

The community and its connection to Symfony guarantee stable implementation with many available resources. Also, the documentation is really good, and this microframework is specially good for large projects.

The advantages of Silex and Slim Framework are pretty similar; maybe the competition made them better.

Refer to the official website at http://silex.sensiolabs.org/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.196.175