Does anynone knows how can we set a custom field for a line item?
We notice that we can set per Payment, Shipping, …but not for a cart line item.
We checked ‚Shopware\Core\Checkout\Cart\LineItem‘ but there are no setter/getter and no variable.
We need to save additional data to cart line item and we want this data to be persistent within order line items too.
Does anyone knows how to achieve that? Maybe by extending Shopware\Core\Checkout\Cart\LineItem and implement there setter/getter. We notice that ‚order_line_item‘ table does have a ‚custom_fields‘ field.
If i use Javascript fetch and the Shopware 6 - Sales-Channel API with POST /sales-channel-api/v1/checkout/cart/product/{id} from the Documentation* to add products. But there is no example or explenation how to use the payload or how it sould look like to set/write the customFields?
Achieving this in the current state of shopware 6 seems to be quite a tedious task.
I was surprised this was rather difficult to achieve as it seems quite a common use case when working with eCommerce frameworks, especially within the enterprise sector.
To be able to store information on order item level I had to do the following (for sure this might not be best practice but it works, maybe it will help somebody):
Find a way to add custom data to your cart (line) items.
Line items are stored inside the cart table, to be specific in a serialized form inside the cart column.
(This implementation for sure raises some questions but it is what it is, I guess)
You want to find a way to add custom data to the line items stored there. In my case I rewrote the CartLineItemController (\Shopware\Storefront\Controller\CartLineItemController::addLineItems) to store additional data on line item level.
Create a new Struct class (inheriting from \Shopware\Core\Framework\Struct\Struct) that will then be used to extend a line item (at the point where you add your custom data).
Add your custom data to the line item via your newly created custom struct. It works like this:
$lineItem->addExtension(‘my_custom_struct’, new MyCustomStruct($myCustomData));
Finally, as the custom data is now stored inside the cart item you want to make sure it gets copied to the order line items (table order_line_item) when the order gets placed.
For that further rewriting is required.
I rewrote \Shopware\Core\Checkout\Cart\Order\Transformer\LineItemTransformer::transform for this.
You can utilize custom fields as per documentation (https://docs.shopware.com/en/shopware-platform-dev-en/internals/core/data-abstraction-layer/custom-field), as they are supported for order line items.
if ($lineItem->getExtension(‘my_custom_struct’)) {
$myCustomFieldData = [‘my_custom_field’ => $lineItem->getExtension(‘my_custom_struct’)->getMyCustomData()];
}
The CartLineItems have a property named payload where product custom fields and such things are stored within. In my case I used the LineItemAddedEvent to modify this payload.
e.g.
/**
* @param LineItemAddedEvent $event
* @throws \Shopware\Core\Checkout\Cart\Exception\InvalidPayloadException
*/
public function onLineItemAdded(LineItemAddedEvent $event): void
{
$lineItem = $event->getLineItem();
foreach ($this->requestStack->getCurrentRequest()->get('lineItems') as $key => $item) {
if ($lineItem->getId() == $key && isset($item['anotherCartFormValue'])) {
$lineItem->setPayloadValue('anotherCartFormValue', $item['anotherCartFormValue']);
}
}
// or do some other stuff with the payload
}
This payload will be used in any step of the checkout without getting overwritten anymore, and is stored in the cart table.
The CartLineItems have a property named payload where product custom fields and such things are stored within. In my case I used the LineItemAddedEvent to modify this payload.
Wow, how could I miss this. The payload approach is definitely less obtrusive and a lot easier to implement.
is it possible to display this updated payload in order line item in admin ?
Yes. It comes with the order line item. You can display it in the backend by overwriting e.g. sw-order-detail-base.html.twig like this (might not look pretty, but you get the idea):