Capítulo 5 - Configurando o Symfony
Para ser simples e fácil de usar, o symfony define algumas convenções, que deveriam satisfazer às exigências mais comuns de aplicações padrão sem a necessidade de modificação. Entretanto, utilizando um conjunto de simples e poderosos arquivos de configuração, é possível personalizar quase tudo sobre a forma que o framework e sua aplicação interagem entre si. Com estes arquivos, você, também, será capaz de adicionar parâmetros específicos para suas aplicações.
Este capítulo explica como o sistema de configuração trabalha:
- A configuração do symfony é mantida em arquivos escritos em YAML, embora você possa sempre escolher um outro formato.
- Os arquivos de configuração estão no projeto, na aplicação, e nos níveis de módulo na estrutura de diretório de um projeto.
- Você pode definir diversos conjuntos de ajustes de configuração; no symfony, um conjunto de configuração é chamado de ambiente.
- Os valores definidos nos arquivos de configuração estão disponíveis no código PHP da sua apĺicação.
- Adicionalmente, symfony autoriza código PHP em arquivos YAML e outros truques para tornar o sistema de configuração ainda mais flexível.
O Sistema de Configuração
Independentemente do objetivo, a maioria das aplicações web têm um conjunto de características em comum. Por exemplo, algumas seções podem ser restritas a um subconjunto de usuários, ou as páginas podem ser decoradas por um layout, ou um formulário pode ser preenchido com uma entrada de usuário depois de ter falhado uma validação. Um framework define a estrutura para emulação destas características, e o desenvolvedor pode further tweak them mudando um ajuste de configuração. Esta estratégia poupa muito tempo de desenvolvimento, desde que muitas mudanças não requerem uma linha de código, mesmo se existe muito código por trás. É, também, muito mais eficiente, porque garante que tal informação pode ser mantida em um único e facilmente identificável local.
Entretanto, esta abordagem tem 2 sérias desvantagens:
- Desenvolvedores acabam escrevendo arquivos XML infinitamente complicados.
- Em uma arquitetura PHP, cada requisição demora mais para ser processada.
Levando estas desvantagens em conta, symfony usa arquivos de configuração somente para o que eles são melhores. De fato, o objetivo de um sistema de configuração no symfony é ser:
- Potente: Quase todo aspecto que pode ser gerenciado usando arquivos de configuração é gerenciado usando arquivos de configuração.
- Simples: Muitos aspectos de configuração não são mostrados em uma aplicação normal, desde que eles raramente precisam ser alterados.
- Fácil: Arquivos de configuração são fáceis de ler, de modificar e de serem criados pelo desenvolvedor.
- Personalizável: A linguagem de configuração padrão é o YAML, mas pode ser INI, XML, ou qualquer formato que o desenvolvedor preferir.
- Rápido: Os arquivos de configuração nunca são processados pela aplicação, mas pelo sistema de configuração, o qual os compila em um pedaço de código de rápido processamento para o servidor PHP.
Sintaxe YAML e Convenções do Symfony
Para sua configuração, symfony usa, por padrão, o formato YAML, ao invés de formatos mais tradicionais como: INI ou XML. YAML mostra a estrutura através da identação e é rápido de escrever. Suas vantagens e regras básicas já foram descritas no Capítulo 1. Entretanto, você precisa manter algumas convenções na memória quando escrever arquivos YAML. Esta seção apresenta várias das mais proeminentes convenções. Para uma completa dissertação sobre o tópico, visite o site do YAML (http://www.yaml.org/).
Primeiro de tudo, nunca use tabulações em arquivos YAML; use espaços. Interpretadores YAML não entendem arquivos com tabulações, então, endente suas linhas com espaços (um duplo espaço branco é a convenção do symfony para endentação), como mostrado in Listing 5-1.
Listing 5-1 - Arquivos YAML Proíbem Tabulações
# Nunca use tabulações
all:
-> mail:
-> -> webmaster: webmaster@example.com
# Ao invés, use espaços em branco
all:
mail:
webmaster: webmaster@example.com
Se os seus parâmetros são strings começando ou terminando com espaços, enclose the value in single quotes. Se um parâmetro string contém caracteres especiais, também enclose o valor com aspas simples, como mostrado in Listing 5-2.
Listing 5-2 - Nonstandard Strings Should Be Enclosed in Single Quotes
error1: This field is compulsory
error2: ' This field is compulsory '
error3: 'Don''t leave this field blank' # Single quotes must be doubled
Você pode definir longas strings em múltiplas linhas e, também, strings de múltiplas linhas com os cabeçalhos especiais de strings (> e |) mais uma endentação adicional. Listing 5-3 demonstra essa convenção.
Listing 5-3 - Definindo Longas e Strings de Múltiplas Linhas
# Folded estilo, começado por >
# Cada quebra de linha é/está folded to a space
# Torna o YAML mais legível
accomplishment: >
Mark set a major league
home run record in 1998.
# Estilo literal, começado por |
# Todas as quebras de linha contam
# Endentação não aparece na string resultante
stats: |
65 Home Runs
0.278 Batting Average
Para definir um valor como um array, enclose os elementos in colchetes ou use a sintaxe expandida com dashes, como mostrado na Listing 5-4.
Listing 5-4 - Sintaxe YAML para Array
# Shorthand syntax for arrays
players: [ Mark McGwire, Sammy Sosa, Ken Griffey ]
# Expanded syntax for arrays
players:
- Mark McGwire
- Sammy Sosa
- Ken Griffey
Para definir um valor como um array associativo, or hash, enclose the elements in curly brackets and always insert a space between the key and the value in the key: value couple. You can also use the expanded syntax by adding indentation and a carriage return for every new key, as shown in Listing 5-5.
Listing 5-5 - Sintaxe YAML para Arrays Associativos
# Sintaxe Incorreta, espaços em branco estão faltando após a vírgula
mail: {webmaster:webmaster@example.com,contact:contact@example.com}
# Correct shorthand syntax for associative arrays
mail: { webmaster: webmaster@example.com, contact: contact@example.com }
# Sintaxe expandida para arrays associativos
mail:
webmaster: webmaster@example.com
contact: contact@example.com
Para atribuir um valor Booleano, use tanto on, 1, ou true para um valor positivo e off, 0, ou false para um valor negativo. Listing 5-6 mostra os possíveis valores Booleanos.
Listing 5-6 - Sintaxe YAML para valores Booleanos
true_values: [ on, 1, true ]
false_values: [ off, 0, false ]
Não hesite em adicionar comentários (começando com the hash mark, #) e espaços extras para valores para tornar seus arquivos YAML mais legíveis, como mostrada na Listing 5-7.
Listing 5-7 - YAML Comments Syntax and Value Alignment
# Esta é uma linha de comentário
mail:
webmaster: webmaster@example.com
contact: contact@example.com
admin: admin@example.com # espaços extras permitem um bom alinhamento de valores
Em alguns arquivos de configuração do symfony, você irá, às vezes, ver linhas que começamcom uma marcação hash (e, como tal, ignoradas pelos interpretadores YAML) mas parecem simples linhas de configuração. Esta é uma convenção do symfony: a configuração padrão, herdada de outros arquivos YAML localizados no núcleo do symfony, é repetida em linhas comentadas na configuração da sua aplicação, para sua informação. Se você quiser mudar o valor de tal parâmetro, você precisa descomentar a linha primeiro, como mostrado na Listing 5-8.
Listing 5-8 - Configuração Padrão é Mostrada Comentada
# Por padrão, o cache está desligado
settings:
# cache: off
# Se você quiser mudar esta configuração, descomente, primeiro, a linha
settings:
cache: on
O Symfony, às vezes, agrupa as definições de parâmetros em categorias. Todas as definições de uma determinada categoria aparecem identadas abaixo de um cabeçalho de categoria. Estruturando longas listas de pares key: value agrupando-as em categorias torna a configuração mais legível. Cabeçalhos de categorias começam com um ponto (.). Listing 5-9 mostra um exemplo de categoria.
Listing 5-9 - Cabeçalhos de categorias parecem chaves, mas começam com ponto (.)
all:
.general:
tax: 19.6
mail:
webmaster: webmaster@example.com
Neste exemplo, mail é uma chave e general é, somente, um cabeçalho de categoria. Tudo trabalha como se o cabeçalho de categoria não existisse, como mostrado na Listing 5-10. O parâmetro tax é, realmente, um filho direto da chave all.
Listing 5-10 - Cabeçalhos de Categoria Estão Lá, Somente para Tornar mais Legível o Arquivo, e são, Realmente, Ignorados.
all:
tax: 19.6
mail:
webmaster: webmaster@example.com
SIDEBAR E se você não gosta de YAML
YAML é, somente, uma interface para definir configurações a serem usadas pelo código PHP, então, a configuração definida em arquivos YAML terminam sendo transformados em PHP. Após exibir uma aplicação, verifique sua configuração em cache (em
cache/myapp/dev/config/, por exemplo). Você irá ver os arquivos PHP correspondendo a sua configuração YAML. Você irá aprender mais sobre a configuração do cache, mais tarde, neste capítulo.As boas notícias são que, se você não quiser usar arquivos YAML, you pode, ainda, fazer o que os arquivos de configuração fazem, na mão, em PHP ou via outro formato (XML, INI, e por aí vai). Através deste livro, você irá conhecer modos alternativos para definir configuraçãoes sem YAML, e você irá até aprender a substituir os manipuladores de configuração do symfony (no Capítulo 19). Se você usá-los sabiamente, estes truques o permitirão bypass os arquivos de configuração ou definir seu próprio formato de configuração.
Socorro, um arquivo YAML Matou Minha Aplicação!
Os arquivos YAML são interpretados em hashes PHP e arrays, e então os valores são usados em várias partes da aplicação para modificar o comportamento do view, do controller, ou do model. Muitas vezes, quando existe um problema em um arquivo YAML, aquele não é detectado até que o valor realmente necessite ser utilizado. Além disso, o erro ou a exceção que é lançada então, não é, habitualmente, relacionada com o arquivo de configuração YAML.
Se sua aplicação, repentinamente, parar de funcionar após a mudança na configuração, você deveria checar se não cometeu nenhum dos erros mais comuns de um editor desatento de YAML:
Você esqueceu um espaço em branco entre a chave e seu valor:
key1:value1 # Um espaço faltando depois do :Chaves em uma seqüência não estão identadas da mesma forma:
all: key1: value1 key2: value2 # Indentation is not the same as the other sequence members key3: value3Existem um caractere YAML reservado em uma chave ou valor, sem delimitadores de strings:
message: tell him: go way # :, [, ], { e } são reservados no YAML message: 'tell him: go way' # Sintaxe corretaVocê está modificando uma linha comentada:
# key: value # Nunca fará efeito por causa do #Você define valores de uma mesma chave duas vezes num mesmo nível:
key1: value1 key2: value2 key1: value3 # key1 é definida novamente, o valor é o último definidoVocê acha que a configuração aceita um tipo especial, enquanto é sempre uma string, até que você o converta:
income: 12,345 # Até que você o converta, isto ainda é uma string
Vista Geral dos Arquivos de Configuração
A configuração é distribuída em arquivos, por assunto. Os arquivos contêm definições de parâmetros, ou ajustes. Alguns destes parâmetros podem ser sobrescritos em vários níveis (projeto, aplicação, e módulo); alguns sao específicos de um certo nível. Os próximos capítulos tratarão de arquivos de configuração relacionados ao seus tópicos principais, e o Capítulo 19 tratará da configuração avançada.
Configuração do Projeto
Por padrão, existem poucos arquivos de configuração do projeto. Aqui estão os arquivos que podem ser encontrados no diretório myproject/config/:
-
config.php: Este é o primeiro arquivo executado por uma requisição ou comando. Ele contém a rota para os arquivos do framework, and you can change it to use a different installation. If you add somedefinestatements at the end of this file, the constants will be accessible from every application of the project. See Chapter 19 for advanced usage of this file. -
databases.yml: This is where you define the access and connection settings to the database (host, login, password, database name, and so on). Chapter 8 will tell you more about it. It can also be overridden at the application level. -
properties.ini: This file holds a few parameters used by the command line tool, including the project name and the connection settings for distant servers. See Chapter 16 for an overview of the features using this file. -
rsync_exclude.txt: This file specifies which directories must be excluded from the synchronization between servers. It is discussed in Chapter 16. -
schema.ymlandpropel.ini: These are data access configuration files used by Propel (symfony's ORM layer). They are used to make the Propel libraries work with the symfony classes and the data of your project.schema.ymlcontains a representation of the project's relational data model.propel.iniis automatically generated, so you probably do not need to modify it. If you don't use Propel, these files are not needed. Chapter 8 will tell you more about their use.
These files are mostly used by external components or by the command line, or they need to be processed even before any YAML parsing program can be loaded by the framework. That's why some of them don't use the YAML format.
Application Configuration
The main part of the configuration is the application configuration. It is defined in the front controller (in the web/ directory) for the main constants, in YAML files located in the application config/ directory, in i18n/ directories for the internationalization files, and in the framework files for invisible--although useful--additional application configuration.
Front Controller Configuration
The very first application configuration is actually found in the front controller; that is the very first script executed by a request. Take a look at the default web/index.php in Listing 5-11.
Listing 5-11 - The Default Production Front Controller
[php]
<?php
define('SF_ROOT_DIR', dirname(__FILE__).'/..');
define('SF_APP', 'myapp');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG', true);
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
sfContext::getInstance()->getController()->dispatch();
After defining the name of the application (myapp) and the environment (prod), the general configuration file is called before the dispatching. So a few useful constants are defined here:
-
SF_ROOT_DIR: Project root directory (normally, should remain at its default value, unless you change the file structure). -
SF_APP: Application name in the project. Necessary to compute file paths. -
SF_ENVIRONMENT: Environment name (prod,dev, or any other project-specific environment that you define). Will determine which configuration settings are to be used. Environments are explained later in this chapter. -
SF_DEBUG: Activation of the debug mode (see Chapter 16 for details).
If you want to change one of these values, you probably need an additional front controller. The next chapter will tell you more about front controllers and how to create a new one.
SIDEBAR The root directory can be anywhere
Only the files and scripts located under the web root (the
web/directory in a symfony project) are available from the outside. The front controller scripts, images, style sheets, and JavaScript files are public. All the other files must be outside the server web root--that means they can be anywhere else.The non-public files of a project are accessed by the front controller from the SF_ROOT_DIR path. Classically, the root directory is one level up the
web/directory. But you can choose a completely different structure. Imagine that your main directory structure is made of two directories, one public and one private:symfony/ # Private area apps/ batch/ cache/ ... www/ # Public area images/ css/ js/ index.phpIn this case, the root directory is the
symfony/directory. So theindex.phpfront controller simply needs to define theSF_ROOT_DIRas follows for the application to work:define('SF_ROOT_DIR', dirname(__FILE__).'/../symfony');
Chapter 19 will give you more information about how to tweak symfony to make it work on a specific directory structure.
Main Application Configuration
The main application configuration is stored in files located in the myproject/apps/myapp/config/ directory:
-
app.yml: This file should contain the application-specific configuration; that is, global variables defining business or applicative logic specific to an application, which don't need to be stored in a database. Tax rates, shipping fares, and e-mail addresses are often stored in this file. It is empty by default. -
config.php: This file bootstraps the application, which means that it does all the very basic initializations to allow the application to start. This is where you can customize your directory structure or add application-specific constants (Chapter 19 provides more details). It starts by including the project'sconfig.php. -
factories.yml: Symfony defines its own class to handle the view, the request, the response, the session, and so on. If you want to use your own classes instead, this is where you can specify them. Chapter 17 provides more information. -
filters.yml: Filters are portions of code executed for every request. This file is where you define which filters are to be processed, and it can be overridden for each module. Chapter 6 discusses filters in more detail. -
logging.yml: This file defines which level of detail must be recorded in the logs, to help you manage and debug your application. The use of this configuration is explained in Chapter 16. -
routing.yml: The routing rules, which allow transforming unreadable and unbookmarkable URLs into "smart" and explicit ones, are stored in this file. For new applications, a few default rules exist. Chapter 9 is all about links and routing. -
settings.yml: The main settings of a symfony application are defined in this file. This is where you specify if your application has internationalization, its default language, the request timeout and whether caching is turned on. With a one-line change in this file, you can shut down the application so you can perform maintenance or upgrade one of its components. The common settings and their use are described in Chapter 19. -
view.yml: The structure of the default view (name of the layout, title, and meta tags; default style sheets and JavaScript files to be included; default content-type, and so on) is set in this file. It also defines the default value of the meta and title tags. Chapter 7 will tell you more about this file. These settings can be overridden for each module.
Internationalization Configuration
Internationalized applications can display pages in several languages. This requires specific configuration. There are two configuration places for internationalization:
-
i18n.ymlof the applicationconfig/directory: This file defines general translation settings, such as the default culture for the translation, whether the translations come from files or a database, and their format. -
Translation files in the application
i18n/directory: These are basically dictionaries, giving a translation for each of the phrases used in the application templates so that the pages show translated text when the user switches language.
Note that the activation of the i18n features is set in the settings.yml file. You will find more information about these features in Chapter 13.
Additional Application Configuration
A second set of configuration files is in the symfony installation directory (in $sf_symfony_ data_dir/config/) and doesn't appear in the configuration directory of your applications. The settings defined there are defaults that seldom need to be modified, or that are global to all projects. However, if you need to modify them, just create an empty file with the same name in your myproject/apps/myapp/config/ directory, and override the settings you want to change. The settings defined in an application always have precedence over the ones defined in the framework. The following are the configuration files in the symfony installation config/ directory:
-
autoload.yml: This file contains the settings of the autoloading feature. This feature exempts you from requiring custom classes in your code if they are located in specific directories. It is described in detail in Chapter 19. -
constants.php: This file contains the default application file structure. To override the settings of this file, use the applicationconfig.php, as explained in Chapter 19. -
core_compile.ymlandbootstrap_compile.yml: These are lists of classes to be included to start an application (inbootstrap_compile.yml) and to process a request (incore_compile.yml). These classes are actually concatenated into an optimized PHP file without comments, which will accelerate the execution by minimizing the file access operations (one file is loaded instead of more than forty for each request). This is especially useful if you don't use a PHP accelerator. Optimization techniques are described in Chapter 18. -
config_handlers.yml: This is where you can add or modify the handlers used to process each configuration file. Chapter 19 provides more details. -
php.yml: This file checks that the variables of thephp.inifile are properly defined and allows you to override them, if necessary. Check Chapter 19 for details.
Module Configuration
By default, a module has no specific configuration. But, if required, you can override some application-level settings for a given module. For instance, you might do this to change the HTML description of all the actions of a module, or to include a specific JavaScript file. You can also choose to add new parameters restricted to a specific module to preserve encapsulation.
As you may have guessed, module configuration files must be located in a myproject/apps/myapp/modules/mymodule/config/ directory. These files are as follows:
-
generator.yml: For modules generated according to a database table (scaffoldings and administrations), this file defines how the interface displays rows and fields, and which interactions are proposed to the user (filters, sorting, buttons, and so on). Chapter 14 will tell you more about it. -
module.yml: This file contains custom parameters specific to a module (equivalent to theapp.yml, but at the module level) and action configuration. Chapter 6 provides more details. -
security.yml: This file sets access restrictions for actions. This is where you specify that a page can be viewed only by registered users or by a subset of registered users with special permissions. Chapter 6 will tell you more about it. -
view.yml: This file contains configuration for the views of one or all of the actions of a module. It overrides the applicationview.ymland is described in Chapter 7. -
Data validation files: Although located in the
validate/directory instead of theconfig/one, the YAML data validation files, used to control the data entered in forms, are also module configuration files. You will learn how to use them in Chapter 10.
Most module configuration files offer the ability to define parameters for all the views or all the actions of a module, or for a subset of them.
SIDEBAR Too many files?
You might be overwhelmed by the number of configuration files present in the application. But please keep the following in mind:
Most of the time, you don't need to change the configuration, since the default conventions match the most common requirements. Each configuration file is related to a particular feature, and the next chapters will detail their use one by one. When you focus on a single file, you can see clearly what it does and how it is organized. For professional web development, the default configuration is often not completely adapted. The configuration files allow for an easy modification of the symfony mechanisms without code. Imagine the amount of PHP code necessary to achieve the same amount of control. If all the configuration were located in one file, not only would the file be completely unreadable, but you could not redefine configuration at several levels (see the "Configuration Cascade" section later in this chapter).
The configuration system is one of the great strengths of symfony, because it makes symfony usable for almost every kind of web application, and not only for the ones for which the framework was originally designed.
Environments
During the course of application development, you will probably need to keep several sets of configuration in parallel. For instance, you will need to have the connection settings for your tests database available during development, and the ones for your real data available for production. To answer the need of concurrent configurations, symfony offers different environments.
What Is an Environment?
An application can run in various environments. The different environments share the same PHP code (apart from the front controller), but can have completely different configurations. For each application, symfony provides three default environments: production (prod), test (test), and development (dev). You're also free to add as many custom environments as you wish.
So basically, environments and configuration are synonyms. For instance, a test environment will log alerts and errors, while a prod environment will only log errors. Cache acceleration is often deactivated in the dev environment, but activated in the test and prod environments. The dev and test environments may need test data, stored in a database distinct from the one used in the production environment. So the database configuration will be different between the two environments. All environments can live together on the same machine, although a production server generally contains only the prod environment.
In the dev environment, the logging and debugging settings are all enabled, since maintenance is more important than performance. On the contrary, the prod environment has settings optimized for performance by default, so the production configuration turns off many features. A good rule of thumb is to navigate in the development environment until you are satisfied with the feature you are working on, and then switch to the production environment to check its speed.
The test environment differs from the dev and prod environment in other ways. You interact with this environment solely through the command line for the purpose of functional testing and batch scripting. Consequently, the test environment is close to the production one, but it is not accessed through a web browser. It simulates the use of cookies and other HTTP specific components.
To change the environment in which you're browsing your application, just change the front controller. Until now, you have seen only the development environment, since the URLs used in the example called the development front controller:
http://localhost/myapp_dev.php/mymodule/index
However, if you want to see how the application reacts in production, call the production front controller instead:
http://localhost/index.php/mymodule/index
If your web server has mod_rewrite enabled, you can even use the custom symfony rewriting rules, written in web/.htaccess. They define the production front controller as the default execution script and allow for URLs like this:
http://localhost/mymodule/index
SIDEBAR Environments and servers
Don't mix up the notions of environment and server. In symfony, different environments are different configurations, and correspond to a front controller (the script that executes the request). Different servers correspond to different domain names in the URL.
http://localhost/myapp_dev.php/mymodule/index _________ _____________ server environmentUsually, developers work on applications in a development server, disconnected from the Internet and where all the server and PHP configuration can be changed at will. When the time comes for releasing the application to production, the application files are transferred to the production server and made accessible to the end users.
This means that many environments are available on each server. For instance, you can run in the production environment even on your development server. However, most of the time, only the production environment should be accessible in the production server, to avoid public visibility of server configuration and security risks.
To add a new environment, you don't need to create a directory or to use the symfony CLI. Simply create a new front controller and change the environment name definition in it. This environment inherits all the default configuration plus the settings that are common to all environments. The next chapter will show you how to do this.
Configuration Cascade
The same setting can be defined more than once, in different places. For instance, you may want to set the mime-type of your pages to text/html for all of the application, except for the pages of an rss module, which will need a text/xml mime-type. Symfony gives you the ability to write the first setting in myapp/config/view.yml and the second in myapp/modules/rss/config/view.yml. The configuration system knows that a setting defined at the module level must override a setting defined at the application level.
In fact, there are several configuration levels in symfony:
-
Granularity levels:
- The default configuration located in the framework
-
The global configuration for the whole project (in
myproject/config/) -
The local configuration for an application of the project (in
myproject/apps/myapp/config/) -
The local configuration restricted to a module (in
myproject/apps/myapp/modules/mymodule/config/)
-
Environment levels:
- Specific to one environment
- For all environments
Of all the properties that can be customized, many are environment-dependent. Consequently, many YAML configuration files are divided by environment, plus a tail section for all environments. The result is that typical symfony configuration looks like Listing 5-12.
Listing 5-12 - The Structure of Symfony Configuration Files
# Production environment settings
prod:
...
# Development environment settings
dev:
...
# Test environment settings
test:
...
# Custom environment settings
myenv:
...
# Settings for all environments
all:
...
In addition, the framework itself defines default values in files that are not located in the project tree structure, but in the $sf_symfony_data_dir/config/ directory of your symfony installation. The default configuration is set in these files as shown in Listing 5-13. These settings are inherited by all applications.
Listing 5-13 - The Default Configuration, in $sf_symfony_data_dir/config/settings.yml
# Default settings:
default:
default_module: default
default_action: index
...
These default definitions are repeated in the project, application, and module configuration files as comments, as shown in Listing 5-14, so that you know that some parameters are defined by default and that they can be modified.
Listing 5-14 - The Default Configuration, Repeated for Information, in myapp/config/settings.yml
#all:
# default_module: default
# default_action: index
...
This means that a property can be defined several times, and the actual value results from a definition cascade. A parameter definition in a named environment has precedence over the same parameter definition for all environments, which has precedence over a definition in the default configuration. A parameter definition at the module level has precedence over the same parameter definition at the application level, which has precedence over a definition at the project level. This can be wrapped up in the following priority list:
- Module
- Application
- Project
- Specific environment
- All environments
- Default
The Configuration Cache
Parsing YAML and dealing with the configuration cascade at runtime represent a significant overhead for each request. Symfony has a built-in configuration cache mechanism designed to speed up requests.
The configuration files, whatever their format, are processed by some special classes, called handlers, that transform them into fast-processing PHP code. In the development environment, the handlers check the configuration for changes at each request, to promote interactivity. They parse the recently modified files so that you can see a change in a YAML file immediately. But in the production environment, the processing occurs once during the first request, and then the processed PHP code is stored in the cache for subsequent requests. The performance is guaranteed, since every request in production will just execute some well-optimized PHP code.
For instance, if the app.yml file contains this:
all: # Setting for all environments
mail:
webmaster: webmaster@example.com
then the file config_app.yml.php, located in the cache/ folder of your project, will contain this:
[php]
<?php
sfConfig::add(array(
'app_mail_webmaster' => 'webmaster@example.com',
));
As a consequence, most of the time, the YAML files aren't even parsed by the framework, which relies on the configuration cache instead. However, in the development environment, symfony will systematically compare the dates of modification of the YAML files and the cached files, and reprocess only the ones that have changed since the previous request.
This presents a major advantage over many PHP frameworks, where configuration files are compiled at every request, even in production. Unlike Java, PHP doesn't share an execution context between requests. For other PHP frameworks, keeping the flexibility of XML configuration files requires a major performance hit to process all the configuration at every request. This is not the case in symfony. Thanks to the cache system, the overhead caused by configuration is very low.
There is an important consequence of this mechanism. If you change the configuration in the production environment, you need to force the reparsing of all the configuration files for your modification to be taken into account. For that, you just need to clear the cache, either by deleting the content of the cache/ directory or, more easily, by calling the clear-cache symfony task:
> symfony clear-cache
Accessing the Configuration from Code
All the configuration files are eventually transformed into PHP, and many of the settings they contain are automatically used by the framework, without further intervention. However, you sometimes need to access some of the settings defined in the configuration files from your code (in actions, templates, custom classes, and so on). The settings defined in settings.yml, app.yml, module.yml, logging.yml, and i18n.yml are available through a special class called sfConfig.
The sfConfig Class
You can access settings from within the application code through the sfConfig class. It is a registry for configuration parameters, with a simple getter class method, accessible from every part of the code:
[php]
// Retrieve a setting
parameter = sfConfig::get('param_name', $default_value);
Note that you can also define, or override, a setting from within PHP code:
[php]
// Define a setting
sfConfig::set('param_name', $value);
The parameter name is the concatenation of several elements, separated by underscores, in this order:
-
A prefix related to the configuration file name (
sf_forsettings.yml,app_forapp.yml,mod_formodule.yml,sf_i18n_fori18n.yml, andsf_logging_forlogging.yml) - The parent keys (if defined), in lowercase
- The name of the key, in lowercase
The environment is not included, since your PHP code will have access only to the values defined for the environment in which it's executed.
For instance, if you need to access the values defined in the app.yml file shown in Listing 5-15, you will need the code shown in Listing 5-16.
Listing 5-15 - Sample app.yml Configuration
all:
version: 1.5
.general:
tax: 19.6
default_user:
name: John Doe
mail:
webmaster: webmaster@example.com
contact: contact@example.com
dev:
mail:
webmaster: dummy@example.com
contact: dummy@example.com
Listing 5-16 - Accessing Configuration Settings in PHP in the dev Environment
[php]
echo sfConfig::get('app_version');
=> '1.5'
echo sfConfig::get('app_tax'); // Remember that category headers are ignored
=> '19.6'
echo sfConfig::get('app_default_user_name');
=> 'John Doe'
echo sfConfig::get('app_mail_webmaster');
=> 'dummy@example.com'
echo sfConfig::get('app_mail_contact');
=> 'dummy@example.com'
So symfony configuration settings have all the advantages of PHP constants, but without the disadvantages, since the value can be changed.
On that account, the settings.yml file, where you can set the framework settings for an application, is the equivalent to a list of sfConfig::set() calls. Listing 5-17 is interpreted as shown in Listing 5-18.
Listing 5-17 - Extract of settings.yml
all:
.settings:
available: on
path_info_array: SERVER
path_info_key: PATH_INFO
url_format: PATH
Listing 5-18 - What Symfony Does When Parsing settings.yml
[php]
sfConfig::add(array(
'sf_available' => true,
'sf_path_info_array' => 'SERVER',
'sf_path_info_key' => 'PATH_INFO',
'sf_url_format' => 'PATH',
));
Refer to Chapter 19 for the meanings of the settings found in the settings.yml file.
Custom Application Settings and app.yml
Most of the settings related to the features of an application should be stored in the app.yml file, located in the myproject/apps/myapp/config/ directory. This file is environment-dependent and empty by default. Put in every setting that you want to be easily changed, and use the sfConfig class to access these settings from your code. Listing 5-19 shows an example.
Listing 5-19 - Sample app.yml to Define Credit Card Operators Accepted for a Given Site
all:
creditcards:
fake: off
visa: on
americanexpress: on
dev:
creditcards:
fake: on
To know if the fake credit cards are accepted in the current environment, get the value of:
[php]
sfConfig::get('app_creditcards_fake');
TIP Each time you are tempted to define a constant or a setting in one of your scripts, think about if it would be better located in the app.yml file. This is a very convenient place to store all application settings.
When your need for custom parameters becomes hard to handle with the app.yml syntax, you may need to define a syntax of your own. In that case, you can store the configuration in a new file, interpreted by a new configuration handler. Refer to Chapter 19 for more information about configuration handlers.
Tips for Getting More from Configuration Files
There are a few last tricks to learn before writing your own YAML files. They will allow you to avoid configuration duplication and to deal with your own YAML formats.
Using Constants in YAML Configuration Files
Some configuration settings rely on the value of other settings. To avoid setting the same value twice, symfony supports constants in YAML files. On encountering a setting name (one that can be accessed by sfConfig::get()) in capital letters enclosed in % signs, the configuration handlers replace them with their current value. See Listing 5-20 for an example.
Listing 5-20 - Using Constants in YAML Files, Example from autoload.yml
autoload:
symfony:
name: symfony
path: %SF_SYMFONY_LIB_DIR%
recursive: on
exclude: [vendor]
The path parameter will take the value returned by sfConfig::get('sf_symfony_lib_dir'). If you want one configuration file to rely on another, you need to make sure that the file you rely on is already parsed (look in the symfony source to find out the order in which the configuration files are parsed). app.yml is one of the last files parsed, so you may rely on others in it.
Using Scriptable Configuration
It may happen that your configuration relies on external parameters (such as a database or another configuration file). To deal with these particular cases, the symfony configuration files are parsed as PHP files before being passed to the YAML parser. It means that you can put PHP code in YAML files, as in Listing 5-21.
Listing 5-21 - YAML Files Can Contain PHP
all:
translation:
format: <?php echo sfConfig::get('sf_i18n') == true ? 'xliff' : 'none' ?>
But be aware that the configuration is parsed very early in the life of a request, so you will not have any symfony built-in methods or functions to help you.
CAUTION In the production environment, the configuration is cached, so the configuration files are parsed (and executed) only once after the cache is cleared.
Browsing Your Own YAML File
Whenever you want to read a YAML file directly, you can use the sfYaml class. It is a YAML parser that can turn a YAML file into a PHP associative array. Listing 5-22 presents a sample YAML file, and Listing 5-23 shows you how to parse it.
Listing 5-22 - Sample test.yml File
house:
family:
name: Doe
parents: [John, Jane]
children: [Paul, Mark, Simone]
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345
Listing 5-23 - Using the sfYaml Class to Turn a YAML File into an Associative Array
[php]
$test = sfYaml::load('/path/to/test.yml');
print_r($test);
Array(
[house] => Array(
[family] => Array(
[name] => Doe
[parents] => Array(
[0] => John
[1] => Jane
)
[children] => Array(
[0] => Paul
[1] => Mark
[2] => Simone
)
)
[address] => Array(
[number] => 34
[street] => Main Street
[city] => Nowheretown
[zipcode] => 12345
)
)
)
Summary
The symfony configuration system uses the YAML language to be simple and readable. The ability to deal with multiple environments and to set parameters through a definition cascade offers versatility to the developer. Some of the configuration can be accessed from within the code via the sfConfig object, especially the application settings stored in the app.yml file.
Yes, symfony does have a lot of configuration files, but this approach makes it more adaptable. Remember that you don't need to bother with them unless your application requires a high level of customization.