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.