📜 ⬆️ ⬇️

Native MVC for Silex PHP Framework

After reading the article telling how to modify the Silex micro-framework under the MVC architecture, I had a dual impression. The method has the right to life, however:

  1. ORM is not always needed in the project, I want to have a simple implementation of the Model;
  2. in Silex there are already (although not quite explicit) native controllers;
  3. writing your autoloaders when you have the opportunity to add what you need to Composer is not good.

Let's see what can be done.

We will adhere to the following structure of the application:
+ project | + protected | composer.json | composer.phar | composer.lock | + app | + Controllers | + Models | + Views | + vendor | + providers | + Providers | + public | .htaccess | index.php | + css | + img | + js 

I set up a virtual host on the project/public folder, so .htaccess will be one
 # project/public/.htaccess <IfModule mod_rewrite.c> Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule> 

Install Silex using Composer package manager


Recently, Silex supports this installation method and that is why you need to use it:

Create a project/protected/composer.json file of approximately the same content (depending on what you need):

  {
     "require": {
         "silex / silex": "1.0. *"
     },
     "minimum-stability": "dev",
     "autoload": {
         "psr-0": {
             "Providers": "",
             "Controllers": "app /"
         }
     }
 }

Here we want to get Silex itself and indicate that we will load our Providers (about them a little further) from project/protected/Providers , and Controllers from project/protected/app/Controllers .
A set of commands to install:
')
  cd / path / to / project / protected
 curl -s http://getcomposer.org/installer |  php
 php composer.phar install


Silex Providers


Providers is a great Silex feature that allows you to implement third-party functionality. Providers are of two types: ControllerProviderInterface for controllers and ServiceProviderInterface for everything else (in our case - for the Model).

Model


Let's write a simple Service Provider and model loader.

 <?php // project/protected/Providers/ModelsServiceProvider.php namespace Providers; use Silex\Application; use Silex\ServiceProviderInterface; class ModelsServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['models.path'] = array(); $app['models'] = $app->share(function($app) { return new Models($app); }); } public function boot(Application $app) { } } class Models { private $app; public function __construct(Application $app) { $this->app = $app; } public function load($modelName, $modelMethod, $data = array()) { require_once $this->app['models.path'] . $modelName . '.php'; $Model = new $modelName($this->app); return $Model->$modelMethod($data); } } 

With the Model, in general, everything. Now we can load any one located in the project/protected/app/Models directory using the $app['models']->load('Class', 'Method', $data) construction with the ability to transfer the required data to it $data . It remains only to register our provider in Silex.

Controller


The only thing we need to take care of directly is about autoloading the controller classes, but Composer has already done this for us. So now we can connect controllers using the standard Silex mount method. Let's see how the index.php file, the simplest Controller and Model will look like.

index.php
 <?php // project/public/index.php require_once __DIR__ . '/../protected/vendor/autoload.php'; $app = new Silex\Application(); $app->register(new Providers\ModelsServiceProvider(), array( 'models.path' => __DIR__ . '/../protected/app/models/' )); $app->mount('/', new Controllers\Index()); $app->run(); 


Controller
 <?php // project/protected/Controllers/Index.php namespace Controllers; use Silex\Application; use Silex\Route; use Silex\ControllerProviderInterface; use Silex\ControllerCollection; class Index implements ControllerProviderInterface { public function connect(Application $app) { $index = new ControllerCollection(new Route()); $index->get('/', function() use ($app) { $label = $app['models']->load('Pages', 'index'); return $label; }); $index->get('/{name}', function($name) use ($app) { $name = $app['models']->load('Pages', 'hello', $name); return "Hello{$name}"; }); return $index; } } 

Briefly by code. The connect() method tells Silex that the routes described inside must be processed as part of the controller that we indexed into index.php (in this case, the base URL for this controller is the application root - /). Next, the $index variable is created, it represents something like a $app and has only routing functions. The routes themselves are written as usual.

Model
 <?php // project/protected/Models/Pages.php class Pages { public function index() { return "Index"; } public function hello($name) { return ", {$name}!"; } } 


What is the result? The simplest implementation of MVC, with the ability to start writing at any time in the standard for Silex style. In this context, the View was not considered, as there are already many ready-made solutions, from which I personally prefer to use Twig , since integration with Silex is 100%.
The whole project is available on github .

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


All Articles