You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony清洁架构项目中FormInterface自动注入失败问题求助

问题解决:Symfony清洁架构项目中SearchHtmlView的Autowire错误

问题背景

在基于清洁架构的Symfony项目中,实现首页搜索栏对接API时,页面抛出Autowire错误:

Cannot autowire service "Infrastructure\Symfony\view\SearchHtmlView": argument "$form" of method "__construct()" references interface "Symfony\Component\Form\FormInterface" but no such service exists. Did you create a class that implements this interface?

错误原因

Symfony的依赖注入容器无法自动注入FormInterface,核心原因是:

  • 表单实例不是服务:FormInterface的实现是在控制器中通过createForm()动态创建的临时对象,并非由DI容器管理的服务,因此无法在类的构造函数中依赖注入。
  • SearchHtmlView的逻辑矛盾:构造函数注入了FormInterface,但generateView方法又接收了一个表单参数,内部却使用构造注入的实例,导致逻辑混乱。

修复步骤

1. 重构SearchHtmlView类

移除构造函数中的FormInterface依赖,仅保留Twig环境,在generateView方法中直接使用传入的表单实例:

namespace Infrastructure\Symfony\view;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;

class SearchHtmlView
{
    private Environment $twig;

    // 仅注入Twig环境,移除FormInterface依赖
    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }

    /**
     * @throws RuntimeError
     * @throws SyntaxError
     * @throws LoaderError
     */
    public function generateView(FormInterface $form): Response
    {
        return new Response($this->twig->render(
            'main/main.html.twig',
            [
                // 使用传入的表单创建视图对象
                "form" => $form->createView()
            ]
        ));
    }
}

2. 优化控制器逻辑(可选)

原控制器中addFlash的位置会导致无论表单是否提交都会显示提示,建议调整为仅在表单提交无效时显示:

namespace Infrastructure\Symfony\controller;

use Domain\Form\SearchFormType;
use Domain\Presenter\SearchCarPresenterInterface;
use Domain\UseCase\SearchCarUseCase;
use Infrastructure\Symfony\view\SearchHtmlView;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;

#[Route("/", name: "main")]
class mainController extends AbstractController
{
    public string $model;
    private SearchHtmlView $searchView;
    private SearchCarUseCase $carUseCase;
    private SearchCarPresenterInterface $presenter;

    public function __construct(
        SearchHtmlView $searchView,
        SearchCarUseCase $carUseCase,
        SearchCarPresenterInterface $presenter
    )
    {
        $this->searchView = $searchView;
        $this->carUseCase = $carUseCase;
        $this->presenter = $presenter;
    }

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */
    public function __invoke(Request $carRequest): Response
    {
        $form = $this->createForm(SearchFormType::class);
        $form->handleRequest($carRequest);

        if ($form->isSubmitted() && $form->isValid()) {
            $this->model = $form->get("car")->getData();
            $this->carUseCase->searchCar($form, $this->model);
            // 可选:添加搜索成功提示
            $this->addFlash("success", "搜索请求已发送");
        } elseif ($form->isSubmitted() && !$form->isValid()) {
            // 仅在表单提交但验证失败时显示错误提示
            $this->addFlash("message", "veuillez remplir le champ demande");
        }

        return $this->searchView->generateView($form);
    }
}

3. 清洁架构适配建议

为了符合清洁架构的分层原则,还可以做以下调整:

  • Domain层解耦框架:将Domain\Form\SearchFormType移到Infrastructure\Symfony\Form目录下,Domain层仅定义搜索请求的DTO(比如SearchCarRequest),避免Domain层依赖Symfony组件。
  • UseCase解耦表单:SearchCarUseCase的searchCar方法不应直接接收FormInterface,而是接收Domain层的SearchCarRequest对象,由控制器负责将表单数据映射到该DTO后传入UseCase,实现框架无关的业务逻辑。

内容的提问来源于stack exchange,提问作者Armad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:17:08