Shopware 6、Symfony 中的抽象类和依赖注入
P粉680087550
P粉680087550 2024-01-09 08:44:57
0
1
501

目前我正在开发基于 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粉680087550
P粉680087550

全部回复(1)
P粉248602298

如果我理解正确的话,您只希望第一个参数可以互换,并且示例中的 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 方法。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板