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.
Please complete these prerequisites.
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.
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;
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.
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
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.
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.
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:
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:
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:
If, however, you visit a non-existing ID, such as http://your_server_ip/2
in this example, it will show an error page:
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.
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
?>
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.
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!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Good job. As for me it is usually simpler to run cli command
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 :))