我会使用一个简单的管理路由系统.
例如我现在有这条路线.
_welcome ANY ANY ANY /
acmedemo_example_index ANY ANY ANY /acme/demos
acmedemo_example_edit ANY ANY ANY /acme/edit/{id}
acmedemo_example_delete ANY ANY ANY /acme/delete/{id}
acmeapi_backup_get GET ANY ANY /api/acme
acmeapi_backup_edit POST ANY ANY /api/acme
Run Code Online (Sandbox Code Playgroud)
现在我将当前用户ID添加到每个路由,因为如果用户向我或其他支持者/管理员发送链接,我们将看到用户看到的内容.你明白?
我现在就有这个.
_welcome ANY ANY ANY /
acmedemo_example_index ANY ANY ANY /{user}/acme/demos
acmedemo_example_edit ANY ANY ANY /{user}/acme/edit/{id}
acmedemo_example_delete ANY ANY ANY /{user}/acme/delete/{id}
acmeapi_backup_get GET ANY ANY /api/acme
acmeapi_backup_edit POST ANY ANY /api/acme
Run Code Online (Sandbox Code Playgroud)
现在是"问题"......如果路由名称匹配,我想自动为每条路由添加"user"参数preg_match('/^acmedemo_/i').
例如(index.html.twig):
<a href="{{ path('acmedemo_example_index') }}">Show demos</a>
Run Code Online (Sandbox Code Playgroud)
要么
<a href="{{ path('acmedemo_example_edit', {id: entity.id}) }}">Edit demo</a>
Run Code Online (Sandbox Code Playgroud)
我不希望使用{{ path('acmedemo_example_edit', {id: entity.id, user: app.user.id}) }}!
而"user"参数需要"\ d +".
我想覆盖路由器上的"生成"功能,例如.然后我可以检查是否$router->getUrl()匹配^acmedemo_,然后我可以添加user参数:)
谢谢!
Soooo对我来说是新的一天:D
我重写了路由器和UrlGenerator.
@ Chausser:我很容易解决你的问题1:
acme_demo_example:
resource: "@AcmeDemoBundle/Controller/"
type: annotation
prefix: /{user}
Run Code Online (Sandbox Code Playgroud)
现在我有这样的路线.
_welcome ANY ANY ANY /
acmedemo_example_index ANY ANY ANY /{user}/acme/demos
acmedemo_example_edit ANY ANY ANY /{user}/acme/edit/{id}
acmedemo_example_delete ANY ANY ANY /{user}/acme/delete/{id}
acmeapi_examples_get GET ANY ANY /api/acme
acmeapi_examples_edit POST ANY ANY /api/acme
Run Code Online (Sandbox Code Playgroud)
问题1解决了!
问题2,因为我不想要额外的路线功能或其他东西.我想用<a href="{{ path('acmedemo_example_index') }}">Show demos</a>和<a href="{{ path('acmedemo_example_edit', {id: entity.id}) }}">Edit demo</a>.
但如果我愿意,我会得到错误.还可以这样做.
我对这项服务的问题是我没有容器>.<
services.yml
parameters:
router.class: Acme\DemoBundle\Routing\Router
router.options.generator_base_class: Acme\DemoBundle\Routing\Generator\UrlGenerator
Run Code Online (Sandbox Code Playgroud)
ACME\DemoBundle \路由\路由器
use Symfony\Bundle\FrameworkBundle\Routing\Router as BaseRouter;
class Router extends BaseRouter implements ContainerAwareInterface
{
private $container;
public function __construct(ContainerInterface $container, $resource, array $options = array(), RequestContext $context = null)
{
parent::__construct($container, $resource, $options, $context);
$this->setContainer($container);
}
public function getGenerator()
{
$generator = parent::getGenerator();
$generator->setContainer($this->container);
return $generator;
}
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
}
Run Code Online (Sandbox Code Playgroud)
ACME\DemoBundle \路由\发电机\ UrlGenerator
use Symfony\Component\Routing\Generator\UrlGenerator as BaseUrlGenerator;
class UrlGenerator extends BaseUrlGenerator implements ContainerAwareInterface
{
private $container;
protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens)
{
/** Set the default user parameter for the routes which haven't a user parameter */
if(preg_match('/^acmedemo_/i', $name) && in_array('user', $variables) && !array_key_exists('user', $parameters))
{
$parameters['user'] = $this->getUser()->getId();
}
return parent::doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens);
}
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* @see \Symfony\Component\Security\Core\Authentication\Token\TokenInterface::getUser()
*/
public function getUser()
{
if (!$this->container->has('security.context')) {
throw new \LogicException('The SecurityBundle is not registered in your application.');
}
if (null === $token = $this->container->get('security.context')->getToken()) {
return null;
}
if (!is_object($user = $token->getUser())) {
return null;
}
return $user;
}
}
Run Code Online (Sandbox Code Playgroud)
问题2解决了!
(我在Symfony*上写的代码*2.3*)
谢谢你的帮助.但这更好我认为=)
实际上使用RequestContext::setParameter()方法有一种更简单的方法.此上下文可通过路由器通过Router::getContext()方法获得.
对传入请求使用内核侦听器来初始化此上下文,或者在请求范围(例如命令)之外,直接通过调用路由器服务上的方法.
$router->getContext()->setParameter('user', $user->getId());
// where $router is the @router service.
Run Code Online (Sandbox Code Playgroud)
请求侦听器的示例:
namespace AppBundle\Listener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* Add user param to router context on new request.
*/
class UserAwareRouterContextSubscriber implements EventSubscriberInterface
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var RequestContextAwareInterface
*/
private $router;
/**
* @param TokenStorageInterface $tokenStorage
* @param RequestContextAwareInterface $router
*/
public function __construct(TokenStorageInterface $tokenStorage, RequestContextAwareInterface $router)
{
$this->tokenStorage = $tokenStorage;
$this->router = $router;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [KernelEvents::REQUEST => 'onRequest'];
}
/**
* @param GetResponseEvent $event
*/
public function onRequest(GetResponseEvent $event)
{
if (!$event->isMasterRequest()) {
return;
}
if ($token = $this->tokenStorage->getToken()) {
$user = $token->getUser();
if ($user instanceof MyUserClass) { // use your own class here :)
$this->router->getContext()->setParameter('user', $user->getId());
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
服务配置:
services:
app.listener.user_aware_router_context:
class: AppBundle\Listener\UserAwareRouterContextSubscriber
arguments:
- '@security.token_storage'
- '@router'
tags:
- {name: kernel.event_subscriber}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5726 次 |
| 最近记录: |