Symfony2:根据域加载配置文件

时间:2016-02-27 10:44:46

标签: php symfony

目前我们正在为德国经营一家网店。现在,我们还希望在英国提供具有自己域名的产品。

根据域的不同,它们应该加载几个设置:

  • Google Analytics ID
  • 付款API秘密/密钥,......
  • 货币
  • 语言
  • 管理员邮件
  • 跟踪像素(FB)
  • 等......

在之前的项目中,我们通过将此设置放在数据库的域表中来解决它。但我认为整个支付服务信息和密钥和和......并不是最好的解决方案。

4 个答案:

答案 0 :(得分:5)

您可以编写一个包Extension class来加载您的配置,具体取决于主机。

捆绑扩展:

// src/AcmeBundle/DependencyInjection/AcmeExtension.php

<?php

namespace AcmeBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class AcmeExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);
        $rootdir = $container->getParameter('kernel.root_dir');

        // Load the bundle's services.yml
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');

        // Load parameters depending on current host
        $paramLoader = new Loader\YamlFileLoader($container, new FileLocator($rootdir.'/config')); // Access the root config directory
        $parameters = sprintf('parameters_%s.yml', $container->getParameter('router.request_context.host'));

        if (!file_exists($rootdir.'/config/'.$parameters)) {
            $parameters = 'parameters.yml'; // Default
        }

        $paramLoader->load($parameters); 
    }
}

相应的捆绑配置:

// src/AcmeBundle/DependencyInjection/Configuration.php

<?php

namespace AcmeBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('acme');

        return $treeBuilder;
    }
}

像这样,您可以创建一个名为parameters_localhost.yml的文件,它将自动加载。 如果找不到该文件,将使用默认的parameters.yml

您可以根据所需的每个参数应用此逻辑(例如_locale用于您的翻译)。

希望得到这个帮助。

答案 1 :(得分:2)

如果您的每个商店都是不同的应用安装,那么为什么不将您的配置保存在parameters.yml文件中?您还可以查看ParameterHandler脚本,它将帮助您管理所有参数。

如果你使用单一代码库,也许你应该完全重新考虑你的实现,因为例如,如果将来你需要从英国商店独立于DE商店等产品制作产品呢? (有更多这样的用例)

我认为您当前的解决方案是一个短期解决方案,如果您计划扩展到不同的国家/地区,您应该投入一些时间来寻求长期解决方案。当然,这完全取决于您的要求和用例。

一个选项是将您的应用程序拆分为多个渠道,其中每个渠道将成为英国和德国的商店等等。

然后,您还可以使用不同的设置,产品,付款,每个频道的货币等。

您可以在GitHub上查看Sylius项目。他们开发了这个不错的ChannelBundle,您可以看到它是如何工作的。

答案 2 :(得分:1)

我知道已经选择了最佳答案,但我找到了parameters.php的其他方法:

<?php

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader;

$hostArray = explode('.', $_SERVER['HTTP_HOST']);
$hostArrayCount = count($hostArray);
$host = $hostArray[$hostArrayCount - 2] . '.' . $hostArray[$hostArrayCount - 1];
$hostDir = $container->getParameter('kernel.root_dir') . '/config/domains/';
$parameters = sprintf('%s.yml', $host);

if (file_exists($hostDir . $parameters)) {
    $hostParamLoader = new Loader\YamlFileLoader($container, new FileLocator($hostDir));
    $hostParamLoader->load($parameters);
}

并在config.yml之后:

imports:
    - { resource: parameters.yml }

添加字符串:

    - { resource: parameters.php }

答案 3 :(得分:0)

您可以在(apache?)配置中使用SetEnv作为数据库变量和每个域的其他变量(ref

# /etc/apache2/sites-available/one-domain.conf
<VirtualHost *:80>
    ServerName      onedomain.uk
    DocumentRoot    "/path/to/onedomain/web"
    DirectoryIndex  index.php index.html
    SetEnv          SYMFONY__GOOGLE__ANALYTICSID mygoogleanalyticsid
    SetEnv          SYMFONY__PAYMENT__APISECRET mysecret
    # ...
    <Directory "/path/to/onedomain/web">
        AllowOverride All
        Allow from All
    </Directory>
</VirtualHost>

然后使用常见的parameters.yml设置变量:

# app/config/parameters.yml
parameters:
    analytics_id: "google.analyticsid"
    payment_secret: "payment.apisecret"
    # ...

它们都有自己的数据库设置和您想为每个设置的任何变量。

您还可以通过设置标识每个域的变量(ref)来分隔缓存和日志文件夹:

# app/AppKernel.php
    public function getCacheDir()
    {
        if(getenv("SYMFONY__DOMAIN__NAME")){
            return dirname(__DIR__).'/var/cache/'.$this->getEnvironment().'/'.getenv("SYMFONY__DOMAIN__NAME");
        } else {
            return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
        }
    }

    public function getLogDir()
    {
        if(getenv("SYMFONY__DOMAIN__NAME")){
            return dirname(__DIR__).'/var/logs/'.getenv("SYMFONY__DOMAIN__NAME");
        } else {
            return dirname(__DIR__).'/var/logs/';
        }
    }

如果您将会话存储在文件中,您也可以对sessions文件夹执行此操作:

# app/config/config.yml
framework:
    # ...
    session:
        handler_id:  session.handler.native_file
        save_path:   "%kernel.root_dir%/../var/sessions/%kernel.environment%/%domain.name%"