Unboxing: Silex

Overview
In the first of our new blog series Box UK Developer Gavin Davies explores the Silex Micro-Framework for PHP 5.3 and Twig template engine.
Author
Gavin Davies
Date
20 May 2011

About Unboxing

Unboxing is our regular feature where someone at Box UK spends a few hours playing with a new framework, library, tool or technique and blogs about his or her experience.

Silex

@CraigMarvelley and @HandyBitesize were talking about Silex on Twitter the other night, so I thought I’d take a look.

What is it?

“Silex is a PHP micro-framework for PHP 5.3. It is built on the shoulders of Symfony2 and Pimple and also inspired by sinatra.” - description from the Silex website. It allows you to pick and choose what components of Symfony2 you want to use. This is in keeping with what seems to be a current theme of Component-based development in the PHP community, evidenced in Stuart Herbert’s recent PHPUK talk on “Beyond Frameworks”. Like Ruby’s Sinatra, it provides a way to get web apps up and running with minimal effort and very little boilerplate code. It comes from Fabien Potencier, who created Symfony, and Igor Wiedler and is MIT licensed. Silex provides an easy way to take bits of Symfony that are useful and make simple apps, often expressed in single files.

Getting to grips

I thought the best way to test it out would be to build a simple application in it and use just the features I needed - so I’ve by no means tested everything, but I have used Silex in the way it’s intended - pick and choose what you need, ignore the rest!

The installation was extremely simple, just downloading and referencing the .phar archive - it could not possibly be easier! My first try at following the tutorial, however, threw an error:

Silex version ede0f9d 2011-05-05 16:24:12 +0200 Fatal error: Uncaught exception

'SymfonyComponentRoutingMatcherExceptionNotFoundException
inphar:///home

/gavin/silex/silex.phar/vendor/Symfony/Component/Routing/Matcher
/UrlMatcher.php:33

I mentioned this on Twitter, and within minutes one of the maintainers, @igorwesome, messaged me and I realised that this was because I hadn’t selected a route in my request - doh!

Once I’d grasped this, the routing was very easy to use so I built a small, single file sample app, starting with, of course, “hello world”:

<?php

require_once __DIR__.'/silex.phar';

$app = new SilexApplication();

$app->get('/', function() use ($app) {

    return “hello world!”;

});

From there, I decided to make an app called “up4it” where you put in an activity, then select from a list of people to invite. This app is of no earthly use, it’s a trivial app just for exploring the micro-framework.

As Silex provides built in support for Twig, I decided to give this a go too and found it to be an excellent templating language - in my brief encounter with it, everything worked exactly as I would expect it to, and I didn’t feel frustrated by it at any point. I installed it through PEAR and referenced the path in my project, and then built a base template:

base.twig

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset=utf-8 />

    <title>Up4It</title>

    <link rel="stylesheet" href="http://www.boxuk.com/css/style.css" type="text/css" />

</head>

<body>

<section id="wrapper">

    <header>

      <h1>Up4It</h1>

      <h2>Well, are you?</h2>

    </header>

    <content>

        {% block content %}

        {% endblock %}

    </content>

</section>

 

<section id="footer">

    <a href="/">Back to start</a>

</section>

</body>

</html>

I then simply built one template per route:

index.twig

{% extends "base.twig" %}

 

{% block content %}

    <h3>What would you like to do?</h3>

    <form action="/makeItHappen" method="POST">

        <input type="text" name="activity" />

        <input type="submit" value="Make it happen!" />

    </form>

{% endblock %}

Twig is simple and unobtrusive. You can just pass in parameters, and access them from the template:

Route for “inviteDudes”

...

$app->post('/inviteDudes', function () use ($app, $theDudes) {

    $request = $app['request'];

    $dudeIds = array_unique($request->get('dudes'));

    $selectedDudes = array_intersect_key($theDudes, $dudeIds);

    return $app['twig']->render('inviteDudes.twig', array(

        'selectedDudes' => $selectedDudes,

        'activity' => $_SESSION['activity']

    ));

});

Associated template for “inviteDudes”

{% extends "base.twig" %}

 

{% block content %}

    <h3>We have invited the following dudes to {{ activity }}!</h3>

    <ul>

        {% for dude in selectedDudes %}

            <li>

                {{ dude.name }}

            </li>

        {% endfor %}

    </ul>

{% endblock %}

Within an hour, I had my silly little app working and I knew my way around both Silex and Twig enough to use them - that felt very quick for unfamiliar tools!

Going deeper

One concern I always have with software is “is it easy to update?” After all, we need the latest security and performance fixes. Thankfully, updating Silex is very simple thanks to the built-in console.

This is a fantastic little framework for getting apps up and running incredibly quickly and I’d strongly recommend it for personal projects. Of course, I would have to formally load test it before I could recommend it for commercial projects, but from what I’ve seen I would be surprised if it wasn’t up to the job. I’ll certainly be using more of it in the weeks to come!

Want to see more of Silex?

These guys at Liip have used Silex in anger for an application and blogged about their experience.

Do you have any suggestions for future Unboxing features? Heard of something interesting that you’d like to know a bit more about? Please leave your ideas in the comment box below.

Banner image courtesy of Grey World (Flickr)

Comments

Add a comment

  • Me

    7 Jun 2011 22:26
    Where is the "dudes" data?
  • Gavin Davies

    16 Jun 2011 09:58 Box UK Staff
    the dudes data is just a test array, I didn't think the test app worth releasing. It was something like:

    // hard coded list of dudes
    $theDudes = array(
    array('name' => 'Mark'),
    array('name' => 'Steve'),
    array('name' => 'Dave'),
    array('name' => 'Jim'),
    );

Add your comment

This will not be shown
If provided, we'll link to this from your name