Короче говоря, вы можете, но будет намного проще дублировать ваши аннотации на каждом контроллере.
Но если вы все равно не хотите этого делать, вот несколько решений.
Маршрутизация
Это самый простой. Вы можете определить глобальный префикс в файле config/routes/annotations.yaml
.
Если вы используете конфигурацию по умолчанию, вы можете попробовать что-то вроде этого:
# Default controllers
controllers:
resource: ../../src/Controller/
type: annotation
# Company controllers
company_controllers:
resource: ../../src/Controller/Company/
type: annotation
prefix: /pro/{uniqid}
Все ваши маршруты теперь начинаются с /pro/{uniqid}
, и вы можете удалить аннотацию @Route
с вашего контроллера.
ParamConverter
Вы можете создать свой собственный ParamConverter . Каждый раз, когда вы будете использовать тип Company
в методе действия, он будет преобразован в соответствующий объект с помощью атрибута uniqid
.
Примерно так:
// src/ParamConverter/CompanyConverter.php
<?php
namespace App\ParamConverter;
use App\Entity\Company;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpFoundation\Request;
class CompanyConverter implements ParamConverterInterface
{
const CONVERTER_ATTRIBUTE = 'uniqid';
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* CompanyConverter constructor.
*
* @param EntityManagerInterface $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @inheritdoc
*/
public function apply(Request $request, ParamConverter $configuration)
{
$uniqid = $request->attributes->get(self::CONVERTER_ATTRIBUTE);
$company = $this->entityManager->getRepository(Company::class)->findOneBy(['uniqid' => $uniqid]);
$request->attributes->set($configuration->getName(), $company);
}
/**
* @inheritdoc
*/
function supports(ParamConverter $configuration)
{
return $configuration->getClass() === Company::class;
}
}
С этим вы можете удалить аннотацию @ParamConverter
с вашего контроллера.
Безопасность
Нельзя использовать раздел access_control файла security.yaml
, поскольку пользовательские функции еще не поддерживаются.
В противном случае что-то вроде этого могло бы быть хорошим:
security:
...
access_control:
-
path: ^/pro
allow_if: "is_granted(constant('App\\Security\\Voter\\CompanyVoter::VIEW'), company)"
(Примечание: это было исправлено в Symfony 4.1 , но я пока не знаю, как это будет работать).
Вместо этого вы можете использовать подписчика, прослушивающего событие ядра kernel.request
:
<?php
namespace App\Subscriber;
use App\Entity\Company;
use App\Security\CompanyVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class SecurityListener implements EventSubscriberInterface
{
/**
* @var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @param AuthorizationCheckerInterface $authorizationChecker
* @param EntityManagerInterface $entityManagerInterface
*/
public function __construct(AuthorizationCheckerInterface $authorizationChecker, EntityManagerInterface $entityManager)
{
$this->authorizationChecker = $authorizationChecker;
$this->entityManager = $entityManager;
}
/**
* @param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$uniqid = $request->attributes->get('uniqid')) {
return;
}
$company = $this->entityManager->getRepository(Company::class)->findOneBy(['titre' => $uniqid]);
if (!$this->authorizationChecker->isGranted(CompanyVoter::VIEW, $company)) {
throw new AccessDeniedHttpException();
}
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => 'onKernelRequest',
);
}
}