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

Shopware 6 服务端API错误捕获:处理数据库重复条目报错

在Shopware 6中捕获数据库重复键错误并优化响应

1. 创建异常订阅器

通过监听kernel.exception事件,捕获数据库抛出的唯一约束违反异常,替换为友好的错误信息和正确的HTTP状态码。

代码示例

<?php

namespace YourPluginName\Subscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;

class ExceptionSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            ExceptionEvent::class => 'onKernelException',
        ];
    }

    public function onKernelException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        
        // 匹配唯一约束违反异常
        if ($exception instanceof UniqueConstraintViolationException) {
            $errorMsg = '数据已存在,请更换后重试';
            
            // 针对特定字段的重复错误定制信息
            if (str_contains($exception->getMessage(), 'my_entity.name')) {
                $errorMsg = '该名称已被使用,请更换其他名称';
            }

            // 返回标准409冲突状态码的JSON响应
            $response = new JsonResponse([
                'errors' => [
                    [
                        'status' => '409',
                        'title' => '重复条目',
                        'detail' => $errorMsg,
                    ]
                ]
            ], 409);

            $event->setResponse($response);
        }
    }
}

2. 注册订阅器

在插件的配置文件中注册上述订阅器,让Shopware识别并启用它。

services.xml 配置示例

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="YourPluginName\Subscriber\ExceptionSubscriber">
            <tag name="kernel.event_subscriber"/>
        </service>
    </services>
</container>

services.yaml 配置示例(若使用YAML格式)

services:
  YourPluginName\Subscriber\ExceptionSubscriber:
    tags:
      - { name: kernel.event_subscriber }

3. 可选:业务层提前校验(推荐)

在写入数据库前主动检查重复条目,从根源避免抛出数据库异常,同时返回更规范的校验错误。

代码示例

<?php

namespace YourPluginName\Service;

use Shopware\Core\Framework\Context;
use YourPluginName\Repository\MyEntityRepository;
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
use Symfony\Component\Validator\ConstraintViolation;

class MyEntityService
{
    public function __construct(private readonly MyEntityRepository $repository)
    {
    }

    public function createOrUpdate(array $data, Context $context): void
    {
        // 检查目标名称是否已存在
        $existingItems = $this->repository->search(
            (new \Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria())
                ->addFilter(new \Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter('name', $data['name'])),
            $context
        );

        if ($existingItems->count() > 0) {
            throw new ConstraintViolationException(
                null,
                [
                    new ConstraintViolation(
                        '该名称已被使用,请更换其他名称',
                        '',
                        [],
                        '',
                        'name',
                        $data['name']
                    )
                ]
            );
        }

        // 执行写入操作
        $this->repository->upsert([$data], $context);
    }
}

关键说明

  • 使用409 Conflict状态码是HTTP协议中表示资源冲突的标准做法,比默认的500状态码更准确。
  • 若需区分不同字段的重复错误,可通过匹配异常消息中的表名和字段名来定制提示内容。
  • 业务层提前校验能减少数据库层面的异常触发,性能更优,同时错误信息更符合Shopware的API响应规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:00:11