Shopware 6, abstrakte Klassen und Abhängigkeitsinjektion in Symfony
P粉680087550
P粉680087550 2024-01-09 08:44:57
0
1
485

Derzeit entwickle ich eine Shopware 6-Erweiterung auf Basis von Symfony. Was ich nicht verstehe, ist, wie man abstrakte Klassen und Abhängigkeitsinjektion implementiert.

Ich möchte also in der Lage sein, den Code umzugestalten und diese Methoden oft zu verwenden, aber in einem anderen Kontext (unter Verwendung eines anderen Repositorys)

<?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();
 }
}

Wie Sie sehen können, gibt es innerhalb des Konstrukts (Produkt-Repository) eine Abhängigkeitsinjektion. Meine Frage ist nun: Wie kann ich eine abstrakte Klasse erstellen, d. h. diese Methoden speichern, aber die untergeordnete Klasse wird das übergeordnete Konstrukt mit dem erforderlichen Repository „überschreiben“? Zum Beispiel möchte ich die Methode getDataId (jetzt getExistingProductId genannt, wird aber in der abstrakten Klasse umgestaltet und umbenannt) für das Product Repository verwenden, aber für die nächste Klasse möchte ich dasselbe für die Category verwenden Repository Methoden?

Service.xml, auch bekannt als Abhängigkeitsinjektor

<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>

Ich bin neu bei OOP. Bitte stellen Sie gute Beispiele und Codeerklärungen bereit. Danke!

P粉680087550
P粉680087550

Antworte allen(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 方法。

Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!