Shopware 6(Symfony)中抽象类与依赖注入实现方案问询
基于Shopware 6的抽象类+依赖注入重构方案
针对你的需求,我们可以通过抽象类封装通用逻辑+依赖注入注入具体仓库的方式来重构,下面是适合刚接触OOP的一步步实现方案:
1. 编写抽象基础服务类
先把所有实体通用的方法(比如获取ID、增改实体)抽到抽象类里,这个类作为所有实体服务的“模板”,只定义通用逻辑,不处理具体业务。
<?php namespace YourPlugin\Service; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult; abstract class AbstractEntityService { // 子类需要注入具体的实体仓库 protected EntityRepository $repository; // 构造函数接收仓库实例,所有子类都会继承这个构造逻辑 public function __construct(EntityRepository $repository) { $this->repository = $repository; } /** * 根据过滤条件获取实体ID列表 */ public function getEntityIds(array $filters, Context $context): array { $criteria = new Criteria(); foreach ($filters as $filter) { $criteria->addFilter($filter); } /** @var IdSearchResult $result */ $result = $this->repository->searchIds($criteria, $context); return $result->getIds(); } /** * 通用的实体增改方法(upsert:存在则更新,不存在则创建) */ public function upsertEntity(array $data, Context $context): void { $this->repository->upsert($data, $context); } /** * 根据ID获取单个实体 */ public function getEntityById(string $id, Context $context): ?object { $criteria = new Criteria([$id]); $result = $this->repository->search($criteria, $context); return $result->first(); } }
2. 创建子类适配具体实体仓库
针对商品、分类等不同实体,创建对应的子类继承抽象类,只需要实现该实体专属的业务逻辑,通用方法直接继承即可。
商品服务子类
<?php namespace YourPlugin\Service; use Shopware\Core\Framework\Context; class ProductService extends AbstractEntityService { // 商品专属业务:更新库存 public function updateStock(string $productId, int $stock, Context $context): void { // 直接调用抽象类的upsert方法,不用重复写仓库操作 $this->upsertEntity([ [ 'id' => $productId, 'stock' => $stock ] ], $context); } }
分类服务子类
<?php namespace YourPlugin\Service; use Shopware\Core\Framework\Context; class CategoryService extends AbstractEntityService { // 分类专属业务:更新分类排序 public function updateCategoryPosition(string $categoryId, int $position, Context $context): void { $this->upsertEntity([ [ 'id' => $categoryId, 'position' => $position ] ], $context); } }
3. 配置依赖注入(services.xml)
Shopware 6基于Symfony,所以需要在插件的src/Resources/config/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> <!-- 抽象服务:标记为abstract,不会被实例化,仅作为子类的父模板 --> <service id="YourPlugin\Service\AbstractEntityService" abstract="true"> <argument type="service" id="Shopware\Core\Framework\DataAbstractionLayer\EntityRepository"/> </service> <!-- 商品服务:继承抽象服务,替换参数为Shopware内置的商品仓库 --> <service id="YourPlugin\Service\ProductService" parent="YourPlugin\Service\AbstractEntityService"> <argument type="service" id="product.repository"/> </service> <!-- 分类服务:继承抽象服务,替换参数为Shopware内置的分类仓库 --> <service id="YourPlugin\Service\CategoryService" parent="YourPlugin\Service\AbstractEntityService"> <argument type="service" id="category.repository"/> </service> </services> </container>
注:Shopware内置的实体仓库ID格式为
{实体名}.repository,比如商品是product.repository,分类是category.repository,直接使用即可。
4. 在业务代码中使用
比如在控制器里注入子类服务,直接调用通用或专属方法:
<?php namespace YourPlugin\Controller; use YourPlugin\Service\ProductService; use YourPlugin\Service\CategoryService; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; #[Route(defaults: ['_routeScope' => ['api']])] class EntityController extends AbstractController { // 构造函数注入子类服务 public function __construct( private readonly ProductService $productService, private readonly CategoryService $categoryService ) {} #[Route(path: '/api/v{version}/your-plugin/active-product-ids', methods: ['GET'])] public function getActiveProductIds(Context $context): Response { // 调用抽象类的通用方法获取启用状态的商品ID $filters = [new EqualsFilter('active', true)]; $productIds = $this->productService->getEntityIds($filters, $context); return $this->json(['active_product_ids' => $productIds]); } #[Route(path: '/api/v{version}/your-plugin/update-category-position', methods: ['POST'])] public function updateCategoryPosition(string $categoryId, int $position, Context $context): Response { // 调用分类服务的专属方法 $this->categoryService->updateCategoryPosition($categoryId, $position, $context); return $this->json(['success' => true]); } }
核心逻辑说明
- 抽象类的价值:把重复的通用逻辑封装起来,子类只需要关注自身专属业务,避免代码冗余;抽象类不能直接实例化,必须被继承。
- 依赖注入的作用:把实体仓库的实例化交给Symfony容器,代码解耦,后续替换仓库(比如测试用Mock仓库)时不需要修改业务代码。
- Shopware的仓库注入:直接使用官方内置的仓库ID即可,不需要自己实例化仓库类。
内容的提问来源于stack exchange,提问作者balrcoding
相关产品推荐
相关产品推荐

