Scaling Silex applications (part II). Using RouteCollection


In the post Scaling Silex applications I wanted to organize a one Silex application. In one comment Igor Wiedler recommended us to use RouteCollections instead of define the routes with a Symfony’s Dependency Injection Container. Because of that I started to hack a little bit about it and here I show you my outcomes:

I want to build an imaginary application with silex. This application has also one Api and one little blog. I want to organize those parts. Our index.php file

<?php
// www/index.php
require_once __DIR__ . '/../vendor/autoload.php';

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RouteCollection;
use Silex\Application;

$app = new Application();

$app['routes'] = $app->extend('routes', function (RouteCollection $routes, Application $app) {
    $loader     = new YamlFileLoader(new FileLocator(__DIR__ . '/../config'));
    $collection = $loader->load('routes.yml');
    $routes->addCollection($collection);

    return $routes;
});

$app->run();

Now our routes.yml file:

# config/routes.yml

home:
  path: /
  defaults: { _controller: 'Gonzalo123\AppController::homeAction' }

hello:
  path: /hello/{name}
  defaults: { _controller: 'Gonzalo123\AppController::helloAction' }

api:
  prefix: /api
  resource: api.yml

blog:
  prefix: /blog
  resource: blog.yml

As we can see we have separated the main routing file into different files: api.yml (for the Api) and blog.yml (for the blog)

# config/api.yml

api.list:
  path:     /list
  defaults: { _controller: 'Gonzalo123\ApiController::listAction' }
# blog.yml

blog.home:
  path:     /
  defaults: { _controller: 'Gonzalo123\BlogController::homeAction' }

And now we can create our controllers:

<?php
// lib/Gonzalo123/AppController.php

namespace Gonzalo123;

use Symfony\Component\HttpFoundation\Response;
use Silex\Application;

class AppController
{
    public function homeAction()
    {
        return new Response("AppController::homeAction");
    }

    public function helloAction(Application $app, $name)
    {
        return new Response("Hello" . $app->escape($name));
    }
}
<?php
// lib/Gonzalo123/ApiController.php

namespace Gonzalo123;

use Symfony\Component\HttpFoundation\Response;

class ApiController
{
    public function listAction()
    {
        return new Response("AppController::listAction");
    }
}
<?php
// lib/Gonzalo123/BlogController.php

namespace Gonzalo123;

use Symfony\Component\HttpFoundation\Response;

class BlogController
{
    public function homeAction()
    {
        return new Response("BlogController::homeAction");
    }
}

And that’s all. Here also the needed dependencies within our composer.json file

{
    "require":{
        "silex/silex":"1.0.*@dev",
        "symfony/yaml":"v2.2.0",
        "symfony/config":"v2.2.0"
    },
    "autoload":{
        "psr-0":{
            "":"lib/"
        }
    }
}

source code at github.

About these ads

About Gonzalo Ayuso

Web Architect specialized in Open Source technologies. PHP, Python, JQuery, Dojo, PostgreSQL, CouchDB and node.js but always learning.

Posted on March 4, 2013, in php, silex, Symfony, Technology and tagged , , . Bookmark the permalink. 18 Comments.

  1. whether it enables the system to create a bundle using Silex

  2. i try to add weprofierProvider like this :
    // web profiler service
    $app->register($profiler = new \Silex\Provider\WebProfilerServiceProvider(), array(
    ‘profiler.cache_dir’ => __DIR__.’/../cache’,
    ));
    $app->mount(‘/_profiler’, $profiler);

    but this make an error:
    Twig_Error_Syntax: The function “path” does not exist in “@WebProfiler/Profiler/toolbar_js.html.twig” at line 15

    • I don’t understand your problem. It looks that it’s out of the scope of this post. To use the WebProfilerServiceProvider you need to follow the instructions that appear within the WebProfilerServiceProvider documentation. It works without problems.

  3. Good solution. Thanks.
    But how can i set and use custom vars (ex. layouts) for any routes/collections in yaml file?
    And what about middlewares?

  4. Good Job.

    I’m new in Silex. (Since Bilbostack speach of Eguiluz :) Old school PHP programmer, with very bad habits, trying to re-learn. And bad english :$

    One question. ¿how can you access $app and $request from homeAction() ? Don’t want to do with global, neither passing in all the methods… :$

    (no se si se me entiende… :D )

    • Gonzalo Ayuso

      be careful. If you use globals you will burn in hell :). It’spretty straightforward. You can use Request through Dependency injection and if you need $app you need to use use keyword:

      example:


      use Symfony\Component\HttpFoundation\Request;

      ...

      $app->get('/', function($Request $request) use ($app){
      ...
      });

      (y sí. Sí que se te entiende :) )

  5. Hi, good job!
    I have a question: If I want to use a before hook with this, its possible?
    Thanks

    • AFAIK you cannot use middlewares when using route collection. In the previous post we discus about it in the comments, but when we are using route collection we cannot define middlewares (before and after) in the yaml file (of course if we hack a little bit). I think the best solution is to use the event dispatcher.

  6. How to inject Silex\Application for every action in a Controller..?

    • You don’t need to inject it. RouteCollection does it. As you can see in the examples, you can use parameters in public functions and Silex call them with with the properly request parameter. But also you can inject the whole SilexApplication. You only need to define the type of the input parameter with the properly type (Silex\Application). This is called “Hollywood principle”

  1. Pingback: Новости » Blog Archive » Дайджест интересных новостей и материалов из мира PHP за последние две недели №12 (25.02.2013 — 11.03.2013)

  2. Pingback: Новости » Blog Archive » Дайджест интересных новостей и материалов из мира PHP за последние две недели №12 (25.02.2013 — 11.03.2013)

  3. Pingback: Working with AngularJS and Silex as Resource provider | Gonzalo Ayuso | Web Architect

  4. Pingback: Bundles in Silex using Stack | Gonzalo Ayuso | Web Architect

  5. Pingback: Дайджест интересных новостей и материалов из мира PHP за последние две недели №12 (25.02.2013 — 11.03.2013) - Juds

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 953 other followers

%d bloggers like this: