piotrpolak / conditional-routing-bundle
提供了一种基于用户定义条件有选择性地加载Symfony包路由的方法。
Requires
- php: >=5.3.0
- symfony/config: ~2.3|~3.4
- symfony/dependency-injection: ~2.3|~3.4
- symfony/framework-bundle: ~2.3|~3.4
- symfony/http-kernel: ~2.3|~3.4
- symfony/routing: ~2.3|~3.4
- symfony/yaml: ~2.3|~3.4
Requires (Dev)
- codeclimate/php-test-reporter: ^0.3.2
- phpmd/phpmd: ^2.6
- phpunit/phpunit: ^4.8
- symfony/expression-language: ~2.3|~3.4
This package is auto-updated.
Last update: 2024-08-26 05:27:10 UTC
README
提供了一种基于用户定义条件加载选定Symfony包路由的方法。
解决了从基础包到另一个包重定向(覆盖)Symfony应用程序路由的问题。
示例用法
- 覆盖选定用户和/或角色的Symfony应用程序路由;
- 基于当前时间(例如切换月度活动)覆盖Symfony应用程序路由;
- 基于会话变量值覆盖Symfony应用程序路由;
- 基于用户角色和HTTP域覆盖Symfony应用程序路由。
安装
安装composer包
composer require piotrpolak/conditional-routing-bundle
在应用程序内核中启用 PiotrPolakConditionalRoutingBundle
// in AppKernel::registerBundles() $bundles = array( // ... new PiotrPolak\ConditionalRoutingBundle\PiotrPolakConditionalRoutingBundle(), // ... );
包含包路由
包含 routing.yml
将启用 ConditionalRouterLoader
。
# in app/config/routing.yml, without those lines ConditionalRouterLoader will not be enabled conditional_routing: resource: "@PiotrPolakConditionalRoutingBundle/Resources/config/routing.yml" type: yaml
Symfony只有在您至少使用它配置一个路由时才会加载资源加载器。您还可以将上述资源文件的全部内容直接粘贴到您的
app/config/routing.yml
中。
实现自己的路由解析器
路由解析器 是实现 RouteResolverInterface
的组件,并决定在请求时包含哪些包的路由。
一个典型的路由解析器组件在容器配置的 conditional_loader.route_resolver
标签下注册 - 您可以注册任意数量的路由解析器组件,所有这些组件都将被考虑在选择要包含的包组合时。
由于您可以将任何其他组件传递给路由解析器构造函数(如 @session
,@security.token_storage
...),因此可以使用任何用户定义的场景选择包。
示例 - 日期条件
以下示例根据年份条件加载 MyCampaign2016Bundle
路由。 注意: MyCampaign2016Bundle
必须首先在 AppKernel.php
中启用。
请注意,
AbstractYamlRouteResolver
只是一个辅助工具,它使使用RouteResolverInterface
更容易。
<?php namespace MyApp\Router; use PiotrPolak\ConditionalRoutingBundle\Model\AbstractYamlRouteResolver; class TimeCampaignRouteResolver extends AbstractYamlRouteResolver { /** * {@inheritdoc} */ public function resolveBundleNames() { // Loads @BaseCampaignBundle/Resources/config/routing.yml // In most cases it makes no sense to define bundle names that are ALWAYS loaded here as it can be done in the // app/config/routing.yml $bundleNames = ['BaseCampaignBundle']; if ((int)date('Y') >= 2016) { // Loads @MyCampaign2016Bundle/Resources/config/routing.yml // Can overwrite routes defined in BaseCampaignBundle or any other bundle $bundleNames[] = 'MyCampaign2016Bundle'; } return $bundleNames; } }
# in services.yml services: # ... my_app.campaign_route_resolver: class: MyApp\CampaignRouteResolver tags: - { name: conditional_loader.route_resolver }
示例 - 数据库值输入
从数据库中读取当前包名称。
<?php namespace MyApp\Router; use Doctrine\ORM\EntityManagerInterface; use PiotrPolak\ConditionalRoutingBundle\Model\AbstractYamlRouteResolver; class DatabaseCampaignRouteResolver extends AbstractYamlRouteResolver { /** @var EntityManagerInterface */ private $em; /** * CampaignRouteResolver constructor. * @param EntityManagerInterface $em */ public function __construct(EntityManagerInterface $em) { $this->em = $em; } /** * {@inheritdoc} */ public function resolveBundleNames() { // Loads @<CURRENT_BUNDLE_NAME>/Resources/config/routing.yml // Can overwrite any previously defined routes $bundleNames = [$this->getCurrentBundleName()]; return $bundleNames; } /** * @return string */ protected function getCurrentBundleName() { // Suppose you have a an entity having two fields: key and value // You might want to add some kind of cache to avoid reading from DB at every request return $this->em->getRepository('MyApp:Parameter') ->findOneBy(['key' => 'currentBundle']) ->getValue(); } }
# in services.yml services: # ... my_app.database_campaign_route_resolver: class: MyApp\DatabaseCampaignRouteResolver arguments: ['@doctrine.orm.entity_manager'] tags: - { name: conditional_loader.route_resolver }
示例 - 加载各种类型的路由
以下示例中的路由解析器直接实现了 RouteResolverInterface
并加载了 YAML 和 XML 类型的路由。
<?php namespace MyApp\Router; use PiotrPolak\ConditionalRoutingBundle\Model\RouteResolverInterface; use PiotrPolak\ConditionalRoutingBundle\Model\RoutingDefinition\XmlBundleRoutingDefinition; use PiotrPolak\ConditionalRoutingBundle\Model\RoutingDefinition\YamlBundleRoutingDefinition; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface; class VariousTypesCampaignRouteResolver implements RouteResolverInterface { /** @var EntityManagerInterface */ private $em; /** @var SessionInterface */ private $session; /** * VariousTypesCampaignRouteResolver constructor. * @param EntityManagerInterface $em * @param SessionInterface $session */ public function __construct(EntityManagerInterface $em, SessionInterface $session) { $this->em = $em; $this->session = $session; } /** * {@inheritdoc} */ public function resolveConditionalRoutingDefinitions() { $definitions = []; // Overwrites homepage for the first visit $numberOfHits = $this->session->get('my_app.number_of_visits', 0); $this->session->set('my_app.number_of_visits', $numberOfHits + 1); if (0 === $numberOfHits) { $definitions[] = new YamlBundleRoutingDefinition('MyAppFirstVisitBundle'); } // Disables some of the business critical routes based on the database value if ($this->em->getRepository('MyApp:Parameters')->findIsMaintenanceModeOn()) { $definitions[] = new XmlBundleRoutingDefinition('MyAppMaintenanceModeBundle'); } return $definitions; } }
# in services.yml services: # ... my_app.various_types_campaign_route_resolver: class: MyApp\VariousTypesCampaignRouteResolver arguments: - '@doctrine.orm.entity_manager' - '@session' tags: - { name: conditional_loader.route_resolver }
兼容性
- PHP 5.4+
- Symfony 2.3-3.4
注意事项
如果您尝试生成一个指向当前未激活的路由的链接,Symfony 将抛出一个错误。为了避免这种情况,请确保所有路由都在您的其中一个基础包中定义了默认行为。
开发
在提交之前应使用 phpmd 检查代码
./vendor/phpmd/phpmd/src/bin/phpmd src/ text codesize,controversial,design,unusedcode,naming,cleancode
测试
composer install --prefer-dist && ./vendor/bin/phpunit -v
为了测试任意版本组合,请使用 (sudo
可能需要连接到 Docker 守护进程)
SYMFONY_VERSION=3.4 PHP_VERSION=7.4 bin/test_in_docker.sh
已知问题
预热 Symfony 缓存不会删除自定义路由匹配器和生成器,因为我们无法预测启用路由的包的最终组合(它们只在运行时才已知)。
清除缓存的解决方案是将以下命令添加到您的部署脚本中
-
Symfony 2
rm -f ./app/cache/*/*UrlGenerator__*.php* && rm -f ./app/cache/*/*UrlMatcher__*.php*
-
Symfony 3
rm -f ./var/*/cache/*UrlGenerator__*.php* && rm -f ./var/*/cache/*UrlMatcher__*.php*