目前我正在开发基于 Symfony 的 Shopware 6 扩展。我不明白的是如何实现抽象类和依赖注入。
所以我希望能够重构代码,并经常使用这些方法,但在另一个上下文中(使用另一个存储库)
<?php declare(strict_types=1); namespace WShopService; use ShopwareCoreFrameworkContext; use ShopwareCoreFrameworkDataAbstractionLayerSearchCriteria; use ShopwareCoreFrameworkDataAbstractionLayerEntityRepository; use ShopwareCoreFrameworkDataAbstractionLayerSearchFilterEqualsFilter; use ShopwareCoreFrameworkUuidUuid; /** * Service for writing Products */ class ProductService { private EntityRepository $productRepository; private MediaImageService $mediaImageService; private EntityRepository $productMediaRepository; public function __construct( EntityRepository $productRepository, MediaImageService $mediaImageService, EntityRepository $productMediaRepository ) { $this->productRepository = $productRepository; $this->mediaImageService = $mediaImageService; $this->productMediaRepository = $productMediaRepository; } private function createProduct(array $data, Context $context = null): void { $context = $context ?? Context::createDefaultContext(); $this->productRepository->create([ $data ], $context); } public function updateProduct(array $data): void { $this->productRepository->update([$data], Context::createDefaultContext()); } public function getExistingProductId(string $productNumber): ?string { $criteria = new Criteria(); $criteria->addFilter(new EqualsFilter('productNumber', $productNumber)); return $this->productRepository->searchIds($criteria, Context::createDefaultContext())->firstId(); } }
如您所见,构造(产品存储库)内部存在依赖注入。现在我的问题是,我如何创建抽象类,即存储这些方法,但子类将使用所需的存储库“重写”父构造?例如,我想在产品存储库上使用getDataId(现在称为getExistingProductId,但将在抽象类中重构并重命名)方法,但是对于下一堂课我想在类别存储库上使用相同的方法?
Service.xml 又名依赖注入器
<service id="wshop_product_service" class="WShopServiceProductService"> <argument type="service" id="product.repository"/> <argument id="wshop_media_image_service" type="service"/> <argument type="service" id="product_media.repository"/> </service>
我是 OOP 的新手。请提供好的示例和代码解释。谢谢!
P粉2486022982024-01-10 00:03:24
如果我理解正确的话,您只希望第一个参数可以互换,并且示例中的 3 个方法应该在抽象中实现。这是一个想法。
摘要:
abstract class AbstractEntityService { protected EntityRepository $repository; public function __construct(EntityRepository $repository) { $this->repository = $repository; } public function create(array $data, ?Context $context = null): void { $context = $context ?? Context::createDefaultContext(); $this->repository->create([ $data ], $context); } public function update(array $data): void { $this->repository->update([$data], Context::createDefaultContext()); } abstract public function getDataId(array $params): ?string; protected function searchId(Criteria $criteria): ?string { return $this->repository->searchIds( $criteria, Context::createDefaultContext() )->firstId(); } }
您在构造函数中获取存储库,并在抽象中实现有关通用存储库的所有通用方法。您想要在扩展类中实现的 getDataId
方法,因为您对每个方法都使用了特定的条件(大概)。因此,您只需通过定义抽象签名来强制扩展类中的实现即可。
您的服务等级:
class ProductService extends AbstractEntityService { private MediaImageService $mediaImageService; private EntityRepository $productMediaRepository; public function __construct( EntityRepository $productRepository, MediaImageService $mediaImageService, EntityRepository $productMediaRepository ) { parent::__construct($productRepository); $this->mediaImageService = $mediaImageService; $this->productMediaRepository = $productMediaRepository; } public function getDataId(array $params): ?string { if (!isset($params['productNumber'])) { return null; } $criteria = new Criteria(); $criteria->addFilter(new EqualsFilter('productNumber', $params['productNumber'])); return $this->searchId($criteria); } // your other methods using the injected services }
在扩展类中,您仅将存储库传递给父构造函数,因为其他注入的服务仅在此特定实例中使用。您可以在创建特定条件的地方实现 getDataId
并使用该条件调用受保护的(因为它只能由扩展使用)searchId
方法。