Development

/doc/tags/RELEASE_1_1_0_BETA4/book/19-Mastering-Symfony-s-Configuration-Files.txt

You must first sign up to be able to contribute.

root/doc/tags/RELEASE_1_1_0_BETA4/book/19-Mastering-Symfony-s-Configuration-Files.txt

Revision 8338, 41.2 kB (checked in by dwhittle, 9 months ago)

1.1: updated docs for bridges and autoloading

Line 
1 Chapter 19 - Mastering Symfony's Configuration Files
2 ====================================================
3
4 Now that you know symfony very well, you are already able to dig into its code to understand its core design and discover new hidden abilities. But before extending the symfony classes to match your own requirements, you should take a closer look at some of the configuration files. Many features are already built into symfony and can be activated by just changing configuration settings. This means that you can tweak the symfony core behavior without overriding its classes. This chapter takes you deep into the configuration files and their powerful capabilities.
5
6 Symfony Settings
7 ----------------
8
9 The `frontend/config/settings.yml` file contains the main symfony configuration for the `frontend` application. You have already seen the function of many settings from this file in the previous chapters, but let's revisit them.
10
11 As explained in Chapter 5, this file is environment-dependent, which means that each setting can take a different value for each environment. Remember that each parameter defined in this file is accessible from inside the PHP code via the `sfConfig` class. The parameter name is the setting name prefixed with sf_. For instance, if you want to get the value of the cache parameter, you just need to call `sfConfig::get('sf_cache')`.
12
13 ### Default Modules and Actions
14
15 Symfony provides default pages for special situations. In the case of a routing error, symfony executes an action of the `default` module, which is stored in the `$sf_symfony_data_dir/modules/default/` directory. The `settings.yml` file defines which action is executed depending on the error:
16
17   * `error_404_module` and `error_404_action`: Action called when the URL entered by the user doesn't match any route or when an `sfError404Exception` occurs. The default value is `default/error404`.
18   * `login_module` and `login_action`: Action called when a nonauthenticated user tries to access a page defined as `secure` in `security.yml` (see Chapter 6 for details). The default value is `default/login`.
19   * `secure_module` and `secure_action`: Action called when a user doesn't have the credentials required for an action. The default value is `default/secure`.
20   * `module_disabled_module` and `module_disabled_action`: Action called when a user requests a module declared as disabled in `module.yml`. The default value is `default/disabled`.
21
22 Before deploying an application to production, you should customize these actions, because the `default` module templates include the symfony logo on the page. See Figure 19-1 for a screenshot of one of these pages, the error 404 page.
23
24 Figure 19-1 - Default 404 error page
25
26 ![Default 404 error page](/images/book/F1901.jpg "Default 404 error page")
27
28 You can override the default pages in two ways:
29
30   * You can create your own default module in the application's `modules/` directory, override all the actions defined in the `settings.yml` file (`index`, `error404`, `login`, `secure`, `disabled`) and all the related templates (`indexSuccess.php`, `error404Success.php`, `loginSuccess.php`, `secureSuccess.php`, `disabledSuccess.php`).
31   * You can change the default module and action settings of the `settings.yml` file to use pages of your application.
32
33 Two other pages bear a symfony look and feel, and they also need to be customized before deployment to production. These pages are not in the `default` module, because they are called when symfony cannot run properly. Instead, you will find these default pages in the `$sf_symfony_data_dir/web/errors/` directory:
34
35   * `error500.php`: Page called when an internal server error occurs in the production environment. In other environments (where `SF_DEBUG` is set to `true`), when an error occurs, symfony displays the full execution stack and an explicit error message (see Chapter 16 for details).
36   * `unavailable.php`: Page called when a user requests a page while the application is disabled (with the `disable` task). It is also called while the cache is being cleared (that is, between a call to the `php symfony cache:clear` task and the end of this task execution). On systems with a very large cache, the cache-clearing process can take several seconds. Symfony cannot execute a request with a partially cleared cache, so requests received before the end of the process are redirected to this page.
37
38 To customize these pages, simply create `error500.php` and `unavailable.php` pages in your application's `web/errors/` directory. Symfony will use these instead of its own.
39
40 >**NOTE**
41 >To have requests redirected to the `unavailable.php` page when needed, you need to set the `check_lock` setting to `on` in the application `settings.yml`. The check is deactivated by default, because it adds a very slight overhead for every request.
42
43 ### Optional Feature Activation
44
45 Some parameters of the `settings.yml` file control optional framework features that can be enabled or disabled. Deactivating unused features boosts performances a bit, so make sure to review the settings listed in Table 19-1 before deploying your application.
46
47 Table 19-1 - Optional Features Set Through `settings.yml`
48
49 Parameter               | Description | Default Value
50 ----------------------- | ----------- | -------------
51 `use_database`          | Enables the database manager. Set it to `off` if you don't use a database. | `on`
52 `use_security`          | Enables security features (secure actions and credentials; see Chapter 6). The default security filter (`sfBasicSecurityFilter`) is enabled only if it is `on`. | `on`
53 `i18n`                  | Enables interface translation (see Chapter 13). Set it to `on` for multilingual applications. | `off`
54 `logging_enabled`       | Enables logging of symfony events. Set it to off when you want to ignore the logging.yml settings and turn symfony logging off completely. | `on`
55 `escaping_strategy`     | Enables the output escaping feature (see Chapter 7). Set it to `on` if you want data passed to your templates to be escaped. | `off`
56 `cache`                 | Enables template caching (see Chapter 12). Set it to `on` if one of your modules includes `cache.yml` file. The cache filter (`sfCacheFilter`) is enabled only if it is on. | `off` in development, `on` in production
57 `web_debug`             | Enables the web debug toolbar for easy debugging (see Chapter 16). Set it to `on` to display the toolbar on every page. The web debug filter (`sfWebDebugFilter`) is enabled ony if it is on. | `on` in development, `off` in production
58 `check_symfony_version` | Enables the check of the symfony version for every request. Set it to on for automatic cache clearing after a framework upgrade. Leave it set to off if you always clear the cache after an upgrade. | `off`
59 `check_lock`            | Enables the application lock system, triggered by the `cache:clear` and `project:disable` tasks (see the previous section). Set it to `on` to have all requests to disabled applications redirected to the `$sf_symfony_data_dir/web/errors/unavailable.php` page. | `off`
60 `compressed`            | Enables PHP response compression. Set it to `on` to compress the outgoing HTML via the PHP compression handler. | `off`
61 `use_process_cache`     | Enables symfony optimizations based on PHP accelerators. When such an accelerator (for instance, APC, XCache, or eAccelerator) is installed, symfony takes advantage of its features to keep objects and configuration in memory between requests. Set the parameter to `off` in development or when you don't want PHP accelerator optimizations. Note that even if you don't have any accelerator installed, leaving it set to `on` will not harm performance. | `on`
62
63 ### Feature Configuration
64
65 Symfony uses some parameters of `settings.yml` to alter the behavior of built-in features such as form validation, cache, and third-party modules.
66
67 #### Output Escaping Settings
68
69 Output escaping settings control the way the variables are accessible in the template (see Chapter 7). The `settings.yml` file includes two settings for this feature:
70
71   * The `escaping_strategy` setting can take the value`on`, or `off`.
72   * The escaping_method setting can be set to `ESC_RAW`, `ESC_SPECIALCHARS`, `ESC_ENTITIES`, `ESC_JS`, or `ESC_JS_NO_ENTITIES`.
73
74 #### Routing Settings
75
76 The routing settings (see Chapter 9) are defined in `factories.yml`, under the `routing` key. Listing 19-1 show the default routing configuration.
77
78 Listing 19-1 - Routing Configuration Settings, in `frontend/config/factories.yml`
79
80     routing:
81       class: sfPatternRouting
82       param:
83         load_configuration: true
84         suffix:             .
85         default_module:     default
86         default_action:     index
87         variable_prefixes:  [':']
88         segment_separators: ['/', '.']
89         variable_regex:     '[\w\d_]+'
90         debug:              %SF_DEBUG%
91         logging:            %SF_LOGGING_ENABLED%
92         cache:
93           class: sfFileCache
94           param:
95             automatic_cleaning_factor: 0
96             cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
97             lifetime:                  31556926
98             prefix:                    %SF_APP_DIR%
99
100   * The `suffix` parameter sets the default suffix for generated URLs. The default value is a period (`.`), and it corresponds to no suffix. Set it to `.html`, for instance, to have all generated URLs look like static pages.
101   * When a routing rule doesn't define the `module` or the `action` parameter, values from the `factories.yml` are used instead:
102     * `default_module`: Default `module` request parameter. Defaults to the `default` module.
103     * `default_action`: Default `action` request parameter. Defaults to the `index` action.
104   * By default, route patterns identify named wildcards by a colon (`:`) prefix. But if you want to write your rules in a more PHP-friendly syntax, you can add the dollar (`$`) sign in the `variable_prefixes` array. That way, you can write a pattern like '/article/$year/$month/$day/$title' instead of '/article/:year/:month/:day/:title'.
105   * The pattern routing will identify named wildcards between separators. The default separators are the slash and the dot, but you can add more if you want in the `segment_separators` parameter. For instance, if you add the dash (`-`), you can write a pattern like '/article/:year-:month-:day/:title'.
106   * The pattern routing uses its own cache, in production mode, to speed up conversions between external URLs and internal URIs. By default, this cache uses the filesystem, but you can use any cache class, provided that you declare the class and its settings in the `cache` parameter. See Chapter 15 for the list of available cache storage classes. To deactivate the routing cache in production, set the `debug` parameter to `on`.
107
108 These are only the settings for the `sfPatternRouting` class. You can use another class for your application routing, either your own or one of symfony's routing factories (`sfNoRouting` and `sfPathInfoRouting`). With either of these two factories, all external URLs look like 'module/action?key1=param1'. No customization possible--but it's fast. The difference is that the first uses PHP's `GET`, and the second uses `PATH_INFO`. Use them mainly for backend interfaces.
109
110 There is one additional parameter related to routing, but this one is stored in `settings.yml`:
111   * `no_script_name` enables the front controller name in generated URLs. The `no_script_name` setting can be on only for a single application in a project, unless you store the front controllers in various directories and alter the default URL rewriting rules. It is usually on for the production environment of your main application and off for the others.
112
113 #### Form Validation Settings
114
115 Form validation settings control the way error messages output by the `Validation` helpers look (see Chapter 10). These errors are included in `<div>` tags, and they use the `validation_error_ class` setting as a `class` attribute and the `validation_error_id_prefix` setting to build up the `id` attribute. The default values are `form_error` and `error_for_`, so the attributes output by a call to the `form_error()` helper for an input named `foobar` will be `class="form_error" id="error_for_foobar"`.
116
117 Two settings determine which characters precede and follow each error message: `validation_error_prefix` and `validation_error_suffix`. You can change them to customize all error messages at once.
118
119 #### Cache Settings
120
121 Cache settings are defined in `cache.yml` for the most part, except for two in `settings.yml`: `cache` enables the template cache mechanism, and `etag` enables ETag handling on the server side (see Chapter 15). You can also specify which storage to use for two all cache systems (the view cache, the routing cache, and the i19n cache) in `factories.yml`. Listing 19-2 show the default view cache factory configuration.
122
123 Listing 19-2 - View Cache Configuration Settings, in `frontend/config/factories.yml`
124
125     view_cache:
126       class: sfFileCache
127       param:
128         automatic_cleaning_factor: 0
129         cache_dir:                 %SF_TEMPLATE_CACHE_DIR%
130         lifetime:                  86400
131         prefix:                    %SF_APP_DIR%/template
132
133 The `class` can be any of `sfFileCache`, `sfAPCCache`, `sfEAcceleratorCache`, `sfXCacheCache`, `sfMemcacheCache`, and `sfSQLiteCache`. It can also be your own custom class, provided it extends `sfCache` and provides the same generic methods for setting, retrieving and deleting a key in the cache. The factory parameters depend on the class you choose, but there are constants:
134
135   * `lifetime` defines the number of seconds after which a cache part is removed
136   * `prefix` is a prefix added to every cache key. Use the same prefix for two applications if you want their cache to be shared.
137
138 Then, for each particular factory, you have to define the location of the cache storage.
139
140  * for `sfFileCache`, the `cache_dir` parameter locates the absolute path to the cache directory
141  * `sfAPCCache`, `sfEAcceleratorCache`, and `sfXCacheCache` don't take any location parameter, since they use PHP native functions for communicating with APC, EAccelerator or the XCache cache systems
142  * for `sfMemcacheCache`, enter the hostname of the Memcached server in the `host` parameter, or an array of hosts in the `servers` parameter
143  * for `sfSQLiteCache`, the absolute path to the SQLite database file should be entered in the `database` parameter
144
145 For additional parameters, check the API documentation of each cache class.
146
147 The view is not the only component to be able to use a cache. Both the `routing` and the `I18N` factories offer a `cache` parameter in which you can set any cache factory, just like the view cache. For instance, Listing 19-1 shows of the routing uses the file cache for its speedup tactics by default, but you can change it to whatever you want.
148
149 #### Logging Settings
150
151 Two logging settings (see Chapter 16) are stored in `settings.yml`:
152
153   * `error_reporting` specifies which events are logged in the PHP logs. By default, it is set to `E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR` for the production environment (so the logged events are `E_PARSE`, `E_COMPILE_ERROR`, `E_ERROR`, `E_CORE_ERROR`, and `E_USER_ERROR`) and to `E_ALL | E_STRICT` for the development environment.
154   * The `web_debug` setting activates the web debug toolbar. Set it to `on` only in the development and test environments.
155
156 #### Paths to Assets
157
158 The `settings.yml` file also stores paths to assets. If you want to use another version of the asset than the one bundled with symfony, you can change these path settings:
159
160   * Rich text editor JavaScript files stored in `rich_text_js_dir` (by default, `js/tiny_mce`)
161   * Prototype libraries stored in `prototype_web_dir` (by default, `/sf/prototype`)
162   * Files needed by the administration generator stored in `admin_web_dir`
163   * Files needed by the web debug toolbar stored in `web_debug_web_dir`
164   * Files needed by the javascript calendar stored in `calendar_web_dir`
165
166 #### Default Helpers
167
168 Default helpers, loaded for every template, are declared in the `standard_helpers` setting (see Chapter 7). By default, these are the `Partial`, `Cache`, and `Form` helper groups. If you use a helper group in all templates of an application, adding its name to the `standard_helpers` setting saves you the hassle of declaring it with `use_helper()` on each template.
169
170 #### Activated Modules
171
172 Activated modules from plug-ins or from the symfony core are declared in the `enabled_modules` parameter. Even if a plug-in bundles a module, users can't request this module unless it is declared in `enabled_modules`. The `default` module, which provides the default symfony pages (congratulations, page not found, and so on), is the only enabled module by default.
173
174 #### Character Set
175
176 The character set of the responses is a general setting of the application, because it is used by many components of the framework (templates, output escaper, helpers, and so on). Defined in the `charset` setting, its default (and advised) value is `utf-8`.
177
178 #### Miscellaneous Configuration
179
180 The `settings.yml` file contains a few more parameters, used internally by symfony for core behaviors. Listing 19-3 lists them as they appear in the configuration file.
181
182 Listing 19-3 - Miscellaneous Configuration Settings, in `frontend/config/settings.yml`
183
184     # Remove comments in core framework classes as defined in the core_compile.yml
185     strip_comments:         on
186     # Maximum number of forwards followed by the action before raising an exception
187     max_forwards:           5
188     # Global constants
189     path_info_array:        SERVER
190     path_info_key:          PATH_INFO
191     url_format:             PATH
192
193 >**SIDEBAR**
194 >Adding Your application settings
195 >
196 >The `settings.yml` file defines symfony settings for an application. As discussed in Chapter 5, when you want to add new parameters, the best place to do so is in the `frontend/config/app.yml` file. This file is also environment-dependent, and the settings it defines are available through the sfConfig class with the `app_` prefix.
197 >
198 >
199 >     all:
200 >       creditcards:
201 >         fake:             off    # app_creditcards_fake
202 >         visa:             on     # app_creditcards_visa
203 >         americanexpress:  on     # app_creditcards_americanexpress
204 >
205 >
206 >You can also write an `app.yml` file in the project configuration directory, and this provides a way to define custom project settings. The configuration cascade also applies to this file, so the settings defined in the application `app.yml` file override the ones defined at the project level.
207
208 Extending the Autoloading Feature
209 ---------------------------------
210
211 The autoloading feature, briefly explained in Chapter 2, exempts you from requiring classes in your code if they are located in specific directories. This means that you can just let the framework do the job for you, allowing it to load only the necessary classes at the appropriate time, and only when needed.
212
213 The `autoload.yml` file lists the paths in which autoloaded classes are stored. The first time this configuration file is processed, symfony parses all the directories referenced in the file. Each time a file ending with `.php` is found in one of these directories, the file path and the class names found in this file are added to an internal list of autoloading classes. This list is saved in the cache, in a file called `config/config_autoload.yml.php`. Then, at runtime, when a class is used, symfony looks in this list for the class path and includes the `.php` file automatically.
214
215 Autoloading works for all `.php` files containing classes and/or interfaces.
216
217 By default, classes stored in the following directories in your projects benefit from the autoloading automatically:
218
219   * `myproject/lib/`
220   * `myproject/lib/model`
221   * `myproject/apps/frontend/lib/`
222   * `myproject/apps/frontend/modules/mymodule/lib`
223
224 There is no `autoload.yml` file in the default application configuration directory. If you want to modify the framework settings--for instance, to autoload classes stored somewhere else in your file structure--create an empty autoload.yml file and override the settings of `$sf_symfony_lib_dir/config/config/autoload.yml` or add your own.
225
226 The autoload.yml file must start with an autoload: key and list the locations where symfony should look for classes. Each location requires a label; this gives you the ability to override symfony's entries. For each location, provide a `name` (it will appear as a comment in `config_autoload.yml.php`) and an absolute `path`. Then define if the search must be `recursive`, which directs symfony to look in all the subdirectories for `.php` files, and `exclude` the subdirectories you want. Listing 19-4 shows the locations used by default and the file syntax.
227
228 Listing 19-4 - Default Autoloading Configuration, in `$sf_symfony_lib_dir/config/config/autoload.yml`
229
230     autoload:
231       # plugins
232       plugins_lib:
233         name:           plugins lib
234         path:           %SF_PLUGINS_DIR%/*/lib
235         recursive:      on
236
237       plugins_module_lib:
238         name:           plugins module lib
239         path:           %SF_PLUGINS_DIR%/*/modules/*/lib
240         prefix:         2
241         recursive:      on
242
243       # project
244       project:
245         name:           project
246         path:           %SF_LIB_DIR%
247         recursive:      on
248         exclude:        [model, symfony]
249
250       project_model:
251         name:           project model
252         path:           %SF_LIB_DIR%/model
253         recursive:      on
254
255       # application
256       application:
257         name:           application
258         path:           %SF_APP_LIB_DIR%
259         recursive:      on
260
261       modules:
262         name:           module
263         path:           %SF_APP_DIR%/modules/*/lib
264         prefix:         1
265         recursive:      on
266
267
268 A rule path can contain wildcards and use the file path parameters from the `constants.php` file (see the next section). If you use these parameters in the configuration file, they must appear in uppercase and begin and end with `%`.
269
270 Editing your own `autoload.yml` will add new locations to symfony's autoloading, but you may want to extend this mechanism and add your own autoloading handler to symfony's handler. As symfony uses the standard `spl_autoload_register()` function to manage class autoloading, you can register more callbacks in the application configuration class:
271
272     [php]
273     class frontendConfiguration extends sfApplicationConfiguration
274     {
275       public function initialize()
276       {
277         parent::initialize(); // load symfony autoloading first
278
279         // insert your own autoloading callables here
280         spl_autoload_register(array('myToolkit', 'autoload'));
281       }
282     }
283
284
285 When the PHP autoloading system encounters a new class, it will first try the symfony autoloading method (and use the locations defined in `autoload.yml`). If it doesn't find a class definition, all the other callables registered with `spl_autoload_register()` will be called, until the class is found. So you can add as many autoloading mechanisms as you want--for instance, to provide a bridge to other framework components (see Chapter 17).
286
287 Custom File Structure
288 ---------------------
289
290 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.
291
292 >**CAUTION**
293 >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.
294
295 ### The Basic File Structure
296
297 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-5 shows a listing of the path variables and the directory they reference.
298
299 Listing 19-5 - Default File Structure Variables, from `$sf_symfony_data_dir/config/constants.php`
300
301     sf_root_dir           # myproject/
302                           #   apps/
303     sf_app_dir            #     frontend/
304     sf_app_config_dir     #       config/
305     sf_app_i18n_dir       #       i18n/
306     sf_app_lib_dir        #       lib/
307     sf_app_module_dir     #       modules/
308     sf_app_template_dir   #       templates/
309     sf_bin_dir            #   batch/
310                           #   cache/
311     sf_base_cache_dir     #     frontend/
312     sf_cache_dir          #       prod/
313     sf_template_cache_dir #         templates/
314     sf_i18n_cache_dir     #         i18n/
315     sf_config_cache_dir   #         config/
316     sf_test_cache_dir     #         test/
317     sf_module_cache_dir   #         modules/
318     sf_config_dir         #   config/
319     sf_data_dir           #   data/
320     sf_doc_dir            #   doc/
321     sf_lib_dir            #   lib/
322     sf_model_lib_dir      #     model/
323     sf_log_dir            #   log/
324     sf_test_dir           #   test/
325     sf_plugins_dir        #   plugins/
326     sf_web_dir            #   web/
327     sf_upload_dir         #     uploads/
328
329 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/'`.
330
331 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-6.
332
333 Listing 19-6 - Default Module File Structure Variables
334
335     sf_app_module_dir                 # modules/
336     module_name                       #  mymodule/
337     sf_app_module_action_dir_name     #    actions/
338     sf_app_module_template_dir_name   #    templates/
339     sf_app_module_lib_dir_name        #    lib/
340     sf_app_module_view_dir_name       #    views/
341     sf_app_module_validate_dir_name   #    validate/
342     sf_app_module_config_dir_name     #    config/
343     sf_app_module_i18n_dir_name       #    i18n/
344
345 So, for instance, the path to the `validate/` directory of the current module is built dynamically at runtime:
346
347     [php]
348     sfConfig::get('sf_app_module_dir').'/'.$module_name.'/'.sfConfig::get('sf_app_module_validate_dir_name')
349
350 ### Customizing the File Structure
351
352 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.
353
354 >**CAUTION**
355 >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.
356
357 For instance, if you want all applications to share a common directory for the template layouts, add this line to the `frontend/config/config.php` file to override the `sf_app_template_dir` settings:
358
359     [php]
360     sfConfig::set('sf_app_template_dir', sfConfig::get('sf_root_dir').DIRECTORY_SEPARATOR.'templates');
361
362 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.
363
364 ### Modifying the Project Web Root
365
366 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-7. This typically happens when hosting a project on a shared host.
367
368 Listing 19-7 - Example of Custom Directory Structure for a Shared Host
369
370     symfony/    # Private area
371       apps/
372       batch/
373       cache/
374       ...
375     www/        # Public area
376       images/
377       css/
378       js/
379       index.php
380
381 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:
382
383     [php]
384     define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony');
385
386 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:
387
388     [php]
389     sfConfig::add(array(
390       'sf_web_dir'      => SF_ROOT_DIR.DIRECTORY_SEPARATOR.'www',
391       'sf_upload_dir'   => SF_ROOT_DIR.DIRECTORY_SEPARATOR.'www'.DIRECTORY_SEPARATOR.sfConfig::get('sf_upload_dir_name'),
392     ));
393
394 ### Linking to Symfony Libraries
395
396 The paths to the framework files are defined in the project `config.php` file, as you can see in Listing 19-8.
397
398 Listing 19-8 - The Paths to the Framework Files, in `myproject/config/config.php`
399
400     [php]
401     <?php
402
403     // symfony directories
404     $sf_symfony_lib_dir  = '/path/to/symfony/lib';
405     $sf_symfony_data_dir = '/path/to/symfony/data';
406
407 These paths are initialized when you call a `php symfony generate: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.
408
409 This means that you can switch to another installation of symfony by changing the paths to the framework files.
410
411 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:
412
413     myproject/
414       lib/
415         symfony/ => /path/to/symfony/lib
416       data/
417         symfony/ => /path/to/symfony/data
418
419 In this case, the project config.php file just needs to define the symfony directories as follows:
420
421     [php]
422     $sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/symfony';
423     $sf_symfony_data_dir = dirname(__FILE__).'/../data/symfony';
424
425 The same principle also applies if you choose to include the symfony files as a `svn:externals` in the project `lib/vendor/` directory:
426
427     myproject/
428       lib/
429         vendor/
430           svn:externals symfony http://svn.symfony-project.com/trunk/
431
432 In this case, the `config.php` file should look like this:
433
434     [php]
435     $sf_symfony_lib_dir  = dirname(__FILE__).'/../lib/vendor/symfony/lib';
436     $sf_symfony_data_dir = dirname(__FILE__).'/../lib/vendor/symfony/data';
437
438 >**TIP**
439 >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.
440
441 Understanding Configuration Handlers
442 ------------------------------------
443
444 Each configuration file has a handler. The job of configuration handlers is to manage the configuration cascade, and to do the translation between the configuration files and the optimized PHP code executable at runtime.
445
446 ### Default Configuration Handlers
447
448 The default handler configuration is stored in `$sf_symfony_lib_dir/config/config/config_handlers.yml`. This file links the handlers to the configuration files according to a file path. Listing 19-9 shows an extract of this file.
449
450 Listing 19-9 - Extract of `$sf_symfony_lib_dir/config/config/config_handlers.yml`
451
452     config/settings.yml:
453       class:    sfDefineEnvironmentConfigHandler
454       param:
455         prefix: sf_
456
457     config/app.yml:
458       class:    sfDefineEnvironmentConfigHandler
459       param:
460         prefix: app_
461
462     config/filters.yml:
463       class:    sfFilterConfigHandler
464
465     modules/*/config/module.yml:
466       class:    sfDefineEnvironmentConfigHandler
467       param:
468         prefix: mod_
469         module: yes
470
471 For each configuration file (`config_handlers.yml` identifies each file by a file path with wildcards), the handler class is specified under the `class` key.
472
473 The settings of configuration files handled by `sfDefineEnvironmentConfigHandler` can be made available directly in the code via the `sfConfig` class, and the param key contains a prefix value.
474
475 You can add or modify the handlers used to process each configuration file--for instance, to use INI or XML files instead of YAML files.
476
477 >**NOTE**
478 >The configuration handler for the `config_handlers.yml` file is `sfRootConfigHandler` and, obviously, it cannot be changed.
479
480 If you ever need to modify the way the configuration is parsed, create an empty `config_handlers.yml` file in your application's `config/` folder and override the `class` lines with the classes you wrote.
481
482 ### Adding Your Own Handler
483
484 Using a handler to deal with a configuration file provides two important benefits:
485
486   * The configuration file is transformed into executable PHP code, and this code is stored in the cache. This means that the configuration is parsed only once in production, and the performance is optimal.
487   * The configuration file can be defined at different levels (project and application) and the final parameter values will result from a cascade. So you can define parameters at a project level and override them on a per-application basis.
488
489 If you feel like writing your own configuration handler, follow the example of the structure used by the framework in the `$sf_symfony_lib_dir/config/` directory.
490
491 Let's suppose that your application contains a `myMapAPI` class, which provides an interface to a third-party web service delivering maps. This class needs to be initialized with a URL and a user name, as shown in Listing 19-10.
492
493 Listing 19-10 - Example of Initialization of the `myMapAPI` Class
494
495     [php]
496     $mapApi = new myMapAPI();
497     $mapApi->setUrl($url);
498     $mapApi->setUser($user);
499
500 You may want to store these two parameters in a custom configuration file called `map.yml`, located in the application config/ directory. This configuration file might contain the following:
501
502     api:
503       url:  map.api.example.com
504       user: foobar
505
506 In order to transform these settings into code equivalent to Listing 19-9, you must build a configuration handler. Each configuration handler must extend `sfConfigHandler` and provide an `execute()` method, which expects an array of file paths to configuration files as a parameter, and must return data to be written in a cache file. Handlers for YAML files should extend the `sfYamlConfigHandler` class, which provides additional facilities for YAML parsing. For the `map.yml` file, a typical configuration handler could be written as shown in Listing 19-11.
507
508 Listing 19-11 - A Custom Configuration Handler, in `frontend/lib/myMapConfigHandler.class.php`
509
510     [php]
511     <?php
512
513     class myMapConfigHandler extends sfYamlConfigHandler
514     {
515       public function execute($configFiles)
516       {
517         $this->initialize();
518
519         // Parse the yaml
520         $config = $this->parseYamls($configFiles);
521
522         $data  = "<?php\n";
523         $data. = "\$mapApi = new myMapAPI();\n";
524
525         if (isset($config['api']['url'])
526         {
527           $data. = sprintf("\$mapApi->setUrl('%s');\n", $config['api']['url']);
528         }
529
530         if (isset($config['api']['user'])
531         {
532           $data. = sprintf("\$mapApi->setUser('%s');\n", $config['api']['user']);
533         }
534
535         return $data;
536       }
537     }
538
539 The `$configFiles` array that symfony passes to the `execute()` method will contain a path to all the `map.yml` files found in the `config/` folders. The `parseYamls()` method will handle the configuration cascade.
540
541 In order to associate this new handler with the `map.yml` file, you must create a `config_handlers.yml` configuration file with the following content:
542
543     config/map.yml:
544       class: myMapConfigHandler
545
546 >**NOTE**
547 >The `class` must either be autoloaded (that's the case here) or defined in the file whose path is written in a `file` parameter under the `param` key.
548
549 As with many other symfony configuration files, you can also register a configuration handler directly in your PHP code:
550
551     sfConfigCache::getInstance()->registerConfigHandler('config/map.yml', myMapConfigHandler, array());
552
553 When you need the code based on the `map.yml` file and generated by the `myMapConfigHandler` handler in your application, call the following line:
554
555     [php]
556     include(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_config_dir_name').'/map.yml'));
557
558 When calling the `checkConfig()` method, symfony looks for existing `map.yml` files in the configuration directories and processes them with the handler specified in the `config_handlers.yml` file, if a `map.yml.php` does not already exist in the cache or if the `map.yml` file is more recent than the cache.
559
560 >**TIP**
561 >If you want to handle environments in a YAML configuration file, the handler can extend the `sfDefineEnvironmentConfigHandler` class instead of `sfYamlConfigHandler`. After calling the `parseYaml()` method to retrieve configuration, you should call the `mergeEnvironment()` method. You can do it all in one line by calling `$config = $this->mergeEnvironment($this->parseYamls ($configFiles));`.
562
563 -
564
565 >**SIDEBAR**
566 >Using Existing configuration handlers
567 >
568 >If you just need to allow users to retrieve values from the code via `sfConfig`, you can use the `sfDefineEnvironmentConfigHandler` configuration handler class. For instance, to have the `url` and `user` parameters available as `sfConfig::get('map_url')` and `sfConfig::get('map_user')`, define your handler as follows:
569 >
570 >     config/map.yml:
571 >       class: sfDefineEnvironmentConfigHandler
572 >       param:
573 >         prefix: map_
574 >
575 >Be careful not to choose a prefix already used by another handler. Existing prefixes are sf_, app_, and mod_.
576
577 Controlling PHP Settings
578 ------------------------
579
580 In order to have a PHP environment compatible with the rules and best practices of agile development, symfony checks and overrides a few settings of the `php.ini` configuration. This is the purpose of the `php.yml` file. Listing 19-12 shows the default `php.yml` file.
581
582 Listing 19-12 - Default PHP Settings for Symfony, in `$sf_symfony_data_dir/config/php.yml`
583
584     set:
585       magic_quotes_runtime:        off
586       log_errors:                  on
587       arg_separator.output:        |
588         &amp;
589
590     check:
591       zend.ze1_compatibility_mode: off
592
593     warn:
594       magic_quotes_gpc:            off
595       register_globals:            off
596       session.auto_start:          off
597
598 The main purpose of this file is to check that the PHP configuration is compatible with your application. It is also very useful to check that your development server configuration is as similar as possible to the production server. That's why you should inspect the production server configuration at the beginning of a project, and report its PHP settings in a `php.yml` file in your project. You can then develop and test with confidence that you will not encounter any compatibility errors once you deploy your project to the production platform.
599
600 The variables defined under the `set` header are modified (despite how they were defined in the server `php.ini` file). The variables defined under the `warn` category cannot be modified on the fly, but symfony can run even if they are not properly set. It is just considered bad practice to have these settings set to on, and symfony will log a warning in this case. The variables defined under the `check` category cannot be modified on the fly either, but they must have a certain value for symfony to run. So, in this case, an exception is raised if the `php.ini` file is not correct.
601
602 The default php.yml file sets log_errors to on so that you can trace errors in symfony projects. It also recommends that the `register_globals` be set to `off` to prevent security breaches.
603
604 If you don't want symfony to apply these settings, or if you want to run a project with `magic_quotes_gpc` and `register_globals` set to `on` without warning, then create a `php.yml` file in your application `config/` directory, and override the settings you want to change.
605
606 Additionally, if your project requires an extension, you can specify it under the `extensions` category. It expects an array of extension names, as follows:
607
608     extensions: [gd, mysql, mbstring]
609
610 Summary
611 -------
612
613 The configuration files can heavily modify the way the framework works. Because symfony relies on configuration even for its core features and file loading, it can adapt to many more environments than just the standard dedicated host. This great configurability is one of the main strengths of symfony. Even if it sometimes frightens newcomers, who see in configuration files a lot of conventions to learn, it allows symfony applications to be compatible with a very large number of platforms and environments. Once you become a master of symfony's configuration, no server will ever refuse to run your applications!
Note: See TracBrowser for help on using the browser.