Why you should use Silex for you next project

Almost a year ago now I worked on a contract where I was required to convert legacy PHP code, which had been written by a non-programmer. For the refactoring I first redesigned the database entirely, refactored any of the business logic out of any files which rendered content, and organised the entire structure. I created a simple router which was used to map simple urls to views which where rendered using an output buffer. I then set about finding an MVC framework to incrementally integrate with the refactored app.

After a few days of research, I chose Silex. Silex is very minimal and unopinionated. It also has very good documentation, including how to add Twig, the Doctrine DBAL (the ORM takes a bit of work) and many of the Symfony packages (Monolog, Swiftmailer, Session, Serializer, Assets and more). The best part was I could use Silex on it's own initially while moving my existing code to routes and controllers, and only then add a template engine and DB library. It also allows you to decide the structure yourself. As the project evolved I was able to rework anything that required it and add any library that could be PSR autoloaded easily.

Doctrine

Using Doctrine DBAL allowed me to use the current SQL queries easily and instantly see a huge performance benefit from the Doctrine Cache. The DBAL (Database Abstraction Layer) is a wrapper around PDO with a few additional features. Therefore plain SQL can be used very easily and the PDO methods will work. The main benefit I noticed was the speed improvements. The client noticed a huge improvement in speed almost immediately after implementing the DBAL in place of raw PDO.

The downside of Doctrine (especially when you start learning the ORM) is the poorly organised documentation. It's also hard to find resources on the more advanced features of the the DBAL and ORM elsewhere.

Twig

After implementing the DBAL I setup Twig and began moving everything over from raw PHP files into Twig views. I was able to do this without any downtime, however it took quite a bit of time, since the application had a full dashboard as well as the main front facing area of the website. The dashboard had 50+ pages while the front-end had 20+ pages.

Twig offers many benefits. It's by far my preferred template engine followed by Blade from Laravel. The syntax is quite easy to pick up, especially seeing as I was coming from knowing Blade mostlye. Blade has many of the same features as Twig (having been inspired by it) such as variable interpolation, block/sections, layouts, filters and Twig is very easy to extend. You can add your own filters and functions which can be used in Twig very easily. The documetation for Twig is also very good.

Once the Views layer and Model layer where in order I began working on moving everything into Controllers and out of the routes. Up to now each route was using callbacks to render the views and inject parameters to said views.

For this I began working with Service Controllers which required learning a bit more about Silex's Dependency Injection library "Pimple" (Why name it this? Why?).

Double-edged sword of Silex: Pimple

Pimple is actually a very easy Dependency Injection Container to pick up. It stores Services in an array of Closures which return the service:

class Dog
{
public function bark()
{
return 'Oh...how original -_-';
}
}
$container
= new Pimple\Container\Container();
$container['dog'] = function ($c) {
return new Dog;
}

echo $container['dog']->bark(); //
Oh...how original -_-

It's downside is that everything is in arrays, so you won't get IDE autocompletion when accessing methods. This was a pain for me because autocompletion is a huge time saver when learning a new class/library. For me this is perhaps the biggest downside to using Silex and/or Pimple.

Silex is essentially a wrapper around Pimple. Silex extends Pimple and uses \ArrayAccess to allow for items to be stored directly in keys on the class, as if it were an array:

$app = new Silex\App;

$app['debug'] = true;

$request = $app['request]; // Request object

$app->get('/', function () use ($request) {
// Do stuff with request here...

// Display content
return $request->getBody();
});

$app->run();

It's kind of cool. Your $app variable becomes the go to guy for almost everything in Silex from routing, config values and to registering and calling services, however storing services in arrays has the downsides I mentioned.

Middleware

If Pimple is the biggest downside to Silex, the way it handles middleware is certainly it's biggest upside. It's far more elegant than ANY other middleware I've used. If the middleware in Laravel or Zend confuses you then the middleware API in Silex will be a treat.

Essentially, you register your middleware as a simple callback, stored in a variable for reuse:

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

$firewall = function (Request $request, Application $app) {
$session = $app['session']->all();

if (!isset($session['logged_in'])) {
return new RedirectResponse($app['url_generator']->generate('login'));
} else {
return null;
}
};

Now we can simply apply this firewall (which ensures a user is logged in or else redirects them to the login page) to any routes which require the user to be logged in:

$app->get('/admin', function () use ($app) {
    return $app['twig']->render('admin/dashboard.twig');
})->before($firewall);

You can learn more about middleware in Silex in the middleware documentation.

Conclusion

Overall Silex is the most flexible framework I've used and it's the easiest to learn. If you've never used MVC it's a great framework to learn the concepts with, because it will force you to get you hands dirty and learn how MVC actually works. It's very easy to use a framework like Laravel, CakePHP or Symfony and never really need to understand how te framework actually fits together or works. Personally, I like to know how things work.

You can use Silex to build everything from APIs and small web services to full web applications. It also has some downsides, however I do feel those are largely outweighed by the strong points of Silex.