Let’s dive in to the initial directory structure within the typical Symfony application. Here it is:

  • app
  • bin
  • src
  • vendor
  • web

While Symfony2 is very flexible in terms of directory structure, it is recommended to keep the basic structure mentioned earlier.

The following table describes their purpose:

Directory Used for
app This holds information about general configuration, routing, security configuration, database parameters, and many others. It is also the recommended place for putting new view files. This directory is a starting point.
bin It holds some helper executables. It is not really important during the development process, and rarely modified.
src This directory holds the project PHP code (usually your bundles).
vendor These are third-party libraries used within the project. Usually, this directory contains all the open source third-party bundles, libraries, and other resources. It’s worth to mention that it’s recommended to keep the files within this directory outside the versioning system. It means that you should not modify them under any circumstances. Fortunately, there are ways to modify the code, if it suits your needs more. This will be demonstrated when we implement user management within our to-do application.
web This is the directory that is accessible through the web server. It holds the main entry point to the application (usually the app.php and app_dev.php files), CSS files, JavaScript files, and all the files that need to be available through the web server (user uploadable files).

So, in most cases, you will be usually modifying and creating the PHP files within the src/ directory, the view and configuration files within the app/ directory, and the JS/CSS files within the web/ directory.

The main directory also holds a few files as follows:

  • .gitignore
  • README.md
  • composer.json
  • composer.lock

The .gitignore file’s purpose is to provide some preconfigured settings for the Git repository, while the composer.json and composer.lock files are the files used by the composer dependency manager.

What is a bundle?

Within the Symfony2 application, you will be using the “bundle” term quite often. Bundle is something similar to plugins. So it can literally hold any code controllers, views, models, and services. A bundle can integrate other non-Symfony2 libraries and hold some JavaScript/CSS code as well. We can say that almost everything is a bundle in Symfony2; even some of the core framework features together form a bundle. A bundle usually implements a single feature or functionality. The code you are writing when you write a Symfony2 application is also a bundle.

There are two types of bundles. The first kind of bundle is the one you write within the application, which is project-specific and not reusable. For this purpose, there is a special bundle called AppBundle created for you when you install the Symfony2 project.

Also, there are reusable bundles that are shared across the various projects either written by you, your team, or provided by a third-party vendors. Your own bundles are usually stored within the src/ directory, while the third-party bundles sit within the vendor/ directory.

The vendor directory is used to store third-party libraries and is managed by the composer. As such, it should never be modified by you.

There are many reusable open source bundles, which help you to implement various features within the application. You can find many of them to help you with User Management, writing RESTful APIs, making better documentation, connecting to Facebook and AWS, and even generating a whole admin panel. There are tons of bundles, and everyday brings new ones.


If you want to explore open source bundles, and want to look around what’s available, I recommend you to start with the http://knpbundles.com/ website.

The bundle name is correlated with the PHP namespace. As such, it needs to follow some technical rules, and it needs to end with the Bundle suffix. A few examples of correct names are AppBundle and AcmeDemoBundle, CompanyBlogBundle or CompanySocialForumBundle, and so on.


Symfony2 is built based on components, and it would be very difficult to manage the dependencies between them and the framework without a dependency manager. To make installing and managing these components easier, Symfony2 uses a manager called composer.

You can get it from the https://getcomposer.org/ website. The composer makes it easy to install and check all dependencies, download them, and integrate them to your work. If you want to find additional packages that can be installed with the composer, you should visit https://packagist.org/. This site is the main composer repository, and contains information about most of the packages that are installable with the composer.

To install the composer, go to https://getcomposer.org/download/ and see the download instruction. The download instruction should be similar to the following:

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

If the download was successful, you should see the composer.phar file in your directory. Move this to the project location in the same place where you have the composer.json and composer.lock files. You can also install it globally, if you prefer to, with these two commands:

$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

You will usually need to use only three composer commands: require, install, and update.

The require command is executed when you need to add a new dependency. The install command is used to install the package. The update command is used when you need to fetch the latest version of your dependencies as specified within the JSON file.

The difference between install and update is subtle, but very important. If you are executing the update command, your composer.lock file gets updated with the version of the code you just fetched and downloaded. The install command uses the information stored in the composer.lock file and the fetch version stored in this file.

When to use install? For example, if you deploy the code to the server, you should use install rather than update, as it will deploy the version of the code stored in composer.lock, rather than download the latest version (which may be untested by you). Also, if you work in a team and you just got an update through Git, you should use install to fetch the vendor code updated by other developers.

You should use the update command if you want to check whether there is an updated version of the package you have installed, that is, whether a new minor version of Symfony2 will be released, then the update command will fetch everything.

As an example, let’s install one extra package for user management called FOSUserBundle (FOS is a shortcut of Friends of Symfony). We will only install it here; we will not configure it. We will configure it in the chapter focused on security and user management.

To install FOSUserBundle, we need to know the correct package name and version. The easiest way is to look in the packagist site at https://packagist.org/ and search for the package there. If you type fosuserbundle, the search should return a package called friendsofsymfony/user-bundle as one of the top results. The download counts visible on the right-hand side might be also helpful in determining how popular the bundle is.

If you click on this, you will end up on the page with the detailed information about that bundle, such as homepage, versions, and requirements of the package.

Type the following command:

$ php composer.phar require friendsofsymfony/user-bundle ^1.3
Using version ^1.3 for friendsofsymfony/user-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing friendsofsymfony/user-bundle (v1.3.6)
    Loading from cache

friendsofsymfony/user-bundle suggests installing willdurand/propel-typehintable-behavior (Needed when using the propel implementation)
Writing lock file
Generating autoload files

Which version of the package you choose is up to you. If you are interested in package versioning standards, see the composer website at https://getcomposer.org/doc/01-basic-usage.md#package-versions to get more information on it.

The composer holds all the configurable information about dependencies and where to install them in a special JSON file called composer.json. Let’s take a look at this:

"name": "wbancer/todoapp",
"license": "proprietary",
"type": "project",
"autoload": {
  "psr-0": {
    "": "src/",
    "SymfonyStandard": "app/SymfonyStandard/"
"require": {
  "php": ">=5.3.9",
  "symfony/symfony": "2.7.*",
  "doctrine/orm": "~2.2,>=2.2.3,<2.5",
  // [...]
  "incenteev/composer-parameter-handler": "~2.0",
  "friendsofsymfony/user-bundle": "^1.3"
"require-dev": {
  "sensio/generator-bundle": "~2.3"
"scripts": {
  "post-root-package-install": [
  "post-install-cmd": [
  // post installation steps
  "post-update-cmd": [
  // post update steps
"config": {
  "bin-dir": "bin"
"extra": {
  // [...]

The most important section is the one with the require key. It holds all the information about the packages we want to use within the project. The key scripts contain a set of instructions to run post-install and post-update. The extra key in this case contains some settings specific to the Symfony2 framework. Note that one of the values in here points out to the parameter.yml file. This file is the main file holding the custom machine-specific parameters. The meaning of the other keys is rather obvious.

If you look into the vendor/ directory, you will notice that our package has been installed in the vendor/friendsofsymfony/user-bundle directory.