First chords in Symfony

By Ivo Lukač -

It has been a long time since I started to learn some new development tool from scratch. For years we are using eZ Publish CMS for our web projects. Of course, we also use other technologies from the stack (PHP, MySQL, Solr, CSS, Javascript, etc.) but the main platform is eZ. With new eZ Publish version 5 we got one new tool in the stack: Symfony PHP framework.

This is first post and probably not the last one in how we are learning the new platform :)

There are probably lot of posts about beginning in Symfony out there, but we still want to share the topic from our angle. We are coming from eZ world so there will be some comparisons with eZ concepts. On the other hand, the topic is not specifically related to eZ 5 but how to do stuff in pure Symfony. Maybe we will connect the dots later on.

General Symfony knowledge is important for us because from time to time we need to do some special kind of web where eZ is not the adequate tool. So learning Symfony makes sense for 2 reasons: to know a tool for more specific projects and to prepare ourselves better for eZ 5 future. If you want to learn on why new eZ Publish version 5 is based on Symfony check here and here. To take a 5 minute look about Symfony check here.

Installation and some key concepts

Well, what we always do at the beginning is installation. Installing Symfony is pretty straightforward and well explained, so we will cover it quickly:

1. Download it here.

If you downloaded the light installation (without vendors) you will have to use the composer:
a) download the composer to web root:

curl -s | php

b) do the installation:

php composer.phar install

2. check the configuration and resolve all blocking things with:

php app/check.php

3. make some simple configuration by calling config.php via URL (optional): http://symfony-test/config.php

This basically sets up some configuration parameters which can be set directly in config file anyway so the step is optional.
Btw, point the web root to [symfony folder]/web/ folder.

In case you have the installation on your localhost there should not be any problems. But my installation was on virtual machine so I accessed the URL over network. To make it work you need to comment out few lines in web/config.php and web/app_dev.php:

// header('HTTP/1.0 403 Forbidden');
// exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');

Installation over :) 

Some main concepts follow.

Directory structure

There are 4 main folders in Symfony installation:
- app where the application lives - the kernel, configuration, caches, logs, and global resources.
- src where the source bundles live (bundle is a set of various files that make one feature or a project), after the installation this is almost empty, there is just an example bundle AcmeDemoBundle
- vendor (where all included features live, with symfony itself) e.g. twig templating engine, swift mailer, etc. As a side note ezpublish ver 5 will be placed here
- web (web root folder with all public files)


So as we explained a bit earlier, bundles are set of files “bundled” together for some good reason. Either it is some specific feature (like Doctrine) or it is some project. If you are coming from eZ world bundles are like extension, pure and simple.  A good way to learn a bit more about the bundles is to remove a bundle. We have that AcmeDemoBundle installed so lets remove that one:
- remove the bundle files src/Acme
- remove the bundle public files or symlinks in web/bundles/acmedemo
- comment it out or remove it in the kernel (kernel directly loads all bundle classes ) app/AppKernel.php

// $bundles[] = new Acme\DemoBundle\AcmeDemoBundle();

- remove the URL routing from (more about routing in some later post, lets just say it is a configuration to map URLs to features)

Preparing a new bundle

The simplest way to create a new bundle is to run the script:

php app/console generate:bundle

This will create appropriate file in src, e.g. NetgenTestBundle. The naming is usually preffered to be: VendorProject
If confirmed while running the script, bundle should be registered in the kernel. Or it can be done by hand in app/AppKernel.php, add the following bundle in the AppKernel::registerBundles() method:

new Netgen\Bundle\TestBundle\NetgenTestBundle(),

Model, View, Controller

One of the most important part of Symfony is its MVC implementation. That is one for the reason why eZ choose it as a platform. In general model could be any kind of content stored in structured way, like data in the database. Symfony comes with Doctrine mapper to ease the access to that kind of model Specifically in new eZ the model is the eZ content model accessed via new Public API.

The view part is implemented with Twig template engine. A simple template is generated with test bundle in src/Netgen/Bundle/TestBundle/Resources/views/Default/index.html.twig:

Hello {{ name }}!

It just shows the variable “name”.

A simple default controller is also generated in src\Netgen\Bundle\TestBundle\Controller\DefaultController.php

namespace Netgen\Bundle\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
  public function indexAction($name)
    return $this->render('NetgenTestBundle:Default:index.html.twig', array('name' => $name));

The code just extends the base controller and implements the indexAction() which just rendered the twig template with the “name” parameter. In this simple case there is no model, in some real scenarios you would access the model in the controller and prepare the data for the view.

Note: in legacy eZ (version 4 and before) the border between view and the controller was not clear. Yes, the template engine was implementation of the view part, and yes you could create a custom module to implement the controller part but a common practice was to write a lot of logic  in the template code. You could do a lot of staff without needing to make a custom module (hint: fetch template functions). In eZ 5 the separation is more clear (which is of course better for producing quality code) due to Symfony forcing a cleaner approach. But I would not be surprised if community starts making some template functions like fetch.

The route

To conclude this test application we need to connect an URL to the controller action. This has been already generated by the script in:
src/Netgen/Bundle/TestBundle/Resources/config/routing.yml by:

    pattern: /hello/{name}
    defaults: { _controller: NetgenTestBundle:Default:index }

The route (“netgen_test_homepage”) is defined with an URL pattern and what action to execute (“NetgenTestBundle:Default:index”). Note that Action suffix will be added automatically to resolve the indexAction() method from our controller.

To test this url type someting like: http://symfony-test/app_dev.php/hello . The result would be an exception:

Controller "Netgen\Bundle\TestBundle\Controller\DefaultController::indexAction()" requires that you provide a value for the "$name" argument (because there is no default value or because there is a non optional argument after this one).

Very nice example of more strict behavior: route expects a  “name” parameter so it raises an exception

So typing in the same URL with the additional parameter: http://symfony-test/app_dev.php/hello/Ivo. We get:

Hello Ivo!

Hope you liked our first chords in Symfony :)


This site uses cookies. Some of these cookies are essential, while others help us improve your experience by providing insights into how the site is being used. For more detailed information on the cookies we use, please check our Privacy Policy.