📜 ⬆️ ⬇️

Symfony 2.0, RequestHandler Component

The site Symfony Components about the component RequestHandler says something like this:
Flexible micro core for fast frameworks.

Is this how it is and what is RequestHandler in Symfony 2, I will try to consider in this topic.

If you look at the processing of the request in a Symfony 2 based application , namely, the run() method of the Symfony\Foundation\Kernel class, you will see that after creating and saving the container in the cache or loading the cache from the DI cache, the request handler object is received and calling its handle() method in parameters, to which the request object is passed, also received from the DI container by the way. This method should return a response object for which the send() method is called to send a response. In general, RequestHandler assumes the first blow when processing a request, it also returns the response object, so I decided to start the overview of the components included in Symfony 2 with it.

First, let's take a look at Symfony/Foundation/Resources/services.xml since this is where the description of the RequestHandlerService service in the DI container occurs.

 <parameter key = "request_handler.class"> Symfony \ Components \ RequestHandler \ RequestHandler </ parameter>
 <parameter key = "request.class"> Symfony \ components \ RequestHandler \ Response </ parameter>
 ...
 <service id = "request_handler" class = "% request_handler.class%">
   <argument type = "service" id = "event_dispatcher" />
 </ service>
 <service id = "request" class = "% request.class%" />

From this description, it becomes clear that the request object is simply created as new Request() , and the request handler object as new RequestHandler($dispatcher) , where $dispatcher an EventDispatcher class object, which is an event dispatcher.
')
Looking in Symfony / Components / RequestHandler we will see the following set of files:

Well, in general, everything is almost obvious. Much is clear without even looking inside the classes. But still briefly about everything. Classes of exceptions, which are used when the corresponding situations arise, all that is done in them is the message and the response code. Request - a request class that parses environment variables, parameters and everything related to the request. Response - the response class that contains the body of the response, forms the headers and everything related to the response. RequestHandler is a request handler. Perhaps consider it in more detail.

In fact, everything that the request handler does is using the Event Manager dispatched to it in the parameters (EventDispatcher) generates various events, thereby notifying applications about the different stages of parsing the request and forming a response. And depending on the reaction of the listeners (listeners) to these events, it terminates or generates the next event.

The list of events that the request handler creates:

That is, events reflect the main stages of parsing a request and forming a response. RequestHandler checking the application's reaction to events continues to create events or terminates. Accordingly, the application is hanging their handlers on certain events involved in the formation of a response. However, some parts of the application may not know anything about each other.

Better, probably try it out with an example. What in general I will do now. So, let's strip Symfony to the goal, removing everything except the kernel and hang our handler on the core.request event, at the same time there will be a small demonstration of the flexibility of the framework.

The example will be based on a sandbox with an updated version of symfony, how the environment was created can be seen here .

So let's start with configs. In the hello/config/config.yml file, hello/config/config.yml comment out everything except the kernel.config: ~ line kernel.config: ~ . Now fix the application kernel, the file hello/HelloKernel.php

 # hello / HelloKernel.php
 // remove all bundles, except for the kernel and our application
 public function registerBundles ()
 {
   return array (
     new Symfony \ Foundation \ Bundle \ KernelBundle (),
     new Application \ HelloBundle \ Bundle (),
   );
 }

Now, it is necessary to describe the necessary parameters and services in the DI container. To do this, we first create our own extension for the DI container, create the src/Application/HelloBundle/DependencyInjection directory, and the HelloExtension.php file with the following contents in it:

 namespace Application \ HelloBundle \ DependencyInjection;

 use Symfony \ Components \ DependencyInjection \ Loader \ LoaderExtension,
     Symfony \ Components \ DependencyInjection \ Loader \ XmlFileLoader,
     Symfony \ Components \ DependencyInjection \ BuilderConfiguration,
     Symfony \ Components \ DependencyInjection \ Reference,
     Symfony \ Components \ DependencyInjection \ Definition;

 class HelloExtension extends LoaderExtension
 {
   public function helloLoad ($ config)
   {
     $ configuration = new BuilderConfiguration ();

     $ loader = new XmlFileLoader (__ DIR __. '/ .. / Resources / config');
     $ configuration-> merge ($ loader-> load ('hello.xml'));
    
     return $ configuration;
   }

   public function getAlias ​​()
   {
     return 'hello';
   }

   public function getNamespace ()
   {
     return 'http://poulikov.ru/schema/dic/hello';
   }

   public function getXsdValidationBasePath ()
   {
     return __DIR __. '/ .. / Resources / config /';
   }
 }

Now let's register our extension:

 # src / Application / HelloBundle / Bundle.php
 // use our extension
 use Application \ HelloBundle \ DependencyInjection \ HelloExtension;

 ...

 // register the extension in the container
 public function buildContainer (ContainerInterface $ container)
 {
   Loader :: registerExtension (new HelloExtension ());
 }

Our extension will look for the hello.xml file along the path src/Application/HelloBundle/Resources/config/hello.xml
so create this file, with something like this:

 <container xmlns = "http://www.symfony-project.org/schema/dic/services"
     xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance"
     xsi: schemaLocation = "http://www.symfony-project.org/schema/dic/services http://www.symfony-project.org/schema/dic/services/services-1.0.xsd">

   <parameters>
       <parameter key = "request_parser.class"> Application \ HelloBundle \ Request \ Parser </ parameter>
   </ parameters>

   <services>
     <service id = "request_parser" class = "% request_parser.class%">
         <annotation name = "kernel.listener" event = "core.request" method = "resolve" />
         <argument type = "service" id = "service_container" />
     </ service>
   </ services>
 </ container>

In this file, we have defined the service that is core.request to listen for the core.request event core.request
Now create the query parser:

 # src / Application / HelloBundle / Request / Parser.php

 namespace Application \ HelloBundle \ Request;

 use Symfony \ Components \ DependencyInjection \ ContainerInterface;
 use Symfony \ Components \ EventDispatcher \ Event;
 use Symfony \ Components \ Routing \ RouterInterface;

 class parser
 {
   protected $ container;

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

   public function register ()
   {
     $ this-> container-> getEventDispatcherService () -> connect ('core.request', array ($ this, 'resolve'));
   }

   public function resolve (Event $ event)
   {
     $ response = $ this-> container-> getResponseService ();
     $ response-> setContent ("<div> Hello, World! I'm Symfony 2.0 lite </ div>");

     $ event-> setReturnValue ($ response);
     $ event-> setProcessed (true);
   }
 }

Now the final touch, in the config hello/config/config.yml add the line hello.hello: ~
It's all! Now, contacting any address, we get the answer:
Result
Completely useless application turned out. But this example is easy to show how it works, you can pick up to other events. Everything is very flexible and convenient.

Source: https://habr.com/ru/post/89202/


All Articles