Was looking for this code just now, so figured I’d post it here even though it’s a rather old topic Sorry for not getting back to you before.
First, load up Commerce and the current order
<?php
use modmore\Commerce\Frontend\Checkout\Standard;
use modmore\Commerce\Frontend\Steps\Cart;
// Instantiate the Commerce class
$path = $modx->getOption('commerce.core_path', null, MODX_CORE_PATH . 'components/commerce/') . 'model/commerce/';
$params = ['mode' => $modx->getOption('commerce.mode')];
/** @var Commerce|null $commerce */
$commerce = $modx->getService('commerce', 'Commerce', $path, $params);
if (!($commerce instanceof Commerce)) {
return '<p class="error">Oops! It is not possible to view your cart currently. We\'re sorry for the inconvenience. Please try again later.</p>';
}
if ($commerce->isDisabled()) {
return $commerce->adapter->lexicon('commerce.mode.disabled.message');
}
$order = \comOrder::loadUserOrder($commerce);
Following that, there’s a few things we can do with the order.
Option 1: Add a product by its ID to the cart; this is exactly the same as a regular add to cart request:
$productId = 1234; // Change this ;)
$process = new Standard($commerce, $order);
$process->currentKey = 'cart';
$cartStep = new Cart($process, []);
$cartStep->setOrder($order);
$cartStep->addProductToCart($productId, ['quantity' => 1]);
// Redirect to the cart or something
Option 2: create an order item based on an existing product, but tweak our item as needed
$product = $commerce->adapter->getObject('comProduct', ['id' => 1234]);
if (!($product instanceof comProduct)) {
return 'Could not find product';
}
$item = $commerce->adapter->newObject('comOrderItem');
// This will set the product ID, sku, name, link, description, price,
// image, delivery_type and tax_group for you
$item->fromProduct($product);
// Add extra info into the properties (note, not indexed/searchable)
$item->setProperty('occasion', 'Easter');
// Or change an item, like set a different name and price:
$item->set('name', 'Product Deluxe');
$item->set('price', $item->get('price') + 2500);
// IMPORTANT: if you change the price while the item is linked to a
// product (through `fromProduct` or setting `product`), you need to
// mark the price as manual to prevent Commerce automatically
// reverting it to the normal product price:
$item->set('is_manual_price', true);
// Add to order
$order->addItem($item);
Option 3: create an order item without a product reference:
$item = $commerce->adapter->newObject('comOrderItem');
$item->set('currency', $order->get('currency'));
$item->fromArray([
'delivery_type' => $deliveryTypeId,
'tax_group' => $taxGroupId,
'sku' => 'Product Code',
'name' => 'Name',
'description' => '...',
'price' => 1334, // in cents!!
'quantity' => 1,
]);
$order->addItem($item);
This logic deals with adding custom order items to the cart. You can add properties (as shown in the option 2 example) which will be automatically available in emails in the item.properties
array.
When using the ItemData module you can also get arbitrary data to be stored with an order item, without using a custom snippet like this, and that also has the benefit of showing the information in the backend and cart automatically as well. If you want to achieve the same with custom add to cart logic, you’ll want to take a peek into core/components/commerce/src/Modules/Cart/ItemData.php
to see how it’s doing that.