The definitive guide of Symfony 1.0

19.3. Custom File Structure

Each time the framework uses a path to look for something (from core classes to templates, plug-ins, configurations, and so on), it uses a path variable instead of an actual path. By changing these variables, you can completely alter the directory structure of a symfony project, and adapt to the file organization requirements of any client.

Caution Customizing the directory structure of a symfony project is possible but not necessarily a good idea. One of the strengths of a framework like symfony is that any web developer can look at a project built with it and feel at home, because of the respect for conventions. Make sure you consider this issue before deciding to use your own directory structure.

19.3.1. The Basic File Structure

The path variables are defined in the $sf_symfony_data_dir/config/constants.php file, included when the application bootstraps. These variables are stored in the sfConfig object, and so they are easy to override. Listing 19-3 shows a listing of the path variables and the directory they reference.

Listing 19-3 - Default File Structure Variables, from $sf_symfony_data_dir/config/constants.php

sf_root_dir           # myproject/
                      #   apps/
sf_app_dir            #     myapp/
sf_app_config_dir     #       config/
sf_app_i18n_dir       #       i18n/
sf_app_lib_dir        #       lib/
sf_app_module_dir     #       modules/
sf_app_template_dir   #       templates/
sf_bin_dir            #   batch/
                      #   cache/
sf_base_cache_dir     #     myapp/
sf_cache_dir          #       prod/
sf_template_cache_dir #         templates/
sf_i18n_cache_dir     #         i18n/
sf_config_cache_dir   #         config/
sf_test_cache_dir     #         test/
sf_module_cache_dir   #         modules/
sf_config_dir         #   config/
sf_data_dir           #   data/
sf_doc_dir            #   doc/
sf_lib_dir            #   lib/
sf_model_lib_dir      #     model/
sf_log_dir            #   log/
sf_test_dir           #   test/
sf_plugins_dir        #   plugins/
sf_web_dir            #   web/
sf_upload_dir         #     uploads/

Every path to a key directory is determined by a parameter ending with _dir. Always use the path variables instead of real (relative or absolute) file paths, so that you will be able to change them later, if necessary. For instance, when you want to move a file to the uploads/ directory in an application, you should use sfConfig::get('sf_upload_dir') for the path instead of SF_ROOT_DIR.'/web/uploads/'.

The module directory structure is defined at runtime, when the routing system determines the module name ($module_name). It is automatically built according to the path names defined in the constants.php file, as shown in Listing 19-4.

Listing 19-4 - Default Module File Structure Variables

sf_app_module_dir                 # modules/
module_name                       #  mymodule/
sf_app_module_action_dir_name     #    actions/
sf_app_module_template_dir_name   #    templates/
sf_app_module_lib_dir_name        #    lib/
sf_app_module_view_dir_name       #    views/
sf_app_module_validate_dir_name   #    validate/
sf_app_module_config_dir_name     #    config/
sf_app_module_i18n_dir_name       #    i18n/

So, for instance, the path to the validate/ directory of the current module is built dynamically at runtime:

sfConfig::get('sf_app_module_dir').'/'.$module_name.'/'.sfConfig::get('sf_app_module_validate_dir_name')

19.3.2. Customizing the File Structure

You will probably need to modify the default project file structure if you develop an application for a client who already has a defined directory structure and who is not willing to change it to comply with the symfony logic. By overriding the sf_XXX_dir and sf_XXX_dir_name variables with sfConfig, you can make symfony work for a totally different directory structure than the default structure. The best place to do this is in the application config.php file.

Caution Use the application config.php and not the project one to override the sf_XXX_dir and sf_XXX_dir_name variables with sfConfig. The project config/config.php file is loaded very early in the life of a request, at a time when the sfConfig class doesn't exist yet, and when the constants.php file is not yet loaded.

For instance, if you want all applications to share a common directory for the template layouts, add this line to the myapp/config/config.php file to override the sf_app_template_dir settings:

sfConfig::set('sf_app_template_dir', sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.'templates');

Note that the application config.php file is not empty, so if you need to include file structure definitions there, do it at the end of the file.

19.3.3. Modifying the Project Web Root

All the paths built in constants.php rely on the project root directory, which is a constant defined in the front controller (SF_ROOT_DIR). Usually, the root directory is one level above the web/ directory, but you can use a different structure. Suppose that your main directory structure is made of two directories, one public and one private, as shown in Listing 19-5. This typically happens when hosting a project on a shared host.

Listing 19-5 - Example of Custom Directory Structure for a Shared Host

symfony/    # Private area
  apps/
  batch/
  cache/
  ...
www/        # Public area
  images/
  css/
  js/
  index.php

In this case, the root directory is the symfony/ directory. So the index.php front controller simply needs to define the SF_ROOT_DIR as follows for the application to work:

define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony');

In addition, since the public area is www/ instead of the usual web/, you must override two file paths in the application config.php file, as follows:

sfConfig::add(array(
  'sf_web_dir'      => SF_ROOT_DIR.'/../www',
  'sf_upload_dir'   => SF_ROOT_DIR.'/../www/'.sfConfig::get('sf_upload_dir_name'),
));

19.3.4. Linking to Symfony Libraries

The paths to the framework files are defined in the project config.php file, as you can see in Listing 19-6.

Listing 19-6 - The Paths to the Framework Files, in myproject/config/config.php

<?php

// symfony directories
$sf_symfony_lib_dir  = '/path/to/symfony/lib';
$sf_symfony_data_dir = '/path/to/symfony/data';

These paths are initialized when you call a symfony init-project from the command line, and refer to the symfony installation used to build the project. They are used both by the command line and by the MVC architecture.

This means that you can switch to another installation of symfony by changing the paths to the framework files.

These paths should be absolute, but by using dirname(__FILE__), you can refer to files inside the project structure and preserve independence of the chosen directory for the project installation. For instance, many projects choose to have the symfony lib/ directory appear as a symbolic link in the project lib/symfony/ directory, and do the same for the symfony data/ directory, as follows:

myproject/
  lib/
    symfony/ => /path/to/symfony/lib
  data/
    symfony/ => /path/to/symfony/data

In this case, the project config.php file just needs to define the symfony directories as follows:

$sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/symfony';
$sf_symfony_data_dir = dirname(__FILE__).'/../data/symfony';

The same principle also applies if you choose to include the symfony files as a svn:externals in the project lib/vendor/ directory:

myproject/
  lib/
    vendor/
      svn:externals symfony http://svn.symfony-project.com/branches/1.0

In this case, the config.php file should look like this:

$sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/vendor/symfony/lib';
$sf_symfony_data_dir = dirname(__FILE__).'/../lib/vendor/symfony/data';

Tip Sometimes, the different servers running an application don't have the same path to the symfony libraries. One way to enable that is to exclude the project config.php file from the synchronization (by adding it to rsync_exclude.txt). Another method is to keep the same paths in the development and production versions of config.php, but to have these paths point to symbolic links that can vary according to the server.