symfony 如何解决Twig环境不注入到shopware 6.5.4.0当尝试使用twig功能

sxissh06  于 2023-10-24  发布在  PWA
关注(0)|答案(2)|浏览(162)

我正在开发一个自定义插件,它可以接受来自API的数据。
我试图使用一个树枝函数来获得数据如下
twig函数类:

<?php declare(strict_types=1);

namespace Nst\Twig;

use Nst\Service\StoryblokService;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class StoryblokTwigExtension extends AbstractExtension
{
    public function __construct(private StoryblokService $storyblokService)
    {
  
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('get_story', [$this, 'getStory']),
        ];
    }

    public function getStory(string $slug): array
    {
        return $this->storyblokService->getStory($slug);
    }
}

在我的服务中:

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services">
    <services>
        <service id="Nst\Service\StoryblokService" public="true">
            <argument type="service" id="Storyblok\Client"/>
        </service>
        
        <service id="Storyblok\Client" class="Storyblok\Client">
            <argument>%env(dumpcode)%</argument>
        </service>

        <service id="Nst\Storefront\Controller\CodesController" public="true">
            <argument type="service" id="twig"/>
            <call method="setContainer">
                <argument type="service" id="service_container"/>
            </call>
        </service>
    </services>
</container>

然后在我的控制器中,我正在渲染页面,我试图注入到我的构造中以供使用。

<?php declare(strict_types=1);

namespace Nst\Storefront\Controller;

use Shopware\Storefront\Controller\StorefrontController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment;

/**
 * @Route(defaults={"_routeScope"={"storefront"}})
 */
class CodesController extends StorefrontController
{    

    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }
    
    public function setTwig(Environment $twig): void
{
    $this->twig = $twig;
    error_log('Twig has been set.'); // or use your preferred logging method
}

    /**
    * @Route("/mystore", name="frontend.example.example", methods={"GET"}, defaults={"_routeScope"={"storefront"}})
    */
    public function showPage(): Response
    {
        if (!$this->twig) {
            error_log('Twig is not set.');
        }
        
        return $this->renderStorefront('@Nst/storefront/page/example.html.twig', [
            'example' => 'Hello world'
        ]);
    }
}

我的twig页面的副本,我需要这个twig函数来显示从API消耗的数据。

{% sw_extends '@Storefront/storefront/base.html.twig' %}

{% block base_content %}
    <h1>Our example controller!</h1>
{% endblock %}

{% set story = get_story('ola-landing-page') %}

{% if story %}
    {# Display your story content here #}
    {{ story.content.title }}
    {# Add more fields as required from the story #}
{% endif %}

但我一直收到

hp.CRITICAL: Uncaught Error: Too few arguments to function Nst\Storefront\Controller\CodesController::__construct(), 0 passed in 

Uncaught PHP Exception Shopware\Storefront\Controller\Exception\StorefrontException: "Class Nst\Storefront\Controller\CodesController does not have twig injected. Add to your service definition a method call to setTwig with the twig instance" at

我不知道该怎么办,已经很长一段时间了,请帮助

ej83mcc0

ej83mcc01#

你扩展了StorefrontController,在那个控制器中已经定义了setTwig()函数。所以最好不要在你自己的控制器中覆盖那个函数,因为你不想改变twig注入控制器的方式。
Shopware使用setter注入将twig模板注入到店面控制器中,但您尝试通过构造函数注入它。
我建议在你的控制器中删除setTwig函数的覆盖,并删除构造函数,因为如果你通过setter注入twig环境,你就不需要它了(当然,如果你想在控制器中注入更多的依赖项,你可以把它加回去)。
然后在services.xml中添加对setTwig函数的调用:

<service id="Nst\Storefront\Controller\CodesController" public="true">
            <call method="setContainer">
                <argument type="service" id="service_container"/>
            </call>
                <call method="setTwig">
                <argument type="service" id="twig"/>
            </call>
        </service>

从架构的Angular 来看,我建议您不要在twig渲染期间通过自定义twig函数加载实际内容,而是在控制器中执行此操作,然后使用已设置的变量渲染twig模板。
如果您想坚持使用twig函数,我猜您需要在services.xml文件中配置该类,以便twig实际上选择它:https://developer.shopware.com/docs/guides/plugins/plugins/storefront/add-custom-twig-function

gjmwrych

gjmwrych2#

您可以通过添加needs_environment选项并将其设置为true来自动注入twig环境,然后正确的示例将自动传递给您的TwigFunction

<?php declare(strict_types=1);

namespace Nst\Twig;

use Nst\Service\StoryblokService;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class StoryblokTwigExtension extends AbstractExtension
{
    public function __construct(private StoryblokService $storyblokService)
    {
  
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('get_story', [$this, 'getStory'], [ 'needs_environment' => true),
        ];
    }

    public function getStory(\Twig\Environment $twig, string $slug): array
    {
        /*
            Now you can use $twig to render something
            or you could even pass it to the service if needed/wanted
            ....
            return $twig->render(....);
            $this->storyblockService->setTwig($twig);
            ...
        */   
        return $this->storyblokService->getStory($slug);
    }
}

相关问题