You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Shopware前台AJAX提交额外新闻通讯订阅表单时触发AccessDeniedHttpException的问题求助

Shopware前台AJAX提交额外新闻通讯订阅表单时触发AccessDeniedHttpException的问题求助

看起来你遇到的这个问题核心原因是Shopware的PageController不允许通过AJAX请求访问,结合你的错误信息和代码,我来一步步帮你排查解决:

1. 问题根源分析

错误信息“PageController can't be requested via XmlHttpRequest.”明确指向两个核心问题:

  1. 你的请求处理控制器很可能继承了Shopware\Storefront\Controller\PageController,而PageController是Shopware专门用于渲染完整页面的控制器类,它内置的XmlHttpRequestListener会直接拦截所有AJAX请求并抛出该异常。
  2. 你的表单同时使用了Shopware内置的data-form-auto-submit自动提交逻辑,又手动添加了submit事件监听,这会导致请求处理逻辑冲突,可能丢失AJAX请求所需的必要头信息。

2. 具体解决方案

方案一:修正控制器的父类

确保你的控制器继承自StorefrontController(这是Shopware处理Storefront各类请求包括AJAX的正确基类),而不是PageController

use Shopware\Storefront\Controller\StorefrontController;

class AdditionalNewsletterController extends StorefrontController
{
    // 你的请求处理方法...
}

方案二:移除冲突的自定义JS监听

你的表单已经通过data-form-auto-submit="true"data-form-auto-submit-options配置了Shopware内置的AJAX自动提交逻辑,不需要再手动编写submit事件监听代码。直接删除index.js中相关的监听逻辑即可,Shopware会自动处理AJAX请求,包括携带CSRF令牌和X-Requested-With头。

方案三:完善表单的CSRF令牌

在你的Twig表单中,添加Shopware官方的CSRF令牌生成标签,确保请求通过CSRF验证:

{% sw_extends '@Storefront/storefront/page/account/newsletter.html.twig' %}
{% block page_account_overview_newsletter_content_form %}
    {{ parent() }}
    <div class="js-additional-option-wrapper">
        <form name="additionalOptionForm"
              method="post"
              action="{{ path('frontend.account.additionalOption') }}"
              data-form-auto-submit="true"
              data-form-auto-submit-options='{"useAjax": true, "ajaxContainerSelector": ".js-additional-option-wrapper"}'>
            {# 添加Shopware官方CSRF令牌 #}
            {{ sw_csrf('frontend.account.additionalOption') }}
            
            {# 你的表单内容示例 #}
            <div class="form-group">
                <label class="form-check-label">
                    <input type="checkbox" 
                           class="form-check-input"
                           name="additionalOption" 
                           value="1"
                           {% if customer.extensions.additionalNewsletterSubscribed %}checked{% endif %}>
                    订阅专属行业动态通讯
                </label>
            </div>
        </form>
    </div>
{% endblock %}

方案四:调整控制器的响应类型

因为是AJAX请求,控制器方法应该返回JsonResponse或者渲染HTML片段,而不是完整页面响应:

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\Customer\CustomerEntity;
use Shopware\Core\Framework\DataAbstractionLayer\RepositoryInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class AdditionalNewsletterController extends StorefrontController
{
    private $customerRepository;
    private $translator;

    public function __construct(RepositoryInterface $customerRepository, TranslatorInterface $translator)
    {
        $this->customerRepository = $customerRepository;
        $this->translator = $translator;
    }

    #[Route(path: '/account/newsletter/additional-option', 
            name: 'frontend.account.additionalOption', 
            methods: ['POST'], 
            defaults: ['_loginRequired' => true, '_storefront' => true])]
    public function handleAdditionalOptionSubmission(Request $request, SalesChannelContext $context, CustomerEntity $customer): JsonResponse
    {
        $isSubscribed = $request->request->getBoolean('additionalOption');
        
        // 这里处理你的业务逻辑,比如更新客户的扩展字段
        $this->customerRepository->update([
            [
                'id' => $customer->getId(),
                'customFields' => [
                    'additional_newsletter_subscribed' => $isSubscribed
                ]
            ]
        ], $context->getContext());
        
        // 返回JSON响应
        return new JsonResponse([
            'success' => true,
            'message' => $this->translator->trans('additionalNewsletter.updatedSuccessfully')
        ]);
    }
}

3. 验证测试

完成以上调整后:

  1. 清除Shopware缓存(执行bin/console cache:clear命令)
  2. 登录前台账号,测试复选框的自动提交功能
  3. 在浏览器开发者工具中检查请求头是否携带X-Requested-With: XMLHttpRequest,以及CSRF令牌是否正确发送

如果仍有问题,可以进一步检查请求的响应状态码和返回内容,定位是否存在其他配置或逻辑问题。

备注:内容来源于stack exchange,提问作者Auhona

火山引擎 最新活动