📜 ⬆️ ⬇️

How PHPixie Works - The Life of a Single Query, Container and Paradigm

image
I have already written many times about the PHPixie framework and programming on it. This time we will look inside and see the life cycle of the application; fortunately, the simplicity and linearity of the code allows us to do this with relative ease.

Like for example symfony, PHPixie consists of two parts: a component library and a basic project, although in the case of PHPixie, the basic project is thinner and consists of only a few files. Here he plays the role of an example and therefore changing it for himself is not only welcomed but in some cases is even necessary. For this it is important to understand what is happening in the system and how. Using my somewhat limited drawing skills, I prepared a query processing diagram.


PHPixie
')
Of course, for those who are already familiar with MVC (or even VC in this case, since I did not draw a model), this scheme will probably seem familiar, but for beginners it can be very useful. So let's start with index.php where all requests fall, here the most important lines are:
$pixie = new \App\Pixie(); $pixie->bootstrap($root)->handle_http_request(); 


And immediately we get to the most important part, the App \ Pixie class which is the heart of the framework, its DI container. Through it you can access all other components. The App \ Pixie inherits from PHPixie \ Pixie from the PHPixie-Core library. The basic project announces this class instead of using PHPixie \ Pixie directly to provide the developer with the opportunity to make changes to it (for example, to connect a module).

It should be noted right away that it is impossible to add new entities to this container on the move, as for example in Silex, everything must be explicitly described in the class. Although it may not seem so convenient at first glance, it does allow for better readability of the code, fully document all entities (since they all become class attributes), and also get hints on these entities in the IDE. Since PHPixie \ Pixie also contains all the factor methods, this will allow us to easily replace any framework class with your own by overloading the corresponding method.

The bootstrap () method initializes $ pixie, reads the configuration, enables exception handling, and so on. Just in handle_http_request () the request is processed. This process consists of three steps:


All three of the most important $ request, $ response and $ pixie objects are available as attributes of the PHPixie \ Controller class. Now let's digress a bit into a few more paradigms of writing PHPixie code:

Do not use the operator "new" anywhere except for factor methods. Each new class must have a factor method (for example, in App \ Pixie) to create instances of it. This approach makes it easy to replace one class with another, which is especially important when writing unit tests. So testing for example the controller, you can now transfer the locked App \ Pixie into it, which instead of the real classes will transfer their mocks.

Do not use static properties and methods. Using statics makes writing tests much harder. Using PHPixie, you can easily do without them, just add an instance as an App \ Pixie attribute and you can access it from almost anywhere. So we will actually get a singleton. By the way, this can be done by adding it to $ instance_classes.

 namespace App; class Pixie extends \PHPixie\Pixie { public function __construct() { $this->instance_classes['singleton'] = '\App\Singleton'; } } //     $pixie->singleton   , //      .     //          


How modules work

Each module for PHPixie is an additional class library that provides its DI container very similar to the main PHPixe \ Pixie, that is, it consists of factory methods for creating instances of classes that are included in the module. Then we simply add it to the array of modules in the main container:

 namespace App; class Pixie extends \PHPixie\Pixie { protected $modules = array( 'db' => '\PHPixie\DB', 'orm' => '\PHPixie\ORM' ); } //     $pixie->db  $pixie->orm 


And what if I, for example, want to replace the PHPixie \ ORM \ Model class with my App \ Model? It's simple, you still have to make your App \ ORM (extends PHPixie \ ORM) whose get () method instead of the PHPixie \ ORM \ Model will return the one you need. this is even more evident in one of the framework's ideas - to use standard OOP techniques instead of some magic as much as possible. For example, to substitute the class of the framework itself, you have to use subclass_prefix and do it at the configuration level and not at the actual programming. This approach allows a much better understanding of the system, since for the most part you can understand the flow without knowing anything about the framework, just by looking at the classes themselves.

But what about hooks, events and so on?

They are not, and I understand it will not. Such things are completely out of a different paradigm, since they make the code non-linear, this is especially true for events, where it is not always completely clear which of the listeners will start first and what happens if it causes some event. And also the readability of the becktrays very often suffers from their use, since they are caused by the framework itself somewhere where the programmer himself did not write the code exactly. If you need to do something in a certain place, it is much easier to overload the method that does just that and add the logic that you need to it.

In the next article, I will either look at how PHPixie works with databases in more detail, or explain in more detail the pros and cons of linear versus event driven programming.

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


All Articles