发布于 2015-08-27 16:45:11 | 105 次阅读 | 评论: 0 | 来源: 网络整理
The default Symfony Standard Edition defines three
execution environments called
dev
, prod
and test
. An environment simply represents a way to
execute the same codebase with different configurations.
In order to select the configuration file to load for each environment, Symfony
executes the registerContainerConfiguration()
method of the AppKernel
class:
// app/AppKernel.php
use SymfonyComponentHttpKernelKernel;
use SymfonyComponentConfigLoaderLoaderInterface;
class AppKernel extends Kernel
{
// ...
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
}
This method loads the app/config/config_dev.yml
file for the dev
environment and so on. In turn, this file loads the common configuration file
located at app/config/config.yml
. Therefore, the configuration files of the
default Symfony Standard Edition follow this structure:
<your-project>/
├─ app/
│ └─ config/
│ ├─ config.yml
│ ├─ config_dev.yml
│ ├─ config_prod.yml
│ ├─ config_test.yml
│ ├─ parameters.yml
│ ├─ parameters.yml.dist
│ ├─ routing.yml
│ ├─ routing_dev.yml
│ └─ security.yml
├─ src/
├─ vendor/
└─ web/
This default structure was chosen for its simplicity — one file per environment.
But as any other Symfony feature, you can customize it to better suit your needs.
The following sections explain different ways to organize your configuration
files. In order to simplify the examples, only the dev
and prod
environments are taken into account.
Instead of suffixing the files with _dev
and _prod
, this technique
groups all the related configuration files under a directory with the same
name as the environment:
<your-project>/
├─ app/
│ └─ config/
│ ├─ common/
│ │ ├─ config.yml
│ │ ├─ parameters.yml
│ │ ├─ routing.yml
│ │ └─ security.yml
│ ├─ dev/
│ │ ├─ config.yml
│ │ ├─ parameters.yml
│ │ ├─ routing.yml
│ │ └─ security.yml
│ └─ prod/
│ ├─ config.yml
│ ├─ parameters.yml
│ ├─ routing.yml
│ └─ security.yml
├─ src/
├─ vendor/
└─ web/
To make this work, change the code of the
registerContainerConfiguration()
method:
// app/AppKernel.php
use SymfonyComponentHttpKernelKernel;
use SymfonyComponentConfigLoaderLoaderInterface;
class AppKernel extends Kernel
{
// ...
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/'.$this->getEnvironment().'/config.yml');
}
}
Then, make sure that each config.yml
file loads the rest of the configuration
files, including the common files. For instance, this would be the imports
needed for the app/config/dev/config.yml
file:
# app/config/dev/config.yml
imports:
- { resource: '../common/config.yml' }
- { resource: 'parameters.yml' }
- { resource: 'security.yml' }
# ...
<!-- app/config/dev/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<imports>
<import resource="../common/config.xml" />
<import resource="parameters.xml" />
<import resource="security.xml" />
</imports>
<!-- ... -->
</container>
// app/config/dev/config.php
$loader->import('../common/config.php');
$loader->import('parameters.php');
$loader->import('security.php');
// ...
注解
Due to the way in which parameters are resolved, you cannot use them to build paths in imports dynamically. This means that something like the following doesn’t work:
# app/config/config.yml
imports:
- { resource: "%kernel.root_dir%/parameters.yml" }
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<imports>
<import resource="%kernel.root_dir%/parameters.yml" />
</imports>
</container>
// app/config/config.php
$loader->import('%kernel.root_dir%/parameters.yml');
A different organization strategy may be needed for complex applications with large configuration files. For instance, you could create one file per bundle and several files to define all application services:
<your-project>/
├─ app/
│ └─ config/
│ ├─ bundles/
│ │ ├─ bundle1.yml
│ │ ├─ bundle2.yml
│ │ ├─ ...
│ │ └─ bundleN.yml
│ ├─ environments/
│ │ ├─ common.yml
│ │ ├─ dev.yml
│ │ └─ prod.yml
│ ├─ routing/
│ │ ├─ common.yml
│ │ ├─ dev.yml
│ │ └─ prod.yml
│ └─ services/
│ ├─ frontend.yml
│ ├─ backend.yml
│ ├─ ...
│ └─ security.yml
├─ src/
├─ vendor/
└─ web/
Again, change the code of the registerContainerConfiguration()
method to
make Symfony aware of the new file organization:
// app/AppKernel.php
use SymfonyComponentHttpKernelKernel;
use SymfonyComponentConfigLoaderLoaderInterface;
class AppKernel extends Kernel
{
// ...
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/environments/'.$this->getEnvironment().'.yml');
}
}
Following the same technique explained in the previous section, make sure to
import the appropriate configuration files from each main file (common.yml
,
dev.yml
and prod.yml
).
Symfony loads configuration files using the Config component, which provides some advanced features.
Configuration files can import files defined with any other built-in configuration
format (.yml
, .xml
, .php
, .ini
):
# app/config/config.yml
imports:
- { resource: 'parameters.yml' }
- { resource: 'services.xml' }
- { resource: 'security.yml' }
- { resource: 'legacy.php' }
# ...
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<imports>
<import resource="parameters.yml" />
<import resource="services.xml" />
<import resource="security.yml" />
<import resource="legacy.php" />
</imports>
<!-- ... -->
</container>
// app/config/config.php
$loader->import('parameters.yml');
$loader->import('services.xml');
$loader->import('security.yml');
$loader->import('legacy.php');
// ...
警告
The IniFileLoader
parses the file contents using the
parse_ini_file
function. Therefore, you can only set
parameters to string values. Use one of the other loaders if you want
to use other data types (e.g. boolean, integer, etc.).
If you use any other configuration format, you have to define your own loader
class extending it from FileLoader
.
When the configuration values are dynamic, you can use the PHP configuration
file to execute your own logic. In addition, you can define your own services
to load configurations from databases or web services.
Some system administrators may prefer to store sensitive parameters in files
outside the project directory. Imagine that the database credentials for your
website are stored in the /etc/sites/mysite.com/parameters.yml
file. Loading
this file is as simple as indicating the full file path when importing it from
any other configuration file:
# app/config/config.yml
imports:
- { resource: 'parameters.yml' }
- { resource: '/etc/sites/mysite.com/parameters.yml' }
# ...
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<imports>
<import resource="parameters.yml" />
<import resource="/etc/sites/mysite.com/parameters.yml" />
</imports>
<!-- ... -->
</container>
// app/config/config.php
$loader->import('parameters.yml');
$loader->import('/etc/sites/mysite.com/parameters.yml');
// ...
Most of the time, local developers won’t have the same files that exist on the
production servers. For that reason, the Config component provides the
ignore_errors
option to silently discard errors when the loaded file
doesn’t exist:
# app/config/config.yml
imports:
- { resource: 'parameters.yml' }
- { resource: '/etc/sites/mysite.com/parameters.yml', ignore_errors: true }
# ...
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<imports>
<import resource="parameters.yml" />
<import resource="/etc/sites/mysite.com/parameters.yml" ignore-errors="true" />
</imports>
<!-- ... -->
</container>
// app/config/config.php
$loader->import('parameters.yml');
$loader->import('/etc/sites/mysite.com/parameters.yml', null, true);
// ...
As you’ve seen, there are lots of ways to organize your configuration files. You can choose one of these or even create your own custom way of organizing the files. Don’t feel limited by the Standard Edition that comes with Symfony. For even more customization, see “如何重载Symfony默认的目录结构”.