Hallo Community,
ich würde gerne die Zusatzfelder auf der Kategorieseite als Filter darstellen. Dazu habe ich versucht mich an die Lösung von den Eigenschaften zu orientieren.
Ich habe 2 Lösungen versucht einmal über customFields und einmal über customFieldsSets, beide hängen am Produkt.
Problem:
- product.customFields
Die Product Entity speichert die customFields als json und ist somit als Array definiert, dazu kommt noch das diese Einträge dynamische key => values beinhalten. Dies ist schon einmal der erste Unterschied gegenüber z.B. den Eigenschaften (properties). Bei diesen ist alles schön in einzelne Entitys verteilt.
Das heißt ich bekomme es nicht ohne großen Aufwand hin das er mir alles aus dem json encodiert und sich alle Informationen,wie bei den Eigenschaften zieht.
- product.customFieldSets
“customFieldsSets” wäre eine Collection, wenn ich diese angebe erhalte ich nur die Id der Collection.
Diese Id könnte ich verwenden und in “custom_field” nachschauen, hier sind aber ebenfalls die Werte als json gespeichert.
Derzeitige® Stand/Lösungen:
1. product.customFields
Mein Event Subscriber:
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
: array
{
return [
ProductListingCollectFilterEvent::class => 'handleFilters',
];
}
public function handleFilters(ProductListingCollectFilterEvent $event)
: void {
$request = $event->getRequest();
$filters = $event->getFilters() ?? new FilterCollection();
$filters->add($this->getCustomFieldFilter($request));
}
private function getCustomFieldFilter(Request $request)
{
$ids = $this->getCustomIds($request);
if (empty($ids)) {
return new Filter(
'custom-fields',
false,
[
new TermsAggregation('customFields', 'product.customFields'),
],
new MultiFilter(MultiFilter::CONNECTION_OR, []),
[],
false
);
}
//TODO: Handle if we have ids
}
private function getCustomIds(Request $request)
: array {
$ids = $request->query->get('custom-fields', '');
if ($request->isMethod(Request::METHOD_POST)) {
$ids = $request->request->get('custom-fields', '');
}
if (\is_string($ids)) {
$ids = explode('|', $ids);
}
return array_filter($ids);
}
Ergebnis im Frontend:
Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection {#5790 ▼
#elements: array:6 [▼
"manufacturer" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult {#6018 ▶}
"price" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\StatsResult {#5942 ▶}
"rating" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\MaxResult {#5903 ▶}
"shipping-free" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\MaxResult {#5947 ▶}
"customFields" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult {#6030 ▼
#buckets: array:2 [▼
0 => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\Bucket {#5950 ▼
#key: "{"custom_easy_car_art": "nw", "custom_easy_car_kilometer": "25000"}"
#count: 1
#result: null
#extensions: []
}
1 => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\Bucket {#5946 ▼
#key: "{"custom_easy_car_art": "gw", "custom_easy_car_oldtimer": "1", "custom_easy_car_kilometer": "15000"}"
#count: 1
#result: null
#extensions: []
}
]
-name: "customFields"
#extensions: []
}
"properties" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult {#5960 ▶}
]
#extensions: []
}
Hier bekomme ich dann nur json in “key” zurück.
2. product.customFields
Mein Event Subscriber:
'handleFilters',
];
}
public function handleFilters(ProductListingCollectFilterEvent $event)
: void {
$request = $event->getRequest();
$filters = $event->getFilters() ?? new FilterCollection();
$filters->add($this->getCustomFieldFilter($request));
}
private function getCustomFieldFilter(Request $request)
{
$ids = $this->getCustomIds($request);
if (empty($ids)) {
return new Filter(
'custom-fields',
false,
[
new TermsAggregation('customFields', 'product.customFieldSets.id'),
],
new MultiFilter(MultiFilter::CONNECTION_OR, []),
[],
false
);
}
//TODO: Handle if we have ids
}
private function getCustomIds(Request $request)
: array {
$ids = $request->query->get('custom-fields', '');
if ($request->isMethod(Request::METHOD_POST)) {
$ids = $request->request->get('custom-fields', '');
}
if (\is_string($ids)) {
$ids = explode('|', $ids);
}
return array_filter($ids);
}
}
Ergebnis im Frontend:
Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection {#5790 ▼
#elements: array:6 [▼
"manufacturer" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult {#6018 ▶}
"price" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\StatsResult {#5942 ▶}
"rating" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\MaxResult {#5903 ▶}
"shipping-free" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\MaxResult {#5947 ▶}
"customFields" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult {#6091 ▼
#buckets: array:1 [▼
0 => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\Bucket {#5946 ▼
#key: "42c39511bf81414fadc0fb54f53a5738"
#count: 2
#result: null
#extensions: []
}
]
-name: "customFields"
#extensions: []
}
"properties" => Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult {#5960 ▶}
]
#extensions: []
}
Hier bekomme ich dann die ID in key zurück.
Fragen:
-
Sind die Zusatzfelder derzeit überhaupt dafür vorgesehen?
-
Wie bekomme ich es hin, dass er alles automatisiert, wie bei den Properties auflöst ? Wahrscheinlich nicht so einfach, oder?
-
Ist der Weg über Entity Extension besser?
Vielen Dank für die Bemühungen und Hilfe!
Viele Grüße
Tobias