I wrote an EntityExtension
for products:
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new ManyToManyAssociationField(
'logos',
LogosDefinition::class,
LogosProductDefinition::class,
'product_id',
'logo_id'
))->addFlags(new ApiAware(), new Inherited())
);
}
public function getDefinitionClass(): string
{
return ProductDefinition::class;
}
}
The definition LogosProductDefinition.php is structured as follows:
class LogosProductDefinition extends MappingEntityDefinition
{
public function getEntityName(): string
{
return 'logo_product';
}
protected function defineFields(): FieldCollection
{
return new FieldCollection([
(new FkField('_logo_id', 'logoId', LogosDefinition::class))->addFlags(new PrimaryKey(), new Required()),
(new FkField('product_id', 'productId', ProductDefinition::class))->addFlags(new PrimaryKey(), new Required()),
(new ReferenceVersionField(ProductDefinition::class))->addFlags(new PrimaryKey(), new Required()),
new ManyToOneAssociationField('logos', 'logo_id', LogosDefinition::class),
new ManyToOneAssociationField('product', 'product_id', ProductDefinition::class),
new CreatedAtField(),
]);
}
}
LogosDefinition.php
class LogosDefinition extends EntityDefinition
{
/* ......... */
protected function defineFields(): FieldCollection
{
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new Required(), new PrimaryKey()),
(new StringField('url', 'url'))->addFlags(new Required()),
new TranslatedField('title'),
new FkField('media_id', 'mediaId', MediaDefinition::class),
new ManyToOneAssociationField('media', 'media_id', MediaDefinition::class, 'id'),
new TranslationsAssociationField(LogosTranslationDefinition::class, 'logos_id'),
new ManyToManyAssociationField('products', ProductDefinition::class, LogosProductDefinition::class, 'logo_id', 'product_id'),
]);
}
}
As a subscriber I registered the PRODUCT_LOADED_EVENT:
class ProductSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'sales_channel.' . ProductEvents::PRODUCT_LOADED_EVENT => 'salesChannelLoaded',
];
}
public function salesChannelLoaded(SalesChannelEntityLoadedEvent $event): void
{
/** @var SalesChannelProductEntity $product */
$products = $event->getEntities();
foreach ($products as $product) {
$id = $product->getParentId() ? $product->getParentId() : $product->getId();
$criteria = new Criteria([$id]);
$criteria->addAssociation('logos');
$productEntity = $this->productRepository->search($criteria, \Shopware\Core\Framework\Context::createDefaultContext())->first();
$prodExtensions = $productEntity->getExtensions();
if (isset($prodExtensions['logos']) && !empty($prodExtensions['logos'])) {
$logos = $prodExtensions['logos']->getElements();
foreach ($logos as &$logo) {
if ($tLogo->mediaId) {
$mediaEntity = $this->mediaRepository->search((new Criteria([$logo->mediaId])), \Shopware\Core\Framework\Context::createDefaultContext())->first();
$logo->media= $mediaEntity;
}
}
$prodExtensions['logos']->setExtensions($logos);
$product->setExtensions($prodExtensions);
}
}
}
}
Now I have the problem when I access the store API via https://myshop.com/store-api/product/<uuid_product> then I see the extensions “logos” listed, but without any content (without properties montioned in LogosDefinition.php).
"extensions": {
"foreignKeys": {
"apiAlias": "array_struct"
},
"logos": [
{
"_uniqueIdentifier": "baf43ddc20174786bb86c929a3f3c450",
"versionId": null,
"translated": [],
"createdAt": "2023-10-31T06:52:54.851+00:00",
"updatedAt": "2023-11-02T15:36:13.339+00:00",
"extensions": {
"foreignKeys": {
"apiAlias": "array_struct"
}
},
"apiAlias": "logos"
}
]
}
You need to define which fields are visible for the store API in your EntityDefinition, by adding the ApiAware flag.
For example:
class LogosDefinition extends EntityDefinition
{
/* ......... */
protected function defineFields(): FieldCollection
{
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new Required(), new PrimaryKey(), new ApiAware()),
(new StringField('url', 'url'))->addFlags(new Required(), new ApiAware()),
(new TranslatedField('title'))->addFlags(new ApiAware()),
(new FkField('media_id', 'mediaId', MediaDefinition::class))->addFlags(new ApiAware()),
(new ManyToOneAssociationField('media', 'media_id', MediaDefinition::class, 'id'))->addFlags(new ApiAware()),
new TranslationsAssociationField(LogosTranslationDefinition::class, 'logos_id'),
new ManyToManyAssociationField('products', ProductDefinition::class, LogosProductDefinition::class, 'logo_id', 'product_id'),
]);
}
}