Introduction
This section explains how the output-module deals with CustomFields in Shopware. It will also explain how you have to prepare your documents in order to map custom fields to Shopware.
The output-module is able to create and fill CustomFields
and CustomFieldSets
. There is currently the restriction that
only CustomFields of the type "text" can be created. However, the filling of CustomFields of other types is possible.
Basics
The trait AttributeAware
provides an AttributeGroupCollection
. The elements within this collection are used to map custom field
sets and custom fields to Shopware:
- The document
AttributeGroup
is mapped to aCustomFieldSet
-The documentAttribute
(which is "owned" by anAttributeGroup
) is mapped to aCustomField
. The owningAttributeGroup
determines to whichCustomFieldSet
theCustomField
belongs. - The module will create
CustomFieldSets
,CustomFieldSetRelations
andCustomFields
automatically if they are not existing yet. However, this behaviour is configurable. -
CustomFieldSets
andCustomFields
are created "on the fly" as soon as a field/set is found that does not yet exist in Shopware. - CustomFields are filled together with the entity in the upsert request.
- Attributes / CustomFields will always be included in upsert requests. Timestamps of the attributes are ignored.
- Attributes are always converted to custom field values, even if the custom field is not existing in Shopware.
Custom Field Sets
Target: custom_field_set
and custom_field_set_relation
Source: Elio\CommonBundle\Document\Attribute\AttributeGroup
Target Field | Source Path | Comment |
---|---|---|
name | name |
Technical name of the set which is unique in Shopware |
Custom field sets are generated from AttributeGroups
:
- The name of the AttributeGroup (
AttributeGroup::name
) corresponds to the technical name of the custom field set (CustomFieldSet::name
) in Shopware. - All
Attributes
that are part of theAttributeGroup
are converted to a custom field of this set.
Custom Field Set Relations
- Depending on the type of document in which the
AttributeGroup
is embedded, a suitableCustomFieldSetRelation
is generated in
Shopware. - If the same
AttributeGroup
is added to different documents, the module will generate two relations in Shopware. - It is not possible to remove relations. If you remove an
AttributeGroup
from all documents the relation to the product-entity will stay in the shop.
How to Create a Custom Field Set
This example shows you how to create a custom field set in Shopware by the help of an AttributeGroup
.
An AttributeGroup
"synqup_data_set" is assigned to a Product
and a Customer
:
$product = ...;
$customer = ...
$attributeGroup = new AttributeGroup('synqup_data_set');
$product->setAttributeGroups(new AttributeGroupCollection([$attributeGroup]));
$customer->setAttributeGroups(new AttributeGroupCollection([$attributeGroup]));
// persist and flush ...
The module will create a CustomFieldSet
with the technical name "synqup_data_set". The CustomFieldSet
is assigned to the Shopware
entities Product
and Customer
:
Custom Fields
Target: custom_field
Source: Elio\CommonBundle\Document\Attribute\Attribute
Target Field | Source Path |
---|---|
* name |
name - technical name of the custom field field which is unique in Shopware |
type | Always 'text'. Other field-types cannot be created yet |
config | Generated automatically by the module |
customFieldSetId | Determined from the AttributeGroup::name to which the Attribute belongs |
- An
Attribute
, owned by anAttributeGroup
, is converted to aCustomField
. - The custom field is assigned to the custom field set that corresponds to the owning
AttributeGroup
.
How to Create and Fill Custom Fields
This example shows you how to create a custom field and how to fill it with data. The example will use the following code:
$attributeGroup = new AttributeGroup(name: 'synqup_data_set'); # converted to a CustomFieldSet with technical name "synqup_data_set"
$attributeGroup->addAttribute( # converted to a CustomField with technical name "translated_data_field"
new Attribute(
name : 'translated_data_field',
valueLabel: TranslationCollection::create([Locale::en_GB, 'en-GB'], [Locale::de_DE, 'de-DE']) # the value used in translated entities
)
);
$attributeGroup->addAttribute(
new Attribute(
name : 'non_translated_data_field',
value: 'non-translated value' # the value used in non translated entities
)
);
$product = ...;
$customer = ...;
$product->setAttributeGroups(new AttributeGroupCollection([$attributeGroup]));
$customer->setAttributeGroups(new AttributeGroupCollection([$attributeGroup]));
Create Custom Fields
First, lets take a look on how to create a custom field. The following has to be considered:
- The document
Attribute
is mapped to aCustomField
- The 'parent'
AttributeGroup
of theAttribute
determines theCustomFieldSet
theCustomField
will be a part of - The name of the
Attribute
(Attribute::name
) determines the technical name of theCustomField
in Shopware
Following these rules the code from above leads to the following result in the administration panel:
- The module creates two custom fields: "translated_data_field" and "non_translated_data_field".
- The custom fields are assigned to the custom field set that belongs to the owning
AttributeGroup
- in this case "synqup data set"
Fill Custom Fields - Translated and Non-Translated Custom Fields
Regarding the values that are transferred to Shopware you have to distinguish between custom fields that are mapped to translated Shopware entities (e.g. Products) and non-translated entities (e.g. Customers or Orders).
Translated Entities
The following principle applies to entities with translated custom fields (e.g. products):
- The module tries to read a translated value from the
TranslationCollection
atAttribute::valueLabel
. This is done for every mapped language. - The field
Attribute::value
is used as fallback for the default system language - but only if the fieldAttribute::valueLabel
is not available.
Following these rules, this example will lead to the following result in the database (field custom_fields
of
the product_translation
table). This is the result for the system language (de-DE):
{
"translated_data_field": "de-DE",
"non_translated_data_field": "non-translated value"
}
This is the result for the optional language (en-GB):
{
"translated_data_field": "en-GB",
"non_translated_data_field": null
}
- As you can see, the translated values were read from
Attribute::valueLabel
, wherever possible - Since the "non_translated_data_field" does not provide the field
Attribute::valueLabel
, but the fieldAttribute::value
, the value was read fromAttribute::value
For the sake of completeness, this is the result (for the system language de-DE) on the product detail page of the administration panel:
Non-Translated Entities
The following principle applies to entities with non-translated custom fields (e.g. customer or order):
- The value for the custom field is read from the field
Attribute::value
by default. - If the field
Attribute::value
is null, the module tries to read a fallback value from the fieldAttribute::valueLabel
for the system locale. - If both values are set the field
Attribute::value
has higher priority.
Following these rules, this example will lead to the following result in the database (field custom_fields
of the customer
table):
{
"translated_data_field": "de-DE",
"non_translated_data_field": "non-translated value"
}
For the sake of completeness, this is the result on the customer detail page of the administration panel:
Configuration
You can manage how the module handles custom fields via configuration:
{
"customFields":{
"enabled": true,
"autoCreate": true,
"ignore": {...},
"create": {...},
"fill": {...}
}
}
-
enabled
: Controls whether custom fields and -sets are created/filled at all. -
autoCreate
: Controls whether custom fields and -sets are created automatically. -
ignore
: Section to configure which custom fields and -sets are ignored entirely by the module (see "Custom Field Filter") -
create
: Section to configure which custom fields and -sets may be created by the module (see "Custom Field Filter") -
fill
: Section to configure which custom fields and -sets may be filled with values (see "Custom Field Filter")
Custom Field Filter
It is possible to exclude certain custom fields and/or -sets from getting created or filled with data via configuration.
There are three options for your filter available: create
, fill
and ignore
(see below for details).
{
"customFields": {
"...": "...",
"create|fill|ignore": {
"whitelistMode": true|false,
"sets": [
"synqup_data_set",
"..."
],
"fields": [
"translated_data_field",
"non_translated_data_field",
"..."
]
}
}
}
-
whitelistMode
: Configures the filter to act like a whitelist (set totrue
) or ignore-list (set tofalse
)-
true
: The filter behaves like a whitelist. Used to specifically include certain sets and fields. This allows the module to handle only a specific selection of sets and fields. -
false
: The filter behaves like an ignore-list. Used to specifically exclude certain sets and fields. You forbid the module to handle a specific collection of fields and sets.
-
-
sets
: Contains a list of technical names of custom field sets (CustomFieldSetEntity::name
/AttributeGroup::name
) that will be included/excluded during custom field handling. -
fields
: Contains a list of technical names of custom fields (CustomFieldEntity::name
/Attribute::name
) that will be included/excluded during custom field handling.
Note that the identifier custom field is not affected by this configuration.
Create Filter
The create
section is used to configure which custom fields and `custom field sets are automatically created.
Whitelist Mode
-
sets
contains allCustomFieldSets
that are created. ACustomField
contained in aCustomFieldSet
will only be created if it is whitelisted infields
. -
fields
contains all fields that are created. The name of the "parent"CustomFieldSet
must be available insets
, otherwise the field is ignored.
Ignore Mode
-
sets
contains allCustomFieldSets
that are not allowed to be created. AllCustomFields
that are part of one of theseCustomFieldSets
are ignored. -
fields
contains allCustomFields
that are not created automatically. Theparent
set does not have to be included insets
, so you can exclude specific CustomFields from getting created.
Fill Filter
The fill
section is used to configure which CustomFieldSets
and CustomFields
are automatically filled with data.
Whitelist Mode
-
sets
contains allCustomFieldSets
whose "children" (=CustomFields
) are filled with data. AllCustomFields
that are part of theCustomFieldSet
will be whitelisted and filled automatically. In other words: If a set is allowed, every field of the set will be allowed (=filled with data) as well. -
fields
contains allCustomFields
that are filled with data. If the "parent" set is not available insets
thisCustomField
will be filled anyway which makes it possible to allow individualCustomFields
to be filled.
Ignore Mode
-
sets
contains allCustomFieldSets
whose fields are not filled. AllCustomFields
that are part of an ignoredCustomFieldSet
are automatically ignored as well. -
fields
contains allCustomFields
that are not filled with data. Theparent
set does not need to be included insets
which makes it possible to ignore individual fields
Ignore Filter
The ignore
section is used to configure which CustomFieldSets
and CustomFields
are ignored entirely. This is a combination of
the create
and fill
sections.
Warning: If the ignore
section contains at least one element both the create
and fill
sections are ignored entirely. This
section is applied to both the create- and fill-sections.
Different Custom Field Types
As already mentioned it is only possible to create custom fields of type text. However, it is possible to fill custom fields of any type. The following types of custom fields are available in Shopware (07-2022):
- Text field
- Text editor
- Number field (integer or float)
- Number field
- Date/time field
- Checkbox
- Active switch
- Select field with single or multi selection
- Colour picker
- Entity select with single or multi selection
- Media field
- Price field
You can find more information in the documentation of Shopware.
The purpose of this section is to give you a first orientation/example on how to fill custom fields of different types. This is by no means a complete documentation on custom fields in Shopware that covers every edge-case that might come up during filling custom fields of different types.
Attributes
The following example contains Attributes
for every aforementioned custom field type.
$customer = $this->documentManager->find(Customer::class, "604f0a46ca2c165eae7380ee");
$typedCustomFieldSet = new AttributeGroup('typed_custom_field_set');
# text field and text editor
$typedCustomFieldSet->addAttribute(new Attribute('type_text_field', 'text-value'));
$typedCustomFieldSet->addAttribute(new Attribute('type_text_editor', '<b>bold-text </b> - <i>italic-text </i>'));
# number field (integer and float)
$typedCustomFieldSet->addAttribute(new Attribute('type_number_integer', 51));
$typedCustomFieldSet->addAttribute(new Attribute('type_number_float', 5.1));
# datetime
$typedCustomFieldSet->addAttribute(new Attribute('type_date_time', new DateTime()));
# checkbox and active switch
$typedCustomFieldSet->addAttribute(new Attribute('type_checkbox', true));
$typedCustomFieldSet->addAttribute(new Attribute('type_active_switch', false));
#
# select fields
#
# use technical names of the select options
$typedCustomFieldSet->addAttribute(new Attribute('type_select_field', 'select_option_1'));
$typedCustomFieldSet->addAttribute(new Attribute('type_select_field_multi', ['select_option_1', 'select_option_2']));
# color picker
$typedCustomFieldSet->addAttribute(new Attribute('type_colour_picker', '#000000'));
#
# entity selection fields
#
# requires entity uuids
$typedCustomFieldSet->addAttribute(new Attribute('type_entity_select', 'c3a2ca36f912a498f7ba57a50211cbee'));
$typedCustomFieldSet->addAttribute(
new Attribute('type_entity_select_multi', ["c3a2ca36f912a498f7ba57a50211cbee", "780d02994e88edd73ba43ec5273df8c9"])
);
#
# media fields
#
# requires uuid of a media object
$typedCustomFieldSet->addAttribute(new Attribute('type_media', 'd11e8d2dfb9a481081fbfd41778cd35b'));
# price
$price = [
[ "currencyId" => "b7d2554b0ce847cd82f3ac9bd1c0dfca",
"net" => 15.0,
"gross" => 15.0,
"linked" => true,
"listPrice" => null,
"percentage" => null,
"regulationPrice" => null
]
];
$typedCustomFieldSet->addAttribute(new Attribute('type_price_field', $price));
$customer->setAttributeGroups(new AttributeGroupCollection([$typedCustomFieldSet]));
API Request
This is the Sync API request that the module would generate from the example above.
[
{
"action": "upsert",
"entity": "customer",
"payload": [
{
"id": "cba00a6cc2b1360c7bb2d4891aca99ce",
"customFields": {
"type_text_field": "text-value",
"type_text_editor": "<b>bold-text </b> - <i>italic-text </i>",
"type_number_float": 5.1,
"type_number_integer": 51,
"type_date_time": "2030-07-29T12:15:00+00:00",
"type_checkbox": true,
"type_active_switch": true,
"type_select_field": "select_option_1",
"type_select_field_multi": [
"select_option_1",
"select_option_2"
],
"type_colour_picker": "#000000",
"type_entity_select": "c3a2ca36f912a498f7ba57a50211cbee",
"type_entity_select_multi": [
"c3a2ca36f912a498f7ba57a50211cbee",
"780d02994e88edd73ba43ec5273df8c9"
],
"type_media": "d11e8d2dfb9a481081fbfd41778cd35b",
"type_price_field": [
{
"currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca",
"net": 15.0,
"gross": 15.0,
"linked": true,
"listPrice": null,
"percentage": null,
"regulationPrice": null
},
{
"currencyId": "89df0abdbab54dc4858d30777a9226bf",
"net": 18.0,
"gross": 18.0,
"linked": true,
"listPrice": null,
"percentage": null,
"regulationPrice": null
}
]
}
}
]
}
]