Scratching the Surface of Silex

In the web development world, we often default to “let’s just use what we’ve always used.” However, often these solutions aren’t simple - they’re just familiar. Enter Silex.

    Derek Fernholz
  • Sep. 05 2013
Silex Header

Sometimes there can be such a thing as overkill.

In the web development world, we often default to a simple approach: “let’s just use what we’ve always used” – the old case of when all you have is a hammer, everything looks like a nail.

However, often these solutions aren’t simple – they’re just familiar. Enter Silex – a very stripped down and truly simplistic framework for creating trivial to complex web applications.

What is Silex?

Silex is a PHP Micro-framework based on Symfony2 components that has been built to focus on smaller applications. Silex solves a lot of common problems without getting in your way, acting as a great base upon which you can architect the rest of your application. It takes advantage of Composer and Pimple for dependency management and gives us great routing capabilities, which is often missing from other PHP frameworks.

Why not Symfony?

Symfony is still an option, especially if you know that you’ll be creating a large scale application that will need to run in a production environment indefinitely and you are not comfortable with enterprise application architecture.

But if you are working toward a smaller app or web tool, Silex makes great sense. You’ll get up and running quickly, and if the need arises for more advanced architecture you can mix in some Symfony2 bundles and components to help you get there.

Installing Silex

There are plenty of step-by-step guides out there for installing Silex, and you can easily find one tailored to your exact environment, so we will simply outline the basic steps. We will be using Composer, a fantastic dependency manager for PHP – not for installation, but also to manage all other bundles, libraries, and anything else we use along the way.

                            
        
            
curl -s http://getcomposer.org/installer | php
        
    

First, create a composer.json file in the root of your project directory. This will be the set of instructions that Composer uses to keep your dependencies up to date and installed, wherever you decide to move the code base.

                            
        
            
{
"require": {
"silex/silex": "1.0.*"
},
"minimum-stability": "dev"
}
        
    

Then, run Composer.

                            
        
            
php composer.phar install
        
    

This will run through all of our instructions and setup the base Silex project structure for us. Think of it as scaffolding in other frameworks.

Looking Behind the Curtain

Now that we have finished the basic install, take a look at the file structure that we have generated. Specifically notice the one named ‘vendor’, which is where Composer stores the dependencies installed by your composer.json file. Basically, anything you did not write specifically for this application or that you are borrowing from somewhere else will live here.

Let’s create an index.php file in the root of our project. We will be using this as a bit of a playground for the remainder of this post. (You know, doing those “Hello World” type things that all programmers like to do.)

                            
        
            
<?php
 
/* include the silex autoload */
require_once __DIR__.'/vendor/autoload.php';
 
$app = new SilexApplication();
 
/* silex uses anonymous functions to define routes */
$app->get('/', function() use($app) {
 
    return 'Hello World!';
 
});
 
$app->run();
?>
        
    

One of the things that makes Silex shine is that little piece of code with the anonymous function that handles the routing. If you’ve ever written a standard web app with your own framework or even another “off the shelf” solution, you know that you either have to setup a proper file structure and application hierarchy from the start, or you will have problems later on. Then, to make it all work, you generally have to rely on standard structure browsing in your application or you can create some fancy Apache rewrite rules to help you.

With Silex, it takes just one simple line of code. (NOTE: If we were to modify that path to be ‘/hello’ instead of ‘/’ our app will display an error for the default path, in my case, silex.local. If we now navigate to /hello (silex.local/hello), you should again see the ‘Hello World!’ that we had before.)

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

Even though this may seem trivial, the power that it gives us for developing an application is quite impressive. 

Example One: Cleaner Parameterized URLs

For example, let’s say we want to take in a parameter from the user in the URL. Naturally, we’d love to make it look friendly, free of the typical errant characters you’d find in a normal GET string (?user=blah&setting=foobar). With one simple change, we can do just that.

                            
        
            
$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello '.$app->escape($name);
})
        
    

This allows us to pass any string we like into our ‘Hello World’ function and print it to the screen. Navigating to silex.local/hello/there will present us with ‘Hello there’ on the screen.

But what happens if we go to just /hello? Since we don’t have a default value for the name parameter, Silex will throw an error. Luckily for us, they provide a simple way to ensure this does not happen to us going forward.

Example Two: Rerouting to Prevent Errors

If there’s one universal truth in development, it’s that things change – including the basic strings we depend on to find our way to an app or site.

Silex provides an easy way to help reroute errors that arise from things like missing default values or other structural changes.

                            
        
            
$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello '.$app->escape($name);
})->value('name', 'there!');
        
    

Simply appending on -&gt;value('name', 'there!') defaults the name parameter to the string ‘there!’ and we can test it by going to silex.local/hello.

These two examples only scratch the surface of what’s called the Symfony Http Foundation: which gives us access to all the old familiar favorites like GET, POST, DELETE, etc.

Basic Authentication and Session Setup

For the simplest of web apps, sometimes all we need is basic authentication in front of some basic admin areas or functions. Silex just so happens to give us a Service Provider to access the Session and make this task semi-trivial.

                            
        
            
$app->register(new Silex\Provider\SessionServiceProvider());

        
    

There are two simple steps: register it, and use it.

                            
        
            
use Symfony\Component\HttpFoundation\Response;

$app->get('/login', function () use ($app) {
    $username = $app['request']->server->get('PHP_AUTH_USER', false);
    $password = $app['request']->server->get('PHP_AUTH_PW');

    if (‘Awesome Test User’ === $username && ‘supersecretpassword’ === $password) {
        $app['session']->set('user', array('username' => $username));
        return $app->redirect('/account');
    }

    $response = new Response();
    $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', 'site_login'));
    $response->setStatusCode(401, 'Please sign in.');
    return $response;
});

$app->get('/account', function () use ($app) {
    if (null === $user = $app['session']->get('user')) {
        return $app->redirect('/login');
    }

    return "Welcome {$user['username']}!";
});
        
    

If you visit /account now, you will be redirected to /login as you do not have a valid user in the Session.

Using the username and password that we set up in the above code sample on the login page, we will be authenticated and passed to the Account page. There we’ll see “Welcome Awesome Test User!” If we fail to enter the correct credentials, we will get an HTTP 401 and the message, “Please sign in.”

Note: this is basic HTTP Authentication and should not be used for anything needing to be truly secured. It can be used to keep an app that is being developed from being crawled by search engines or seen by the public.

Application Logging with Monolog

One of the other Service Providers we have access to is Monolog. It will log requests and errors and allow you to add logging to your application. This allows you to debug and monitor the behavior, even in production.

To enable it, we need to add the requirement to our composer.json file, register it, and then use it.

                            
        
            
{
    "require": {
        "silex/silex": "1.*",
                        "monolog/monolog": ">=1.0.0"
    }
}
        
    

Now we just need to run a “composer update” from the command line to bring in the Monolog bundle.

                            
        
            
$app->register(new Silex\Provider\MonologServiceProvider(), array(
    'monolog.logfile' => __DIR__.'/development.log',
));

        
    

Registering the Monolog Service also configures it with the path to a file that we will log to, in this case, ‘development.log’.

                            
        
            
if ('Awesome Test User' === $username && 'supersecurepassword' === $password) {
        $app['session']->set('user', array('username' => $username));
        $app['monolog']->addInfo(sprintf("User '%s' logged in.", $username));
        return $app->redirect('/account');
    }
        
    

Inside our login logic, I have added a line to log when the user is successfully logged in and which username was entered to do so.

That’s the basics, in place of info, we can log errors or debug messages. This should give you the basic tools to get going on your first app in Silex.

Where can we go from here?

The team at Sensio Labs has put together quite extensive documentation and usage examples over on their documentation site, I would suggest glancing over the usage section.

The logical next steps would be to determine what it is we want to do in our application. Assuming a typical application, we will need some sort of datastore or database, some ways to retrieve data, and some sort of security layer.

For database interaction, I would recommend setting up a MySQL Database and then read all about Doctrine to get access to that data. We can then use some of the built in response helper methods to return the data as HTML or JSON right out of the box. The latter could be quite useful if our application was to be an API providing data for some other service, like an iOS or Android application.

The basic security provided by Silex is great, if you use it. Notice above that we passed our input parameter through an ‘escape’ function? This was to sanitize that input. If we follow some basic guidelines for web development, have our server setup properly, and take heed of the advice on the Silex Security section there should be no problems pushing this site into the public domain.

Go Forth and Structure Simply

Silex is a framework that works well for any project, from the trivial to the complex. We’ve demonstrated a small part of Silex’s value with a few heavy lifting, simple service providers and a very small amount of custom code — from accessing URL parameters, to routing, to accessing the session’s data.

The next steps are up to you. Go over some of the examples in the Silex Cookbook. This will give you a firmer grasp on the information we talked about here, and give you a decent toolset for building a full fledged application.