📜 ⬆️ ⬇️

Phalcon - Compiled PHP MVC Framework


Creating compiled MVC frameworks for PHP more than once came to the mind of coders.

The advantages of this approach:

And by itself no less obvious flaws:



In this article I will try to introduce another attempt to make a compiled PHP MVC Framework.
')

Acquaintance


I myself am in search of a fast, reliable and capable framework. Walking on foreign forums and blogs, I stumbled upon an interesting benchmark, where a certain framework on “Hello World!” Did belly-bellied celebrities several times.



I couldn’t go past this and began to find out how it works and develops.
Project less than a year. The first commit on github is January 10, 2012. And yes, this is an open source project. As I understand it, now 3 people are less actively involved in it.

The authors are trying to give people the opportunity to write code without thinking about its performance, adhering to standards and giving access to most of the methods used, which are loaded into memory from the start of the server.

Example

The best way to learn the framework is to do something on it, while at the same time studying the documentation.
I made a 3-page application showing some of the features of phalcon , namely:

In addition, the developers say much more:


Project Hierarchy:

 xmpl /
     apps /
         app / config /
         app / controllers /
         app / models /
         app / views /
         app / My /
     public /
         public / img /
         public / css /
         public / js /


All code will be located along the path / apps /, initialization of the application /public/index.php. On the last file, in fact, you need to configure the redirect of nonexistent pages, via apache (.htaccess in the folders / and / public /) or nginx .

Initialization:

About initialization in brief under the spoiler.
<?php //    ini  $config = new Phalcon\Config\Adapter\Ini( '../apps/config/config.ini' ); // ,  ,      $loader = new \Phalcon\Loader(); $loader->registerDirs(array( $config->application->controllersDir, $config->application->modelsDir, $config->application->myDir, )); $loader->register(); // DI $di = new \Phalcon\DI(); //,    url. $di->set('url', function() use ($config){ $url = new \Phalcon\Mvc\Url(); return $url; }); //    ,  ( Mysql, PostgreSQL, SQLite) $di->set('db', function() use ($config) { $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array( "host" => $config->database->host, "username" => $config->database->username, "password" => $config->database->password, "dbname" => $config->database->name )); return $connection; }); //2       $di->set('modelsManager', function(){ return new Phalcon\Mvc\Model\Manager(); }); //,   -  ,  (Apc, Files, Memory, Session) $di->set('modelsMetadata', function(){ return new \Phalcon\Mvc\Model\Metadata\Memory(); }); //  $di->set('router', 'Phalcon\Mvc\Router'); // ,      view  .    . $di->set('dispatcher', function() use ($di) { $dispatcher = new Phalcon\Mvc\Dispatcher(); return $dispatcher; }); //    $di->set('response', 'Phalcon\Http\Response'); $di->set('request', 'Phalcon\Http\Request'); //   $di->set('filter', function(){ return new \Phalcon\Filter(); }); //    Volt   $di->set('voltService', function($view, $di) use ($config) { $volt = new Phalcon\Mvc\View\Engine\Volt($view, $di); $volt->setOptions(array( "compiledPath" => $config->application->templCompDir, "compiledExtension" => ".compiled" )); return $volt; }); // ,   .    eventManager, //,     view.    //      $di->set('view', function() use ($config) { $eventsManager = new \Phalcon\Events\Manager(); $viewManager = new ViewManager(); $eventsManager->attach('view', $viewManager); $view = new \Phalcon\Mvc\View(); $view->setViewsDir( $config->application->viewsDir ); $view->registerEngines(array( ".phtml" => 'voltService' )); $view->setEventsManager($eventsManager); return $view; }); //    ,  front (Base64, Data, None, Output)  backend (Apc, File, Memcache, Mongo),  ,     $di->set('cache', function(){ $frontCache = new Phalcon\Cache\Frontend\Data(array( "lifetime" => 60 )); $cache = new Phalcon\Cache\Backend\Apc($frontCache); return $cache; }); //         try { $application = new \Phalcon\Mvc\Application(); $application->setDI($di); echo $application->handle()->getContent(); } catch(Phalcon\Exception $e){ echo $e->getMessage(); } 



Most can be connected automatically, like this:
 $di = new Phalcon\DI\FactoryDefault(); 


Controllers and their classes:

Now, standard routing is available in your application / baseUri / ControllerName / ActionName / , methods are connected that via di inherit the $ this-> cache, $ this-> dispatcher, $ this-> db controllers ...

You can also call your classes located in the / apps / My / folder
The ViewManager class will receive all the events generated by the View . On interests beforeRender . In it, we will transfer to the view variables containing the name of the class and the action.

We will also create the BaseController class.
 class BaseController extends \Phalcon\Mvc\Controller { public function initialize() { Phalcon\Tag::prependTitle('Example | '); } } 

 class IndexController extends BaseController { public function initialize() { //    title,     (   Poll) Phalcon\Tag::setTitle('Index'); parent::initialize(); } public function indexAction(){ } } 


It inherits the standard class. Our controllers will already inherit BaseController and get the prefix to the html title tag.


View

Phalcon provides a fairly convenient template method where a hierarchy exists.
Templates are stored in the / apps / views / folder .
The root pattern /apps/views/index.phtm is rendered by all controllers, except those where a different path is explicitly specified.
This file may contain the further path of the hierarchy:
 {{ content() }} 


I used the built-in template engine syntax. For other engines, too, have their own counterparts.
This function calls the following pattern, located along the path:
/apps/view/layer/ControllerName.phtml

Essentially, setting a specific layout for a particular controller, as I did in my application. You can also call content () in it , thereby loading the template /apps/views/ControllerName/ActionName.phtml

In templates, you can load other templates, replace the pre-set blocks, call custom functions and predefined by the engine, refer to the Models methods.
Only Volt is their young project, so many functions are not in it, but they are planned for the next releases.
Out of the box, support Slim , Smarty , Mustache ...

Out of the box there is the possibility of caching compiled templates, only in the version up to 0.6.0 inclusive, there is a bug that resets the cache and returns a blank page.

Models

Connection to the database is carried out using PDO. There are 2 database implementations, an object-oriented path and PHQL, its own pseudo-SQL string handler.
Unfortunately, the first is only suitable for fairly simple requests, and the second will be difficult for those who are used to the first.

Model in the application
 class Poll extends Phalcon\Mvc\Model { //    ,  ,    public public $id; public $gender; public $age; public $read_modern; public $authors; public $genre; public $method; public $timestamp; //    ,      public function getSource() { return 'answers'; } //     public function initialize() { $this->setConnectionService('db'); } } 



In the models, for myself, I did not find anything new and interesting, except that the storage of metadata in different places. They can also be completely predetermined.

disadvantages

I did not fully understand everything that this framework could do, but I still noticed the flaws:

It is difficult to call it flaws. Unless there is no direct communication with the developers, except for the issue list on the githabe.

Application Functionality


We have an application with the main page, the survey page and the output of the results. From here work with DB, sending data with filtering, and receiving with minute caching in Apc.

Iron: VPS hosting. Processor x1 500 MHz, OP 256 MB. The horse is weak.
APC is connected. The settings are all default. Server: Nginx - PHP-FPM - PHP - MySQL

Synthetic tests:
1. -c50 -d5 -r10
2. -c100 -d2 -r10
3. -c300 -d2 -r20 (LA - 0.7)
4. -c400 -d1 -r20 (LA - 0.47)
5. -c800 -d1 -r30 (LA - 1.1)
6. -c1000 -b -r20 (LA - 2)
(-c: competitors, -d: delay before re-call, -r: number of repetitions, -b: call without delay, LA: load average)


Siege makes in random order 3 queries, all dynamic. 2 of them with queries to the database, with caching in 1 minute.
With great competition, errors appeared (up to 2% of requests).
Maximum processed 516 requests per second. Pretty bad. If you store the requested json in files and update them by cron, you can reduce the load several times.

Spent a couple more tests with siege. -c500 -r10 -d1 -i
1. APC is disabled
2. APC is enabled with a small buffer and stat = 0
image

Links


Phalcon website
Phalcon repository

Working example
Sample sources on GitHub

PS

The survey in the application is not just chosen, please answer honestly;)
And I apologize for the confusion, in one article lay out everything is impossible.

11/19/2012 23:00
Someone decided to query for returning results from the database. Logs grow in yeast. LA ranges from 1 to 4. The site is loaded. I am very happy :)
Ddosyat with wrk . Judging by the logs comes to 60 requests per second. ip 188.254.105.18
11/19/2012 11:43 PM
I spam a 0.5GB log and that's enough. Bye ddos.

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


All Articles