Native MVC for Silex PHP Framework

After reading an article telling how to modify the Silex micro-framework for MVC architecture, I got a double impression. The method has the right to life, however:

  1. the project does not always need ORM, I want to have a simple implementation of the Model;
  2. Silex already has (albeit not quite explicit) native controllers;
  3. writing your autoloaders when you can add the right thing to Composer is not good.

Let's see what can be done.

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

I configured the virtual host on the folder project/public, so there .htaccesswill be one
# project/public/.htaccess

    Options -MultiViews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

Installing Silex Using Composer Package Manager

Recently, Silex supports this installation method, and here's why you need to use it:
  • the ability to update all libraries to current or required versions with one command;
  • generating one autoloader for everything you need.

Let's create a file with the project/protected/composer.jsonfollowing 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 bit later) from project/protected/Providers, and the Controllers from project/protected/app/Controllers.
A set of commands for installation:

cd / path / to / project / protected
curl -s | php
php composer.phar install

Silex providers

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


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

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, that's all. Now we can load any one located in the directory project/protected/app/Modelsusing the construction $app['models']->load('Class', 'Method', $data)with the ability to transfer the necessary data to it $data. It remains only to register our provider in Silex.


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

register(new Providers\ModelsServiceProvider(), array(
    'models.path' => __DIR__ . '/../protected/app/models/'
$app->mount('/', new Controllers\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 on the code. The method connect()tells Silex that the routes described inside should be processed as part of the controller that we mounted in index.php (in this case, the base URL for this controller is the application root - /). Then a variable is created $index, it is something like a particle $appand has only routing functions. Routes themselves are written as usual.


Что в итоге? Простейшая реализация MVC, с возможностью в любой момент начать писать в стандартном для Silex стиле. В данном контексте не рассматривалось Представление, так как уже есть множество готовых решений, из который лично я предпочитаю использовать Twig, благо интеграция с Silex у него 100%.
Весь проект доступен на github.

Also popular now: