如何根据URL注入特定的参数?

时间:2017-05-15 09:06:02

标签: php symfony

开发Symfony 3应用程序,我需要根据URL拥有一个多网站。 这是我的parameters.yml文件:

...
dbname_cda: my-website-cda
dbname_pts: my-website-pts
dbname_vis: my-website-vis
...

这是config.yml

doctrine:
    dbal:
        default_connection: my-website
        connections:
            my-website:
                driver:   pdo_mysql
                host:     "%dbhost%"
                port:     "%dbport%"
                dbname:   "%_______%"
                user:     "%dbuser%"
                password: "%dbpassword%"
                charset:  UTF8

https://my-website.com/cda会注入参数dbname_cda

https://my-website.com/pts会注入参数dbname_pts

https://my-website.com/vis会注入参数dbname_vis

实际上,除了根据网址从不同数据库加载数据外,它是同一个网站。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这是一种解决问题的方法,考虑到您无法动态注入变量这一事实,因为这些配置变量是在Symfony&#34;编译时&#34;。< / p>

首先在app/config/config.yml中声明您的所有连接(我只接受您的cdapts连接):

doctrine:
    dbal:
        default_connection: cda
        connections:
            cda:
                driver: pdo_mysql
                host: '%database_host%'
                port: '%database_port%'
                dbname: '%database_cda_name%'
                user: '%database_user%'
                password: '%database_password%'
                charset: UTF8
            pts:
                driver: pdo_mysql
                host: '%database_host%'
                port: '%database_port%'
                dbname: '%database_pts_name%'
                user: '%database_user%'
                password: '%database_password%'
                charset: UTF8

    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: cda
        entity_managers:
            cda:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                connection: cda
                mappings:
                    AppBundle:  ~
            pts:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                connection: pts
                mappings:
                    AppBundle: ~

然后,在doctrine中声明您自己的app/config/services.yml服务版本。该版本将取代Symfony定义的版本。

services:
    # ...

    doctrine_url_switcher:
        class: AppBundle\Doctrine\Registry
        decorates: doctrine
        arguments:
            - '@doctrine_url_switcher.inner' # Original Doctrine service
            - '@request_stack'
        public: false

我在这里使用Symfony的service decoration机制来定义doctrine服务的新版本。

现在,定义AppBundle\Doctrine\Registry类,它扩展了Symfony的类,并在请求默认实体管理器或连接时使用RequestStack

<?php

namespace AppBundle\Doctrine;

use Doctrine\Bundle\DoctrineBundle\Registry as BaseRegistry;
use Symfony\Component\HttpFoundation\RequestStack;

class Registry extends BaseRegistry
{
    private $requestStack;

    public function __construct(BaseRegistry $baseRegistry, RequestStack $requestStack)
    {
        parent::__construct(
            $baseRegistry->container,
            $baseRegistry->getConnectionNames(),
            $baseRegistry->getManagerNames(),
            $baseRegistry->getDefaultConnectionName(),
            $baseRegistry->getDefaultManagerName()
        );

        $this->requestStack = $requestStack;
    }

    /**
     * {@inheritdoc}
     */
    public function getConnection($name = null)
    {
        $connection = null;
        $request = $this->requestStack->getCurrentRequest();

        if ($request) {
            $path = $request->getPathInfo();

            if (preg_match(':^/cda:', $path)) {
                $connection = 'cda';
            } elseif (preg_match(':^/pts:', $path)) {
                $connection = 'pts';
            }
        }

        return parent::getConnection($connection);
    }

    /**
     * {@inheritdoc}
     */
    public function getManager($name = null)
    {
        $manager = null;
        $request = $this->requestStack->getCurrentRequest();

        if ($request) {
            $path = $request->getPathInfo();

            if (preg_match(':^/cda:', $path)) {
                $manager = 'cda';
            } elseif (preg_match(':^/pts:', $path)) {
                $manager = 'pts';
            }
        }

        return parent::getManager($manager);
    }
}

通过重写Registry类的方法,我们使用请求对象来确定应该使用哪个实体管理器或哪个连接。使用特定实体管理器名称或连接名称调用父方法,具体取决于URL。如果URL无法帮助找到要使用的URL,则使用默认值(在config.yml中定义)。

相关问题