搜尋

首頁  >  問答  >  主體

Shopware 6、Symfony 中的抽象類別和依賴注入

目前我正在開發基於 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粉680087550P粉680087550403 天前555

全部回覆(1)我來回復

  • P粉248602298

    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 方法。

    回覆
    0
  • 取消回覆