<p>There is currently no way to populate a cart from a link as a standard feature of Commerce 2.</p>

<p>But you could accomplish this in 2 ways.</p>

<p>1) With a smart template to add all items from the order to the current cart.</p>

<p>Create a template that takes an order number param like so:</p>

<p><code>cart/start-order?number=5bnuy8843nuy48bdy48u3bd84</code></p>

<p>In that template you would do the following:</p>

<pre><code>{# @var craft \craft\web\twig\variables\CraftVariable #}

{% set number = craft.app.request.param('number') %}
{% set previousOrder = craft.orders.number(number).one() %}

{% if not order %}
  {% redirect 'shop' %}
{% endif %}

{# Get the current cart if there is one, also make sure the cart is persisted so we can add to it. #}

{% if cart is not defined %}
  {% set cart = craft.commerce.getCarts().getCart(true) %}
{% endif %}

{# Clears the current cart. This is optional as you may just want to add the items to the cart #}
{% do cart.setLineItems([]) %}

{% for oldLineItem in previousOrder.lineItems %}

  {% set lineItem = craft.commerce.lineitems.createLineItem(cart.id, oldLineItem.purchasableId, oldLineItem.options, oldLineItem.qty, oldLineItem.note) %}

  {% do cart.addLineItem(lineItem) %}

{% endfor %}

{% do craft.app.elements.saveElement(cart) %}

{%  for lineItem in cart.lineItems %}
  {{  lineItem.qty }} * {{ lineItem.description }}
{%  endfor %}
</code></pre>

<p>This add all items from the cart in the email link to the current cart. You would do a similar thing to populate addresses etc if you wish.</p>

<p>2) Alternatively, if you just want to replace the current cart in the users session with the incomplete cart you passed in from the email’s number param, you could do the following</p>

<ul>
<li>Create a plugin/model with a controller action.</li>
<li>The controller action would accept an order number param (like the template example above)</li>
<li>The controller action would do the following:</li>
</ul>

<p>Code:</p>

<pre><code>$request = Craft::$app-&gt;getRequest();
$session = Craft::$app-&gt;getSession();

$number = $request-&gt;getParam('number');
$order = \craft\commerce\elements\Order:find()-&gt;number($number)-&gt;one();

if ($order &amp;&amp; !$order-&gt;isCompleted){
  // Forget the current cart in their session.
  \craft\commerce\Plugin::getInstance()-&gt;getCarts()-&gt;forgetCart();

  $session-&gt;set('commerce_cart', $number);
  return $this-&gt;redirect('shop/cart');
}

return $this-&gt;redirect('shop/cartLoadError');
</code></pre>

<p>This should get you mostly there. Let me know if you have any questions.</p>

CC BY-SA 4.0
2018-11-28T12:30:37.433Z
Thanks for these solutions, Luke! Will there be functionality like this in Commerce (as it's a very common use case), that would make it a better choice to wait a bit?
Paul
CC BY-SA 4.0
2018-11-28T12:10:59.760Z
2018-11-28T12:10:59.760Z
Luke Holder
<p>When using Commerce 2, is there a way to fill a client's cart with the contents of an (inactive) cart, by using a link? Use case: abandoned cart email.</p>

<plugin-craftcommerce2>
(How) can I fill a visitor's cart by using a link?
# (How) can I fill a visitor's cart by using a link?

(Asked by: username_0 on 2018-11-08)

When using Commerce 2, is there a way to fill a client's cart with the contents of an (inactive) cart, by using a link? Use case: abandoned cart email.

**Tags:** plugin-craftcommerce2

---

## 1 answers

### Answer by username_1 on 2018-11-28. Score: 4 | Accepted answer

There is currently no way to populate a cart from a link as a standard feature of Commerce 2.
But you could accomplish this in 2 ways.
1) With a smart template to add all items from the order to the current cart.
Create a template that takes an order number param like so:
cart/start-order?number=5bnuy8843nuy48bdy48u3bd84
In that template you would do the following:
{# @var craft \craft\web\twig\variables\CraftVariable #}

{% set number = craft.app.request.param('number') %}
{% set previousOrder = craft.orders.number(number).one() %}

{% if not order %}
  {% redirect 'shop' %}
{% endif %}

{# Get the current cart if there is one, also make sure the cart is persisted so we can add to it. #}

{% if cart is not defined %}
  {% set cart = craft.commerce.getCarts().getCart(true) %}
{% endif %}

{# Clears the current cart. This is optional as you may just want to add the items to the cart #}
{% do cart.setLineItems([]) %}

{% for oldLineItem in previousOrder.lineItems %}

  {% set lineItem = craft.commerce.lineitems.createLineItem(cart.id, oldLineItem.purchasableId, oldLineItem.options, oldLineItem.qty, oldLineItem.note) %}

  {% do cart.addLineItem(lineItem) %}

{% endfor %}

{% do craft.app.elements.saveElement(cart) %}

{%  for lineItem in cart.lineItems %}
  {{  lineItem.qty }} * {{ lineItem.description }}
{%  endfor %}

This add all items from the cart in the email link to the current cart. You would do a similar thing to populate addresses etc if you wish.
2) Alternatively, if you just want to replace the current cart in the users session with the incomplete cart you passed in from the email’s number param, you could do the following

Create a plugin/model with a controller action.
The controller action would accept an order number param (like the template example above)
The controller action would do the following:

Code:
$request = Craft::$app->getRequest();
$session = Craft::$app->getSession();

$number = $request->getParam('number');
$order = \craft\commerce\elements\Order:find()->number($number)->one();

if ($order && !$order->isCompleted){
  // Forget the current cart in their session.
  \craft\commerce\Plugin::getInstance()->getCarts()->forgetCart();

  $session->set('commerce_cart', $number);
  return $this->redirect('shop/cart');
}

return $this->redirect('shop/cartLoadError');

This should get you mostly there. Let me know if you have any questions.

> **Comments:**
> **username_0**: Thanks for these solutions, Luke! Will there be functionality like this in Commerce (as it's a very common use case), that would make it a better choice to wait a bit?  

---

