Currently I am developing a Shopware 6 extension based on Symfony. What I don't understand is how to implement abstract classes and dependency injection.
So I want to be able to refactor the code and use these methods often, but in another context (using another repository)
<?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(); } }
As you can see, there is dependency injection inside the construct (product repository). Now my question is, how can I create an abstract class, i.e. store these methods, but the child class will "override" the parent construct with the required repository? For example, I want to use the getDataId (now called getExistingProductId, but will be refactored and renamed in the abstract class) method on ProductRepository, but for the next class I want to Use the same method on Category Repository?
Service.xml also known as dependency injector
<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>
I am new to OOP. Please provide good examples and code explanations. Thanks!
If I understand correctly, you only want the first parameter to be interchangeable, and the 3 methods in your example should be implemented in the abstraction. Here's an idea.
Summary:
You get the repository in the constructor and implement all the common methods about the common repository in the abstraction. You want to implement the
getDataId
methods in your extended class because you are using specific conditions for each method (presumably). So you just force the implementation in the extended class by defining an abstract signature.Your service level:
In the extension class you only pass the repository to the parent constructor because other injected services are only used in this specific instance. You can implement
getDataId
where you create a specific condition and use that condition to call the protected (because it can only be used by extensions)searchId
method.