Zum Hauptinhalt springen
Version: 2026.10

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 KlasseBeschreibung
AbstractProductExtensionDefinitionDefinition 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
AbstractProductExtensionEntityEntität mit pimcoreId, product und translations
Aggregate\ProductExtensionTranslation\AbstractProductExtensionTranslationEntityOptionale Übersetzungs-Entität
AbstractProductExtensionErgänzt die Assoziation productExtension an der Produkt-Entität
vorsicht

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​

NameBeschreibung
getEntityClass(): stringKlasse der konkreten Entität
getProductExtensionTranslationDefinitionClass(): stringKlasse der konkreten Übersetzungs-Definition
getAdditionalFields(): arrayProjektspezifische 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
}
Hinweis

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​

NameBeschreibung
getParentDefinitionClass(): stringKlasse 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;
Hinweis

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

TabellePflichtspaltenEigene Spalten
twocream_product_extensionid, pimcore_id, created_at, updated_atFelder aus getAdditionalFields()
twocream_product_extension_translationtwocream_product_extension_id, language_id, created_at, updated_atFelder aus getAdditionalTranslatedFields()
Hinweis

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.