Produkt-Extension
Überblick
Für Produktdaten, die nicht in der Shopware Produkt-Entität abgebildet werden können, stellt das Plugin ab Version 3.0.0 abstrakte Klassen für die Entität twocream_product_extension inkl. Übersetzungstabelle bereit. Die Produkt-Extension wird über eine 1:1-Assoziation productExtension mit dem Produkt verknüpft und kann direkt über den Produkt-Import geschrieben werden (siehe "Produkt-Import"). Die Felder werden im Produkt-Modul über getProductExtensionFieldMap() und getProductExtensionTranslationKeyMap() den Schlüsseln aus product-extension zugeordnet, in Pimcore liefert sie der Produkt-Adapter unter product-extension (siehe "Produkt-Export aufbauen").
Alle Klassen liegen im Namespace Twocream\JsonImporter\Core\Content\Product\ProductExtension.
| Abstrakte Klasse | Beschreibung |
|---|---|
AbstractProductExtensionDefinition | Definition mit den Feldern id, pimcore_id, created_at, updated_at und den Assoziationen product und translations. Eigene Felder werden über getAdditionalFields() ergänzt |
Aggregate\ProductExtensionTranslation\AbstractProductExtensionTranslationDefinition | Übersetzungs-Definition für twocream_product_extension_translation. Eigene Felder werden über getAdditionalTranslatedFields() ergänzt |
AbstractProductExtensionEntity | Entität mit pimcoreId, product und translations |
Aggregate\ProductExtensionTranslation\AbstractProductExtensionTranslationEntity | Optionale Übersetzungs-Entität |
AbstractProductExtension | Ergänzt die Assoziation productExtension an der Produkt-Entität |
Das Plugin registriert keine dieser Klassen und legt keine Tabellen an. Die konkreten Klassen, die Service-Registrierung und die Migration sind im Projekt umzusetzen.
Konkrete Klassen
Je abstrakter Klasse ist im Projekt eine konkrete Klasse anzulegen. Die konkrete Entität muss dabei von AbstractProductExtensionEntity erben.
Definition
| Name | Beschreibung |
|---|---|
getEntityClass(): string | Klasse der konkreten Entität |
getProductExtensionTranslationDefinitionClass(): string | Klasse der konkreten Übersetzungs-Definition |
getAdditionalFields(): array | Projektspezifische Felder, inkl. TranslatedFields für übersetzbare Felder und weiterer Assoziationen |
<?php
namespace MyCustomExtension\Core\Content\Product\ProductExtension;
use MyCustomExtension\Core\Content\Product\ProductExtension\Aggregate\ProductExtensionTranslation\ProductExtensionTranslationDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\TranslatedField;
use Twocream\JsonImporter\Core\Content\Product\ProductExtension\AbstractProductExtensionDefinition;
class ProductExtensionDefinition extends AbstractProductExtensionDefinition
{
public function getEntityClass(): string
{
return ProductExtensionEntity::class;
}
protected function getProductExtensionTranslationDefinitionClass(): string
{
return ProductExtensionTranslationDefinition::class;
}
protected function getAdditionalFields(): array
{
return [
new StringField('business_area', 'businessArea'),
new TranslatedField('subtitle'),
];
}
}
Entität
<?php
namespace MyCustomExtension\Core\Content\Product\ProductExtension;
use Twocream\JsonImporter\Core\Content\Product\ProductExtension\AbstractProductExtensionEntity;
class ProductExtensionEntity extends AbstractProductExtensionEntity
{
protected ?string $businessArea = null;
protected ?string $subtitle = null;
// Getter und Setter
}
pimcoreId ist in der Entität als int definiert. Beim Schreiben der Produkt-Extension ist pimcoreId daher immer mitzugeben – der Produkt-Import übernimmt das automatisch.
Für die oben gezeigten Felder lauten die Maps im Produkt-Modul:
protected function getProductExtensionFieldMap(): array
{
return ['business-area' => 'businessArea'];
}
protected function getProductExtensionTranslationKeyMap(): array
{
return ['subtitle' => 'subtitle'];
}
Übersetzungs-Definition
| Name | Beschreibung |
|---|---|
getParentDefinitionClass(): string | Klasse der konkreten Definition der Produkt-Extension |
getAdditionalTranslatedFields(): array | Übersetzbare Felder, als Gegenstück zu den TranslatedFields der Definition |
<?php
namespace MyCustomExtension\Core\Content\Product\ProductExtension\Aggregate\ProductExtensionTranslation;
use MyCustomExtension\Core\Content\Product\ProductExtension\ProductExtensionDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\LongTextField;
use Twocream\JsonImporter\Core\Content\Product\ProductExtension\Aggregate\ProductExtensionTranslation\AbstractProductExtensionTranslationDefinition;
class ProductExtensionTranslationDefinition extends AbstractProductExtensionTranslationDefinition
{
protected function getParentDefinitionClass(): string
{
return ProductExtensionDefinition::class;
}
protected function getAdditionalTranslatedFields(): array
{
return [
new LongTextField('subtitle', 'subtitle'),
];
}
}
Extension
<?php
namespace MyCustomExtension\Core\Content\Product;
use MyCustomExtension\Core\Content\Product\ProductExtension\ProductExtensionDefinition;
use Twocream\JsonImporter\Core\Content\Product\ProductExtension\AbstractProductExtension;
class ProductExtension extends AbstractProductExtension
{
protected function getProductExtensionDefinitionClass(): string
{
return ProductExtensionDefinition::class;
}
}
Klassen registrieren
Die Definitionen und die Extension sind in der Service-Konfiguration des Projekts zu registrieren:
<service id="MyCustomExtension\Core\Content\Product\ProductExtension\ProductExtensionDefinition">
<tag name="shopware.entity.definition" entity="twocream_product_extension"/>
</service>
<service id="MyCustomExtension\Core\Content\Product\ProductExtension\Aggregate\ProductExtensionTranslation\ProductExtensionTranslationDefinition">
<tag name="shopware.entity.definition" entity="twocream_product_extension_translation"/>
</service>
<service id="MyCustomExtension\Core\Content\Product\ProductExtension">
<tag name="shopware.entity.extension"/>
</service>
Sobald Definition und Extension registriert sind, lädt der Produkt-Import bei bestehenden Produkten die Assoziation productExtension automatisch mit. Für deaktivierte Varianten ohne eigenen Löscheintrag wird im Report zudem die Pimcore-ID der Produkt-Extension ausgegeben.
Migration
Die Tabellen sind über eine Migration im Projekt anzulegen. Beispiel für die oben gezeigten Felder:
CREATE TABLE IF NOT EXISTS `twocream_product_extension` (
`id` BINARY(16) NOT NULL,
`pimcore_id` INT NULL,
`business_area` VARCHAR(255) NULL,
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `twocream_product_extension_translation` (
`twocream_product_extension_id` BINARY(16) NOT NULL,
`language_id` BINARY(16) NOT NULL,
`subtitle` LONGTEXT NULL,
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`twocream_product_extension_id`, `language_id`),
CONSTRAINT `fk.twocream_product_extension_translation.twocream_product_extension_id`
FOREIGN KEY (`twocream_product_extension_id`)
REFERENCES `twocream_product_extension` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk.twocream_product_extension_translation.language_id` FOREIGN KEY (`language_id`)
REFERENCES `language` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Die Tabelle twocream_product_extension besitzt bewusst keinen Fremdschlüssel auf product. Die Produkt-Tabelle besitzt den Primärschlüssel (id, version_id), ein Fremdschlüssel auf einen Teil davon passt nicht zur Versionierung. Die ID der Produkt-Extension entspricht der ID des Produkts.
Daher werden die Einträge eines gelöschten Produkts nicht automatisch entfernt – das Aufräumen ist Aufgabe des Projekts. Der Produkt-Import selbst löscht keine Produkte, sondern deaktiviert sie.
Die Übersetzungstabelle verweist mit ON DELETE CASCADE auf twocream_product_extension (id) und language (id).
| Tabelle | Pflichtspalten | Eigene Spalten |
|---|---|---|
twocream_product_extension | id, pimcore_id, created_at, updated_at | Felder aus getAdditionalFields() |
twocream_product_extension_translation | twocream_product_extension_id, language_id, created_at, updated_at | Felder aus getAdditionalTranslatedFields() |
Bestehende Projekte mit einer eigenen Produkt-Extension für twocream_product_extension können ihre Klassen auf die abstrakten Klassen umstellen. Tabellen- und Spaltennamen bleiben dabei unverändert, eine Schemaänderung ist nicht notwendig.