In Commerce 2, how can I load the current user's cart? The current user may be either anonymous or logged in. The site has multiple stores and I won't know which store the user is currently on.
3 Answers
It depends what you need, really. If you just need all carts for all stores, the cart provider service can give you that:
$all_carts = \Drupal::service('commerce_cart.cart_provider')
->getCarts();
If you need a cart for a particular store based on context, it gets trickier. A reference to the "current" store can be found via the current store service:
$store = \Drupal::service('commerce_store.current_store')->getStore();
And the cart related to that store via the cart provider:
$cart = \Drupal::service('commerce_cart.cart_provider')
->getCart('default', $store);
(incidentally in all the above snippets, if you can inject those services into your current context instead of using the static methods, all the better).
The problem is in Commerce's definition of a "current" store. Out of the box that either comes from the order entity when viewing an order, or it's the default store. From your description neither of those will do the job, so you'll need to write a custom store resolver.
I don't know what context you have available when needing the cart entity, so here's a naive example based on a product page. Since a product can be in more than one store, it just returns the first in the array.
namespace Drupal\MODULE\Resolver;
use Drupal\commerce_product\Entity\ProductInterface;
use Drupal\commerce_store\Resolver\StoreResolverInterface;
use Drupal\Core\Routing\RouteMatchInterface;
class ProductPageStoreResolver implements StoreResolverInterface {
protected $routeMatch;
public function __construct(RouteMatchInterface $route_match) {
$this->routeMatch = $route_match;
}
public function resolve() {
$product = $this->routeMatch->getParameter('commerce_product');
if ($product instanceof ProductInterface) {
$stores = $product->getStores();
return reset($stores);
}
return NULL;
}
}
And the entry for MODULE.services.yml:
services:
MODULE.product_page_store_resolver:
class: Drupal\MODULE\Resolver\ProductPageStoreResolver
arguments: ['@current_route_match']
tags:
- { name: commerce_store.store_resolver, priority: 100 }
Once you clear the cache, the first code snippet above will return the first store a product is assigned (when viewing it).
-
Thank you for your detailed answer. The information you provided will definitely be helpful to me but I'm not sure that it helps with my immediate issue. Is there no way to just get the current user's cart? In Commerce 1 you could simply use commerce_cart_order_load(). Feb 9, 2018 at 18:07
-
1There’s no such concept any more; a cart (which is an order) has to be related to a store, and if you have multiple stores you have to tell Commerce which one you want to make a query for. Someone involved in development would probably be able to tell you for sure, but I had a good look over the code last night and I’m pretty sure I’m right– Clive ♦Feb 9, 2018 at 18:44
-
Okay. Thanks for the additional info. I'm still trying to grasp the new 'cart/store' relation concept but your info helps a lot. Feb 9, 2018 at 19:07
Just think maybe this could be useful, to load (last)cart order from specific user by id, use this.
$orders = \Drupal::entityTypeManager()
->getStorage('commerce_order')
->loadByProperties(['uid' => $user_id, 'cart' => '0']);
But to load cart for both logged in and anonymous user you should use this
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
$carts = $cart_provider->getCarts();
$order = array_shift($carts);
-
The above loads cart with a value of 0 for the user in Commerce 2.12 for me. To load all a users carts I had to remove the cart property:
$orders = \Drupal::entityTypeManager() ->getStorage('commerce_order') ->loadByProperties(['uid' => $user_id]);
to get all orders of a user.– tenkenApr 10, 2019 at 15:43 -
1That is correct, it loads only last cart, so to get all of them, what you say is correct, I fixed wording a bit to properly reflect code.– BlissfulJun 6, 2019 at 14:46
-
I made and edit and added answer for both user 0 and logged in users.– BlissfulOct 15, 2020 at 10:13
to get current user's cart (if you only have 1 store):
$store = \Drupal\commerce_store\Entity\Store::load(1);
$order_type = 'default';
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
$cart = $cart_provider->getCart($order_type, $store);
to get specific user's cart:
$cart = $cart_provider->getCart($order_type, $store, $account);