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

关于Shopware中api.order.search控制器路由定义及自定义扩展控制器的技术咨询

Shopware中api.order.search控制器路由定义及自定义扩展控制器的技术咨询

嘿,我来帮你理清楚这个问题~

首先你疑惑的点很关键:原api.order.search路由根本不是用控制器注解定义的,Shopware的这类通用API路由是通过动态代码注册的,不是依赖Symfony的注解路由机制,所以你在原ApiController上找不到对应的@Route注解很正常!

先搞懂原路由的来历

你贴的路由表信息显示这是一个Symfony\Component\Routing\Route实例,它是Shopware框架在启动时,通过专门的路由加载器(比如Shopware\Core\Framework\Api\ApiRouteLoader)动态生成的——框架会遍历所有注册的实体(比如order、product),自动为每个实体生成对应的搜索、详情、更新等通用API路由,然后直接绑定到ApiController的对应方法,通过路由defaults里的entityName参数来区分不同实体。

接下来实现你的自定义路由/api/custom/search/order

最直接的方式是手动注册自定义路由,不用依赖动态生成,步骤如下:

1. 在你的插件里注册路由

如果是Shopware 6插件,在插件目录的src/Resources/config/下创建routes.xml,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="api.custom.order.search" path="/api/custom/search/order{path}">
        <default key="_controller">YourPluginNamespace\Controller\OrderActionController::search</default>
        <default key="_routeScope">['api']</default>
        <default key="entityName">order</default>
        <requirement key="path">(\/[0-9a-f]{32}\/(extensions\/)?[a-zA-Z-]+)*\/?</requirement>
        <requirement key="version">\d+</requirement>
        <method>POST</method>
    </route>

</routes>

把YourPluginNamespace换成你实际的插件命名空间就行。

2. 编写你的自定义控制器

继承ApiController后,你可以复用父类的核心逻辑,然后修改响应格式来适配另一个系统:

<?php

namespace YourPluginNamespace\Controller;

use Shopware\Core\Framework\Api\Controller\ApiController;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntitySearchResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
 * @Route(defaults={"_routeScope"={"api"}})
 */
class OrderActionController extends ApiController
{
    public function search(Request $request, Context $context, string $entityName, string $path): Response
    {
        // 复用父类的搜索逻辑,拿到查询条件和仓库
        [$criteria, $repository] = $this->resolveSearch($request, $context, $entityName, $path);
        
        // 执行搜索
        $result = $context->scope(Context::CRUD_API_SCOPE, function (Context $context) use ($repository, $criteria): EntitySearchResult {
            return $repository->search($criteria, $context);
        });
        
        // 这里就是你自定义响应格式的地方!
        // 不用父类的responseFactory,自己构建适配另一个系统的结构
        $customResponseData = [
            'total' => $result->getTotal(),
            'orders' => array_map(function($order) {
                // 按需转换字段,比如只返回需要的字段,或者调整结构
                return [
                    'id' => $order->getId(),
                    'orderNumber' => $order->getOrderNumber(),
                    'totalAmount' => $order->getTotalPrice()
                    // 其他你需要的字段
                ];
            }, $result->getElements()),
            // 其他自定义响应字段
        ];
        
        return $this->json($customResponseData);
    }
}

3. 验证路由是否生效

运行Shopware的控制台命令:

bin/console debug:router api.custom.order.search

如果能看到路由的详细信息,说明注册成功了,接下来就可以测试POST请求到/api/custom/search/order,就能拿到你自定义格式的响应啦~

补充说明

  • 如果你想批量为多个实体生成这类自定义路由,才需要考虑继承Shopware的路由加载器来动态注册,但你只需要order的话,手动注册路由是最简洁的方案。
  • 原控制器没有注解是因为路由是直接绑定到方法的,和注解路由机制完全无关,所以不用纠结“动态注解”的问题哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:03:15