Tutorial

How To Get Started with Silex on Ubuntu 14.04

Published on January 15, 2015
How To Get Started with Silex on Ubuntu 14.04

Introduction

Silex is a PHP micro-framework built on Symfony2 components. It can be used to build small websites and large applications alike. It is concise, extensible, and testable.

In this tutorial, we will begin by downloading and configuring Silex. Then you will learn how to make a basic Silex application.

We will be using Composer to install Silex, which is a popular PHP package manager. More information about Composer can be found in this tutorial. At the end of this tutorial, you will have a fully functional blog site.

Note: This tutorial was tested on Ubuntu, but should work equally well on other Linux distributions. The links refer to Ubuntu tutorials, but please feel free to find the appropriate guides for setting up your server and installing the LAMP stack and Git.

Prerequisites

Please complete these prerequisites.

Step 1 — Installing Silex

In this section, we will install Silex using Composer. To begin with, change your working directory to the Apache document root, /var/www/html:

cd /var/www/html

Next, delete the default contents of this folder:

sudo rm /var/www/html/index.html

Then, move to the /var/www directory so as not to expose all of your files to the public:

cd /var/www

Then, download Composer:

sudo curl -sS https://getcomposer.org/installer | sudo php

Next, we will create and edit the Composer file composer.json:

sudo nano composer.json

In this file, add the following contents:

{
    "require": {
        "silex/silex": "~1.2"
    }
}

We have now told Composer to download Silex version 1.2 as a dependency. To start the download, execute the following command:

sudo php composer.phar update

Now, Composer will download Silex and its dependencies; this might take a few seconds.

Step 2 — Bootstrapping Silex

In this section, we will bootstrap Silex by including the required files and creating the application. To start, edit the file /var/www/html/index.php:

sudo nano /var/www/html/index.php

In this file, add the following basic contents:

<?php
require_once __DIR__.'/../vendor/autoload.php'; // Add the autoloading mechanism of Composer

$app = new Silex\Application(); // Create the Silex application, in which all configuration is going to go

// Section A
// We will later add the configuration, etc. here


// This should be the last line
$app->run(); // Start the application, i.e. handle the request
?>

Throughout this tutorial, we’ll be adding more configuration information and other data to this file. All of the new lines that we add will go in Section A, between the $app = new Silex\Application(); and $app->run(); lines.

In the same file, /var/www/html/index.php turn on debugging, which is useful when developing your application. Add this line in Section A:

$app['debug'] = true;

Step 3 - Creating a Blog Application

In this section, we will create a sample blog application. If you want to focus on your own application instead, please take a look at the Silex documentation.

We will create an example blog application. It will not make use of a database, but it can be converted relatively easily by taking a look at the DoctrineServiceProvider documentation.

Adding the Twig Template Engine

First, start by adding another dependency: Twig. Twig is a template engine also used by the Symfony framework. It will serve the templates of our application. To add it, edit composer.json:

sudo nano /var/www/composer.json

Then, add the new dependency line for twig, shown in red below. Don’t forget the comma on the previous line:

{
    "require": {
        "silex/silex": "~1.2",
        "twig/twig": ">=1.8,<2.0-dev"
    }
}

Next, update the Composer dependencies:

sudo php composer.phar update

Enabling mod_rewrite

Now, you will need to configure the web server, which is Apache in this case.

First, make sure you have enabled mod_rewrite and that you have permitted changes in the .htaccess file. The process is described in this tutorial, but remember that Ubuntu 14.04’s default virtual host is in /var/www/html rather than /var/www.

After you’ve enabled the module (as explained in the linked tutorial), add the following lines to your /etc/apache2/sites-available/000-default.conf file:

sudo vim /etc/apache2/sites-available/000-default.conf
<Directory /var/www/html/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
</Directory>

Then, create and edit the .htaccess file:

sudo nano /var/www/html/.htaccess

In this file, add the following contents:

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]
</IfModule>

This will make sure that any request for a file which does not exist points to our application, which allows the application to do the routing.

Creating Blog Content

To add some articles, we will create an array containing the title, contents, author and date of publication. We can store this in our application object by means of the container object that it extends. A container object is able to hold multiple objects, which can be reused by all other objects in the application. To do this, add the following in Section A in /var/www/html/index.php

sudo nano /var/www/html/index.php

Add the following contents:

$app['articles'] = array(
    array(
        'title'    => 'Lorem ipsum dolor sit amet',
        'contents' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean mollis vestibulum ultricies. Sed sit amet sagittis nisl. Nulla leo metus, efficitur non risus ut, tempus convallis sem. Mauris pharetra sagittis ligula pharetra accumsan. Cras auctor porta enim, a eleifend enim volutpat vel. Nam volutpat maximus luctus. Phasellus interdum elementum nulla, nec mollis justo imperdiet ac. Duis arcu dolor, ultrices eu libero a, luctus sollicitudin diam. Phasellus finibus dictum turpis, nec tincidunt lacus ullamcorper et. Praesent laoreet odio lacus, nec lobortis est ultrices in. Etiam facilisis elementum lorem ut blandit. Nunc faucibus rutrum nulla quis convallis. Fusce molestie odio eu mauris molestie, a tempus lorem volutpat. Sed eu lacus eu velit tincidunt sodales nec et felis. Nullam velit ex, pharetra non lorem in, fringilla tristique dolor. Mauris vel erat nibh.',
        'author'   => 'Sammy',
        'date'     => '2014-12-18',
    ),
    array(
        'title'    => 'Duis ornare',
        'contents' => 'Duis ornare, odio sit amet euismod vulputate, purus dui fringilla neque, quis eleifend purus felis ut odio. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque bibendum pretium ante, eu aliquet dolor feugiat et. Pellentesque laoreet est lectus, vitae vulputate libero sollicitudin consequat. Vivamus finibus interdum egestas. Nam sagittis vulputate lacus, non condimentum sapien lobortis a. Sed ligula ante, ultrices ut ullamcorper nec, facilisis ac mi. Nam in vehicula justo. In hac habitasse platea dictumst. Duis accumsan pellentesque turpis, nec eleifend ex suscipit commodo.',
        'author'   => 'Sammy',
        'date'     => '2014-11-08',
    ),
);

These articles can be reused everywhere in our application now, and you can even add more yourself. For real-world websites, it would probably be a better idea to use a database.

Routing

Basically, routing maps a URL like http://www.example.com/ to / and executes the function associated with it. To add a basic route, add the following in Section A of /var/www/html/index.php:

sudo nano /var/www/html/index.php

Contents:

$app->get('/', function (Silex\Application $app)  { // Match the root route (/) and supply the application as argument
    $output = '';
    foreach ($app['articles'] as $article) { // Create a basic list of article titles
        $output .= $article['title'];
        $output .= '<br />';
    }

    return $output; // Return it to so it gets displayed by the browser
});

Now, when you visit http://your_server_ip, it should display a list of article titles:

The browser view of the page created above, showing the two article titles

Templates

Even though our website now displays the correct output, it doesn’t look very nice. To fix this, we will make use of Twig.

First, Silex requires us to register Twig as a service provider, which is basically a way to reuse certain parts of an application in another application. To register Twig, add this in section A:

sudo nano /var/www/html/index.php

Contents:

$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__.'/../templates', // The path to the templates, which is in our case points to /var/www/templates
));

We can now make use of the Twig template engine. To do this, edit the $app->get('/', function (Silex\Application $app) { }); block, which defines the route of /, to match what’s shown here. New lines are shown in red:

$app->get('/', function (Silex\Application $app)  { // Match the root route (/) and supply the application as argument
    return $app['twig']->render( // Render the page index.html.twig
        'index.html.twig',
        array(
            'articles' => $app['articles'], // Supply arguments to be used in the template
        )
    );
});

Save your changes and close the file.

Now let’s create the index.html.twig template. Create the directory and then create and open the file base.html.twig:

sudo mkdir /var/www/templates
sudo nano /var/www/templates/base.html.twig

This file will be our base template, which means all other templates will inherit from it, so we don’t have to add the basics in every template. In this file, add the following contents:

<!doctype html>
<html>
<head>
    <title>{% block title %}Blog{% endblock %}</title>
</head>
<body>
{% block body %}

{% endblock body %}
</body>
</html>

This file contains two blocks. Blocks can be overridden in subtemplates to provide content. The block called title will be used to provide a title for the single article page. The block body will be used to display all contents.

Save your changes.

Now we’ll create and edit the file /var/www/templates/index.html.twig:

sudo nano /var/www/templates/index.html.twig

Add the following contents:

{% extends 'base.html.twig' %}
{% block body %}
    <h1>
        Blog index
    </h1>

    {% for article in articles %}
        <article>
            <h1>{{ article.title }}</h1>
            <p>{{ article.contents }}</p>
            <p><small>On {{ article.date }} by {{ article.author }}</small></p>
        </article>
    {% endfor %}
{% endblock %}

First, we specify that we want to extend the template base.html.twig. After that, we can begin overriding blocks defined in the parent template. In this template, we only override the block body, where we create a loop which displays all articles.

Now visit http://your_server_ip; it should show an index of all your posts:

Browser view of the new index page, listing all posts

Another Controller for a Single Post

Next, we will add another controller which displays a single post. The posts will be matched by their array index. Open /var/www/html/index.php again:

sudo nano /var/www/html/index.php

Add this to Section A, which will allow us to display pages for individual articles:

$app->get('/{id}', function (Silex\Application $app, $id)  { // Add a parameter for an ID in the route, and it will be supplied as argument in the function
    if (!array_key_exists($id, $app['articles'])) {
        $app->abort(404, 'The article could not be found');
    }
    $article = $app['articles'][$id];
    return $app['twig']->render(
        'single.html.twig',
        array(
            'article' => $article,
        )
    );
})
    ->assert('id', '\d+') // specify that the ID should be an integer
    ->bind('single'); // name the route so it can be referred to later in the section 'Generating routes'

Save your changes. Then, create and edit the file /var/www/templates/single.html.twig:

sudo nano /var/www/templates/single.html.twig

Add the following contents:

{% extends 'base.html.twig' %}
{% block title %}{{ article.title }}{% endblock %}
{% block body %}
    <h1>
        {{ article.title }}
    </h1>
    <p>{{ article.contents }}</p>
    <p><small>On {{ article.date }} by {{ article.author }}</small></p>
{% endblock %}

In this template, we also make use of the title block to display the article title. The body block looks almost identical to the former body block, so it should be pretty self-explanatory.

If you now visit http://your_server_ip/0 or http://your_server_ip/1, it should show an article:

The browser view of a single article

If, however, you visit a non-existing ID, such as http://your_server_ip/2 in this example, it will show an error page:

The browser view of a non-existing article error, HttpException

Generating Routes

Next, we will add links from the home page to the single article view, and back from the articles to the home page. Silex has the ability to generate routes using a Symfony component. It is provided as a service provider, so you should add that first to Section A. Open /var/www/html/index.php:

sudo nano /var/www/html/index.php

Add the following to Section A:

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

This will allow us to make use of the URL generator service. When we created the single view controller, we already added a named route. It was done using the following line:

->bind('single'); // name the route so it can be referred to later in the section 'Generating routes'

Now, we will also need to bind a route to the home page. To do that, add the ->bind('index') route at the end of this block, just before the final semicolon. Changes are marked in red:

$app->get('/', function (Silex\Application $app)  { // Match the root route (/) and supply the application as argument
    return $app['twig']->render(
        'index.html.twig',
        array(
            'articles' => $app['articles'],
        )
    );
})->bind('index');

Next, we will need to actually generate the URLs. Open /var/www/templates/index.html.twig:

sudo nano /var/www/templates/index.html.twig

Then, change the following <h1> line, as shown below:

{% extends 'base.html.twig' %}
{% block body %}
    <h1>
        Blog index
    </h1>

    {% for article in articles %}
        <article>
            <h1><a href="{{ app.url_generator.generate('single', { id: loop.index0 }) }}">{{ article.title }}</a></h1>
            <p>{{ article.contents }}</p>
            <p><small>On {{ article.date }} by {{ article.author }}</small></p>
        </article>
    {% endfor %}
{% endblock %}

This creates a link from the title of the article to the individual article page. The app.url_generator refers to the service that we have registered. The generate function takes two parameters: the route name, single in this case, and parameters for the route, which is just the ID in this case. loop.index0 refers to a 0-indexed index in the loop. Thus, when the first item is looped, it is a 0; when the second item is looped, it is a 1, etc.

The same can be done to refer back to the index page in the single page template:

sudo nano /var/www/templates/single.html.twig

Add the following <p> line to create the link:

{% extends 'base.html.twig' %}
{% block title %}{{ article.title }}{% endblock %}
{% block body %}
    <h1>
        {{ article.title }}
    </h1>
    <p>{{ article.contents }}</p>
    <p><small>On {{ article.date }} by {{ article.author }}</small></p>

    <p><a href="{{ app.url_generator.generate('index') }}">Back to homepage</a></p>
{% endblock %}

This should be pretty self-explanatory.

That’s it! Feel free to visit the website again at http://your_server_ip/. You should be able to click an article title to visit that article’s page, and then use the link at the bottom of the article to return to the home page.

Complete index.php File

For your reference, here’s what the final /var/www/html/index.php file should look like.

<?php
require_once __DIR__.'/../vendor/autoload.php'; // Add the autoloading mechanism of Composer

$app = new Silex\Application(); // Create the Silex application, in which all configuration is going to go



// Section A
// We will later add the configuration, etc. here

$app['debug'] = true;
$app['articles'] = array(
    array(
        'title'    => 'Lorem ipsum dolor sit amet',
        'contents' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean mollis vestibulum ultricies. Sed sit amet sagittis nisl. Nulla leo metus, efficitur non risus ut, tempus convallis sem. Mauris pharetra sagittis ligula pharetra accumsan. Cras auctor porta enim, a eleifend enim volutpat vel. Nam volutpat maximus luctus. Phasellus interdum elementum nulla, nec mollis justo imperdiet ac. Duis arcu dolor, ultrices eu libero a, luctus sollicitudin diam. Phasellus finibus dictum turpis, nec tincidunt lacus ullamcorper et. Praesent laoreet odio lacus, nec lobortis est ultrices in. Etiam facilisis elementum lorem ut blandit. Nunc faucibus rutrum nulla quis convallis. Fusce molestie odio eu mauris molestie, a tempus lorem volutpat. Sed eu lacus eu velit tincidunt sodales nec et felis. Nullam velit ex, pharetra non lorem in, fringilla tristique dolor. Mauris vel erat nibh.',
        'author'   => 'Sammy',
        'date'     => '2014-12-18',
    ),
    array(
        'title'    => 'Duis ornare',
        'contents' => 'Duis ornare, odio sit amet euismod vulputate, purus dui fringilla neque, quis eleifend purus felis ut odio. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque bibendum pretium ante, eu aliquet dolor feugiat et. Pellentesque laoreet est lectus, vitae vulputate libero sollicitudin consequat. Vivamus finibus interdum egestas. Nam sagittis vulputate lacus, non condimentum sapien lobortis a. Sed ligula ante, ultrices ut ullamcorper nec, facilisis ac mi. Nam in vehicula justo. In hac habitasse platea dictumst. Duis accumsan pellentesque turpis, nec eleifend ex suscipit commodo.',
        'author'   => 'Sammy',
        'date'     => '2014-11-08',
    ),
);

$app->get('/', function (Silex\Application $app)  { // Match the root route (/) and supply the application as argument
    return $app['twig']->render( // Render the page index.html.twig
        'index.html.twig',
        array(
            'articles' => $app['articles'], // Supply arguments to be used in the template
        )
    );
})->bind('index');

$app->register(new Silex\Provider\TwigServiceProvider(), array(
    'twig.path' => __DIR__.'/../templates', // The path to the templates, which is in our case points to /var/www/templates
));

$app->get('/{id}', function (Silex\Application $app, $id)  { // Add a parameter for an ID in the route, and it will be supplied as argument in the function
    if (!array_key_exists($id, $app['articles'])) {
        $app->abort(404, 'The article could not be found');
    }
    $article = $app['articles'][$id];
    return $app['twig']->render(
        'single.html.twig',
        array(
            'article' => $article,
        )
    );
})
    ->assert('id', '\d+') // specify that the ID should be an integer
    ->bind('single'); // name the route so it can be referred to later in the section 'Generating routes'

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




// This should be the last line
$app->run(); // Start the application, i.e. handle the request
?>

Conclusion

You have created a simple blog application using Silex. It can be expanded a lot further, starting with coupling it with a database. That is out of the scope of this tutorial, though. The official documentation can be very helpful and is definitely a must-read if you want to continue using Silex.

If Silex is too micro for you, you should definitely consider using the Symfony framework, for which a tutorial can be found here.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
4 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Good job. As for me it is usually simpler to run cli command

$ composer.phar require <package>

instead of editing composer.json. Also it checks if you give wrong version.

Very good! My thanks to you.

Good job.

hahaha the template it looks like template in Django :))

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel