我正在構建的應用程式不會以傳統方式作業。所有路線都將存盤在資料庫中。根據提供的路線,我需要獲得正確的控制器和要執行的操作。
據我了解,這可以使用“kernel.controller”事件偵聽器來實作:https ://symfony.com/doc/current/reference/events.html#kernel-controller
我正在嘗試使用提供的檔案,但此處的示例并未準確顯示如何設定要傳遞的新可呼叫控制器。我這里有個問題,因為我不知道如何將服務容器注入到我新呼叫的控制器中。
一開始的設定:
服務.yaml
parameters:
db_i18n.entity: App\Entity\Translation
developer: '%env(DEVELOPER)%'
category_directory: '%kernel.project_dir%/public/uploads/category'
temp_directory: '%kernel.project_dir%/public/uploads/temp'
product_directory: '%kernel.project_dir%/public/uploads/product'
app.supported_locales: 'lt|en|ru'
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
App\Translation\DbLoader:
tags:
- { name: translation.loader, alias: db }
App\Extension\TwigExtension:
arguments:
- '@service_container'
tags:
- { name: twig.extension }
App\EventListener\RequestListener:
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onControllerRequest }
聽者:
請求監聽器.php
<?php
namespace App\EventListener;
use App\Controller\Shop\HomepageController;
use App\Entity\SeoUrl;
use Doctrine\Persistence\ManagerRegistry;
use Exception;
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Security;
class RequestListener
{
public ManagerRegistry $doctrine;
public RequestStack $requestStack;
public function __construct(ManagerRegistry $doctrine, RequestStack $requestStack)
{
$this->doctrine = $doctrine;
$this->requestStack = $requestStack;
}
/**
* @throws Exception
*/
public function onControllerRequest(ControllerEvent $event)
{
if (!$event->isMainRequest()) {
return;
}
if(str_contains($this->requestStack->getMainRequest()->getPathInfo(), '/admin')) {
return;
}
$em = $this->doctrine->getManager();
$pathInfo = $this->requestStack->getMainRequest()->getPathInfo();
;
$route = $em->getRepository(SeoUrl::class)->findOneBy(['keyword' => $pathInfo]);
if($route instanceof SeoUrl) {
switch ($route->getController()) {
case 'homepage':
$controller = new HomepageController();
$event->setController([$controller, $route->getAction()]);
break;
default:
break;
}
} else {
throw new Exception('Route not found');
}
}
}
所以這是最基本的例子。我從資料庫中獲取路由,如果它是“主頁”路由,我創建新的 HomepageController 并設定操作。但是我錯過了我不知道如何注入的容器介面。我收到此錯誤:
在 null 上呼叫成員函式 has()
在線:供應商\symfony\framework-bundle\Controller\AbstractController.php:216
這是:
/**
* Returns a rendered view.
*/
protected function renderView(string $view, array $parameters = []): string
{
if (!$this->container->has('twig')) { // here
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
}
return $this->container->get('twig')->render($view, $parameters);
}
控制器是最基本的:
主頁控制器.php
<?php
namespace App\Controller\Shop;
use App\Repository\CategoryRepository;
use App\Repository\Shop\ProductRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class HomepageController extends AbstractController
{
#[Route('/', name: 'index', methods: ['GET'])]
public function index(): Response
{
return $this->render('shop/index.html.twig', [
]);
}
}
所以基本上容器沒有設定。如果我轉儲$event->getController()我得到這個:
RequestListener.php on line 58:
array:2 [▼
0 => App\Controller\Shop\HomepageController {#417 ▼
#container: null
}
1 => "index"
]
我需要通過做來設定容器$controller->setContainer(),但是我要通過什么?
uj5u.com熱心網友回復:
不要注入容器,控制器也是服務,手動實體化它們會阻止您使用建構式依賴注入。使用僅包含控制器的服務定位器:
在config/services.yaml中宣告:
# config/services.yaml
services:
App\EventListener\RequestListener:
arguments:
$serviceLocator: !tagged_locator { tag: 'controller.service_arguments' }
然后在事件監聽器中,添加服務定位器引數并從中獲取完全配置的控制器:
# ...
use App\Controller\Shop\HomepageController;
use Symfony\Component\DependencyInjection\ServiceLocator;
class RequestListener
{
# ...
private ServiceLocator $serviceLocator;
public function __construct(
# ...
ServiceLocator $serviceLocator
) {
# ...
$this->serviceLocator = $serviceLocator;
}
public function onControllerRequest(ControllerEvent $event)
{
# ...
if($route instanceof SeoUrl) {
switch ($route->getController()) {
case 'homepage':
$controller = $this->serviceLocator->get(HomepageController::class);
# ...
break;
default:
break;
}
}
# ...
}
}
如果您轉儲任何控制器,您將看到容器已設定。從建構式自動裝配的附加服務也是如此。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/476230.html
