Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom route configuration with Silex

I know that the basis of Silex approach in which all the application logic in a single file. But my application will be possible to have more than twenty controllers. So I want to have a handy map to manage the router.

My question is to search for solutions in which I would be able to make a router to a separate file. In the best case, the file must be of YAML type:

# config/routing.yml

_home:
    pattern: /
    defaults: { _controller: MyProject\Controller\MyController::index }

But the native is also a good case (for me):

$routes = new RouteCollection();

$routes->add(
    'home',
    new Route('/', array('controller' => 'MyProject\Controller\MyController::index')
));

return $routes;

Problem of the second case is that I have to use the match() function for each rule of routing. It is not at all clear.

What are the ways to solve this issue? The condition is that I want to use the existing API Silex or components of Symfony2.

Small note:

I don't use a ControllerProviderInterface for my Controller classes. This is an independent classes.

like image 441
Yury Avatar asked Feb 03 '13 19:02

Yury


2 Answers

First of all, the basis of Silex is not that you put everything in one file. The basis of Silex is that you create your own 'framework', your own way of organizing applications.

"Use silex if you are comfortable with making all of your own architecture decisions and full stack Symfony2 if not." -- Dustin Whittle

Read more about this in this blogpost, created by the creator of Silex.


How to solve your problem

What you basically want is to parse a Yaml file and get the pattern and defaults._controller settings from each route that is parsed.

To parse a Yaml file, you can use the Yaml Component of Symfony2. You get an array back which you can use to add the route to Silex:

// parse the yaml file
$routes = ...;
$app = new Silex\Application();

foreach ($routes as $route) {
    $app->match($route['pattern'], $route['defaults']['_controller']);
}

// ...
$app->run();
like image 192
Wouter J Avatar answered Sep 21 '22 20:09

Wouter J


I thought I'd add my method here as, although others may work, there isn't really a simple solution. Adding FileLocator / YamlFileLoader adds a load of bulk that I don't want in my application just to read / parse a yaml file.

Composer

First, you're going to need to include the relevant files. The symfony YAML component, and a really simple and useful config service provider by someone who actively works on Silex.

"require": {
    "symfony/yaml": "~2.3",
    "igorw/config-service-provider": "1.2.*"
}

File

Let's say that your routes file looks like this (routes.yml):

config.routes:
  dashboard:
    pattern:  /
    defaults: { _controller: 'IndexController::indexAction' }
    method:   GET

Registration

Individually register each yaml file. The first key in the file is the name it will be available under your $app variable (handled by the pimple service locator).

$this->register(new ConfigServiceProvider(__DIR__."/../config/services.yml"));
$this->register(new ConfigServiceProvider(__DIR__."/../config/routes.yml"));
// any more yaml files you like

Routes

You can get these routes using the following:

$routes = $app['config.routes']; // See the first key in the yaml file for this name
foreach ($routes as $name => $route)
{
    $app->match($route['pattern'], $route['defaults']['_controller'])->bind($name)->method(isset($route['method'])?$route['method']:'GET');    
}

->bind() allows you to 'name' your urls to be used within twig, for example.
->method() allows you to specify POST | GET. You'll note that I defaulted it to 'GET' with a ternary there if the route doesn't specify a method.

like image 27
Jimbo Avatar answered Sep 19 '22 20:09

Jimbo