📜 ⬆️ ⬇️

Phalcon: Let's learn by example

PHP MVC Framework - PhalconPHP
More recently, the Habré mentioned the PHP MVC Framework written in C, where its advantages and disadvantages were described. With this article I want to continue my acquaintance with a rather interesting web developer tool - PhalconPHP .

This article is a free translation of the basic lesson , in which the process of creating an application with a simple registration form will be reviewed, and the main aspects of the framework's behavior will be explained.

The best way to use this guide is to go through it step by step.
')
The end result can be found on github .
The application framework can be automatically generated using developer tools , but this article does not describe this feature.

Installing Phalcon PHP is quite trivial, it all comes down to installing a PHP extension, which can be downloaded from the official site.

With Phalcon PHP installed, check for the presence of the “Phalcon” section in the phpinfo () output results, or execute the snippet below:

<?php print_r(get_loaded_extensions()); 

Among other extensions, you should see phalcon:

 Array ( [0] => Core [1] => libxml [2] => filter [3] => SPL [4] => standard [5] => phalcon [6] => pdo_mysql ) 


Directory structure


Phalcon does not require the use of any particular project hierarchy; to develop an application, you can use such a structure you are used to working with.

For example, in this lesson we will use the following structure:

 tutorial /
   app /
     controllers /
     models /
     views /
   public /
     css /
     img /
     js /

Note that you do not need a directory like “library” to host the framework, Phalcon is already accessible from memory and is ready for use.

Beautiful URLs


This lesson uses human-readable URLs (CNCs). CNC is not only useful for search engine optimization, but also makes it easier for users to memorize links. Support of CNC by your application is not required, you are free to develop a project without their support.

This example uses mod_rewrite for Apache and, based on our directory structure, we need two .htaccess files: one at the root of the project, the other in a public directory.

 #/.htaccess <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] </IfModule> 

All requests to the application will be sent to the public/ directory. This step ensures that internal project folders remain hidden from public access, reducing the security risk.

The second set of rules checks if the required file exists. If the file is missing, the web server converts the request to the required form for the framework.

 #/public/.htaccess <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] </IfModule> 

Translator's note: in terms of both security and performance, it will be more efficient to take the application out of public_html, leaving only the images, js and css available. But we will not deviate from the example.

Bootstrap bootstrap


The first file you need to create is the init script. This file implements the initialization of components, it serves as the basis of the application, providing control over its entire behavior.

The public/index.php Bootstrap file looks like this:

 <?php try { //Register an autoloader $loader = new \Phalcon\Loader(); $loader->registerDirs(array( '../app/controllers/', '../app/models/' ))->register(); //Create a DI $di = new Phalcon\DI\FactoryDefault(); //Setting up the view component $di->set('view', function(){ $view = new \Phalcon\Mvc\View(); $view->setViewsDir('../app/views/'); return $view; }); //Handle the request $application = new \Phalcon\Mvc\Application(); $application->setDI($di); echo $application->handle()->getContent(); } catch(\Phalcon\Exception $e) { echo "PhalconException: ", $e->getMessage(); } 

Below we analyze each part of this file in more detail.

Autoloader


The first part of the initialization file is the autoloader registration. It is used to load controllers and models. For example, we can register one or more controller directories, increasing the flexibility of the application. In our example, the Phalcon\Loader component is used.

With it, you can load classes using different approaches, but in this example we chose to detect classes based on predefined directories.

 <?php $loader = new \Phalcon\Loader(); $loader->registerDirs( array( '../app/controllers/', '../app/models/' ) )->register(); 


Dependency management


Working with the Phalcon framework, it is necessary to understand the concept of dependency injection ( Dependency injection , wiki ). This may seem complicated, but in reality everything is very simple and practical.

Phalcon contains a mechanism that stores the components necessary for the operation of the application, and provides access to them upon request by the framework. This mechanism is the class Phalcon\DI , which acts as a link, combining the various components to work together.

 <?php //Create a DI $di = new Phalcon\DI\FactoryDefault(); 

Phalcon \ DI \ FactoryDefault is the heir of Phalcon\DI implementing dependency injection. It registers most of the standard framework components. Thus, we should not register them one by one. If necessary, you can easily replace it with your own implementation.

The next step is to register the “view” component. Since view files are not classes, they cannot be loaded using the autoloader, so we must specify their location.

 <?php //Setting up the view component $di->set('view', function(){ $view = new \Phalcon\Mvc\View(); $view->setViewsDir('../app/views/'); return $view; }); 

The Phalcon \ Mvc \ Application component is registered in the last part of this file. Its purpose is to initialize the request environment, process the route, and perform the corresponding request action. It receives a response from the controller and returns it when the process is complete.

 <?php $application = new \Phalcon\Mvc\Application(); $application->setDI($di); echo $application->handle()->getContent(); 

As you can see, the initialization file is quite simple and we do not need to include any additional files. We set the stage for a flexible MVC application in less than 30 lines of code.

Controller


By default, Phalcon searches for a controller and its action with the name “Index”. It will be executed if the controller and action are not specified in the request. The simplest controller looks like this:

 <?php class IndexController extends \Phalcon\Mvc\Controller { public function indexAction() { echo "<h1>Hello!</h1>"; } } 

The controller class has the “Controller” suffix, and its action must have the “Action” suffix. If you open the application in a browser, you will see something like this:

image

Congratulations, you are flying with a falcon! (Approx. Translator: Phalcon is consonant with the English. Falcon - Falcon * )

View


Sending output to the screen directly from the controller is justified, but you should not do so. The necessary data should be transferred to the view responsible for the display on the screen. Phalcon will look for a view in a file with the same name as the last action taken, in a directory with the name of the last controller that was executed.

In our case, this is app/views/index/index.phtml :

 <?php echo "<h1>Hello!</h1>"; 

And the controller itself ( app/controllers/IndexController.php ) now contains an empty action:

 <?php class IndexController extends \Phalcon\Mvc\Controller { public function indexAction() { } } 

The view is processed automatically after the completion of the action. The output in the browser should remain the same.

Registration form


Change the view app/views/index/index.phtml by adding a link to another “signup” controller:

 <?php echo "<h1>Hello!</h1>"; echo Phalcon\Tag::linkTo("signup", "Sign Up Here!"); 

The generated HTML will display the <a> tag with a link to the new controller:

 <h1>Hello!</h1> <a href="/test/signup">Sign Up Here!</a> 

To generate a link, the Phalcon \ Tag class was used. This auxiliary class allows you to build HTML in accordance with the framework standard. Here you can find a more detailed description of the generation of HTML code.

image

This is the new “Signup” app/controllers/SignupController.php ( app/controllers/SignupController.php ):

 <?php class SignupController extends \Phalcon\Mvc\Controller { public function indexAction() { } } 


The empty action “indexAction” directs to the form view ( app/views/signup/index.phtml ).

 <?php use Phalcon\Tag; ?> <h2>Sign using this form</h2> <?php echo Tag::form("signup/register"); ?> <p> <label for="name">Name</label> <?php echo Tag::textField("name") ?> </p> <p> <label for="name">E-Mail</label> <?php echo Tag::textField("email") ?> </p> <p> <?php echo Tag::submitButton("Register") ?> </p> </form> 

Opening this controller in the browser you will see something like this:

image

Phalcon\Tag provides useful methods for creating form elements.
In the Phalcon\Tag::form method, we passed the path to the controller / action of the application that will process the form.

By clicking on the “Register” button you will see an exception thrown from the framework, indicating the absence of the “register” action in the “signup” controller.

PhalconException: Action “register” was not found on controller “signup”

By implementing this action we will get rid of the exception:

 <?php class SignupController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function registerAction() { } } 

Again, sending the form you will see a blank page.

The username and email entered must be saved in the database. In accordance with the principles of MVC, interaction with the database must be carried out by the application model to provide clean object-oriented code.

Model


Phalcon brings the first ORM for PHP, written entirely in C. Instead of increasing the complexity of development, it simplifies it.

Before creating our first model, we need to have a table in the database. A simple table for storing registered users might look like this:

 CREATE TABLE `users` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(70) NOT NULL, `email` varchar(70) NOT NULL, PRIMARY KEY (`id`) ); 

The model must be located in the app/models directory.
This will look like a model that provides access to the “ users ” table:

 <?php class Users extends \Phalcon\Mvc\Model { } 


DB connection


In order to be able to use a database connection and access data through models, we need to specify connection settings in the initialization file. Connecting to a database is just another component that other components can later use.

The updated bootstrap file (public / index.php) will look like this:

 <?php try { //Register an autoloader $loader = new \Phalcon\Loader(); $loader->registerDirs(array( '../app/controllers/', '../app/models/' ))->register(); //Create a DI $di = new Phalcon\DI\FactoryDefault(); //Set the database service $di->set('db', function(){ return new \Phalcon\Db\Adapter\Pdo\Mysql(array( "host" => "localhost", "username" => "root", "password" => "secret", "dbname" => "test_db" )); }); //Setting up the view component $di->set('view', function(){ $view = new \Phalcon\Mvc\View(); $view->setViewsDir('../app/views/'); return $view; }); //Handle the request $application = new \Phalcon\Mvc\Application(); $application->setDI($di); echo $application->handle()->getContent(); } catch(\Phalcon\Exception $e) { echo "PhalconException: ", $e->getMessage(); } 

Now our models are ready to work and interact with the rest of the application.

Saving data using the model


Our next step: getting data from a form and writing it to a table.
Let's add the “register” action:

 <?php class SignupController extends \Phalcon\Mvc\Controller { public function indexAction() { } public function registerAction() { //Request variables from html form $name = $this->request->getPost("name", "string"); $email = $this->request->getPost("email", "email"); $user = new Users(); $user->name = $name; $user->email = $email; //Store and check for errors if ($user->save()) { echo "Thanks for register!"; } else { echo "Sorry, the following problems were generated: "; foreach ($user->getMessages() as $message) { echo $message->getMessage(), "<br/>"; } } } } 


You can never trust the data received from the user. The data transferred to our application must be validated / filtered . This will make the application more secure from attacks like SQL injections.

In our application, we apply the “ string ” filter to the entered name and the “ email ” filter to the email address to make sure that the user has not sent us any malicious characters.

The Phalcon \ Filter component makes this task elementary, since it is embedded from the dependency container in a call to the getPost method.

Next, we create an instance of the Users model. Public properties of the model correspond to the fields in the users table. By setting the values ​​of the new model and calling the save() method, we write to the database. The save() method returns a Boolean value that informs us whether the record was successful.

Additional validation occurs automatically for fields that are marked as not null (i.e., are required). If you leave the fields blank when sending the form, then in the browser you will see the message:

Sorry, the following problems were generated: name is required
email is required


Conclusion


This very simple lesson is designed to show how easy it is to start developing your application on the Phalcon PHP framework. The fact that Phalcon is an extension to PHP written in C does not contradict the simplicity of development.

I invite you to continue to study the manual , which will open for you the additional features offered by Phalcon!

___
* Falcon is the fastest bird, and generally a living creature, in the world. But, in fairness, it is worth noting that in the speed of horizontal flight, the falcon is inferior to the swift.

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


All Articles