Building a modern PHP API in 2020

So, using this API as an example, I want to show a modern PHP architecture for high-load projects. When the project is still at the very beginning, and not that the business logic (relationship with the database) is not spelled out, but the business model itself is not very clear, building an effective IT architecture can only go one way: it is necessary to rigidly separate the frontend and backend.



What did you usually do in such situations two or three years ago? A monolithic framework like Laravel or Yii2 was taken, the entire business model was broken, at least, into blocks, and these blocks were already implemented as framework modules. As a result, after another 3 years, a huge non-rotating machine was obtained, which is slow in itself, but became almost unbearably slow, in which the frontend is rendered through the backend using the classic MVC architecture (the user sent a request, the controller picked it up, called the model, which in turn I did something with the database, returned everything to the controller, and the controller finally called the viewer, inserted the data from the model there and gave it all to the user who had already opened another can of beer ...). And ... well, some more advanced guys, they didn't just view Tweeter Bootstrap,and actually very good libraries like JQuery were screwed into the viewer, or instead of the viewer they used some frontend framework. As a result, it became more and more difficult to maintain such a BeLaZ, and it was very difficult to introduce a new programmer to the team, because not everyone is born Einstein. Let's add here the total lack of developer documentation (you read the comments in 9000 files - everything is there!) And in the end, looking at everything, it became really sad ...it became really sad ...it became really sad ...



But then a series of events took place, which radically changed the situation. Firstly, finally, the PSR standards came out and Symfony suddenly ceased to be the only modular framework, and secondly, ReactJS came out, which made it possible to fully separate the frontend from the backend and force them to communicate through the API. And finishing the last nail in the coffin of the old development system (MVC is our everything!) OpenAPI 3.0 comes out, in fact, which regulates the standards of this communication through the API between the frontend and backend.



And in the PHP world, it became possible to do the following:



  1. , , โ€” : ( GET โ€” , API, , ReactJS . , ...
  2. API OpenAPI 3.0 ( swagger.io ) YAML JSON , , , YAML , . YAML middleware . .
  3. -, , - API , API: github.com/OpenAPITools/openapi-generator โ€” 40 API , โ€” Dlang.


So, I think we figured out the API. We write a YAML file in swagger or insomnia, through OpenAPITools we generate a server and custom libraries. We do not touch the abstract classes (daddy lib), but move all the business logic into inherited classes (daddy scr), so that during the subsequent regeneration of the server we do not break anything, but simply stupidly copied the daddy lib to our framework root and added new business logic in a non-relocatable daddy scr. API ready - fast, simple, functional. The client libraries are ready too. The director did not even have time to return from the Maldives ...



Now there are questions, or rather two questions: what do we have in front of the API and, accordingly, what is behind us after the API.



Answers:



1. "There, beyond the river", far in front of the API we are blooming, spreading to new functionality and pictures - FRONTEND (ReactJS is preferable, but Vue will do too. Although there is so much out of the box that it will make the process heavier, but how much in real life it will be needed - not entirely clear and depends directly on the business model). And NO! I won't even come close to this beast, because since childhood I have been allergic to it. A separate specialist is needed here. I am not a full stack and I do not write a frontend.



2. Right in front of the API itself, we ... DO NOT GUESS ... not NGINX, but RoadRunner roadrunner.dev/features . We go in, read, understand that it is faster and the walkers are signed by the number of processors, and therefore there will never be a sign โ€œWE ARE IN PREVENTIONโ€, because you just need to switch the walkers.



And I want to dwell on this point in more detail. For in my view there are three ways "how to fly fish" queries I mean ...



1. If the entire API has been written and will be written in the future, on PHP - why not head to break, put RoadRunner with prometheus.io



2. In if the system is assembled from different pieces, different services are written in different languages โ€‹โ€‹and then it is also not clear what they will be written in:



2.1. Install NGINX UNIT - we use supported languages.



2.2. We lift EVERYTHING ANY system of containers, Docker, LXC, LXD. The choice again depends on the size of the project - to support the assembly of PROXMOX-LXC on hosting with 12 processors, with 32GB of memory, for 40 euros per month will be several times cheaper than Docker assemblies on the Google Cloud Platform. We put a server suitable for the language in each container, and connect all this to HAProxy www.haproxy.org . HAProxy is a gorgeous balancer and proxy server that is no less popular in a corporate environment than NGINX. What it does and what it doesn't, read here cbonte.github.io/haproxy-dconv/2.3/intro.html paragraph 3.1. With this architecture, services or microservices can be written on anything and no one depends on the restrictions imposed by RoadRunner or NGINX UNIT.



3. "Under the tail" - Cycle ORM. We are not lazywatch the video , what will be behind it specifically MySQL or PostgreSQL - again, I would leave on after the business scheme of the project is clear. MySQL scales easier, PostgreSQL has more business logic moved inside the database itself.



4. An example that you can see and touch . There, a test task is taken as a basis. All the most useful things are in the EXTRAS folder. There is already a generator jar file, a YAML swagger API file, generated by the API stub via OpenAPITools in SLIM4. Even with authentication and middleware. API documentation generated by swagger, not OpenAPITools. It is assumed that some users are logged in and issued a token. There is already RoadRunner in front. The stack is PHP 7.4.10, PostgreSQL 12.4.



After Git clone, composer install in the /bootstrap.php file, write the user and password to the database, which we first create, because this is PostgreSQL, by default the server listens to the local port 8888, if necessary, change it in the /.rr.yaml file, and execute command: composer run-script fill-database. All - no migrations. We are using.



PS All logged in users are assigned the same token. Generally there are no user input validations and almost no protections in the example - this example is mainly aimed at architecture. Best



regards,

Kirill Lapchinsky

api-studio.com

mail@api-studio.com



All Articles