繁体   English   中英

symfony2 为路由添加动态参数,尝试使用自定义加载器

[英]symfony2 add dynamic parameter for routing, try with custom loader

我尝试像这里一样设置自定义路由器加载程序

http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html

我想为所有路由添加动态参数(来自会话的参数)

这是我的代码

namespace Mea\Crm4Bundle\Routing;

use Mea\Crm4Bundle\Entity\Application;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Config\Resource\FileResource;

class AppLoader extends YamlFileLoader
{
    private static $availableKeys = array(
        'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition',
    );
    private $yamlParser;

    private $loaded = false;
    /**
     * @var
     */
    private $annotationClassLoader;
    /**
     * @var
     */
    private $session;

    /**
     * Constructor.
     *
     * @param FileLocatorInterface $locator A FileLocatorInterface instance
     * @param AnnotationClassLoader $annotationClassLoader
     * @param Session $session
     */
    public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $annotationClassLoader, Session $session)
    {
        $this->locator = $locator;
        $this->annotationClassLoader = $annotationClassLoader;
        $this->session = $session;
    }


    public function load($file, $type = null)
    {

        $appId = $this->session->get(
            Application::CRM_APP_ID_SESSION
        );


        $path = $this->locator->locate($file);

        if (!stream_is_local($path)) {
            throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path));
        }

        if (!file_exists($path)) {
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        try {
            $parsedConfig = $this->yamlParser->parse(file_get_contents($path));
        } catch (ParseException $e) {
            throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
        }

        $collection = new RouteCollection();
        $collection->addResource(new FileResource($path));

        // empty file
        if (null === $parsedConfig) {
            return $collection;
        }

        // not an array
        if (!is_array($parsedConfig)) {
            throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path));
        }

        foreach ($parsedConfig as $name => $config) {

            $config['defaults']['_applicationid']=$appId;

            if (isset($config['pattern'])) {
                if (isset($config['path'])) {
                    throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
                }

                @trigger_error(sprintf('The "pattern" option in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "path" option in the route definition instead.', $path), E_USER_DEPRECATED);

                $config['path'] = $config['pattern'];
                unset($config['pattern']);
            }

            $this->validate($config, $name, $path);

            if (isset($config['resource'])) {
                $this->parseImport($collection, $config, $path, $file);
            } else {
                $this->parseRoute($collection, $name, $config, $path);
            }
        }

        return $collection;

    }

    public function supports($resource, $type = null)
    {
        return 'crmapp' === $type;
    }

}

这是routing.yml

mea_crm:
    resource: @MeaCrm4Bundle/Resources/config/routing.yml
    type: crmapp
    prefix: /{_applicationid}
    defaults:  { _applicationid: 5 }

这是 services.yml

  app.routing_loader:
            class: Mea\Crm4Bundle\Routing\AppLoader
            arguments: [@file_locator, @sensio_framework_extra.routing.loader.annot_class,@session]
            tags:
                - { name: routing.loader }

如果我删除缓存,此加载程序将被触发一次。 所以我认为这不是我需要的。 我如何覆盖路由器或以其他方式 - 我想从会话中设置 _aplication id 默认值。

更新 1

我设置路由器

这是工作方法

class RouteGenerator extends  UrlGenerator

public function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array()){


        if(!isset($parameters[MeaCrm4Bundle::CRM_APP_SWITCH_PARAMETER])){

            //for test
            $parameters[MeaCrm4Bundle::CRM_APP_SWITCH_PARAMETER] = 1212;

        }

        $url = parent::doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);

        return $url;
    }

当我添加到 parameters.yml

router.options.generator_base_class: Mea\Crm4Bundle\Routing\RouteGenerator

我有我想要的 - 树枝,控制器使用这个路由器并设置我的参数。 只有一个 - 这不是服务,所以我没有 @session 在这里获取会话的最佳方法是什么?

您创建其他类即服务吗? 我得到了覆盖树枝生成器的示例,但是存在通过服务而不是类覆盖主路由器的方法吗?

更新 2

所以我覆盖路由器 - 但没有会话 - 我需要像这里

public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, Session $session)
    {
        $this->routes = $routes;
        $this->context = $context;
        $this->logger = $logger;
        $this->session = $session;
    }

但是现在怎么办 - 如何在此处获取会话?

我想你应该尝试实现Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface

或者尝试扩展路由器并将其注册为服务。

然后,您需要按照TwigBundle提供的扩展创建适当的扩展:

<service id="twig.extension.routing" class="Symfony\Bridge\Twig\Extension\RoutingExtension" public="false">
    <argument type="service" id="router" />
</service>

将您的自定义生成器传递给它:

<service id="app.twig.url_generator" class="AppBundle\Twig\Extension\RoutingExtension" public="false">
    <argument type="service" id="app.url_generator">
</service>

<service id="app.url_generator" class="AppBundle\Routing\AppUrlGenerator" public="false">
    <argument type="service" id="router">
    <argument type="service" id="session">
</service>

您需要装饰路由器以加载路由集合。

并且不要忘记注册树枝扩展名:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM