Как загрузить корзину текущего пользователя в Commerce 2?
В Commerce 2, как я могу загрузить корзину текущего пользователя? Текущий пользователь может быть либо анонимным, либо авторизованным. На сайте есть несколько магазинов, и я не буду знать, в каком магазине в данный момент находится пользователь.
3 answers
Это зависит от того, что вам действительно нужно. Если вам просто нужны все тележки для всех магазинов, служба поставщика тележек может предоставить вам следующее:
$all_carts = \Drupal::service('commerce_cart.cart_provider')
->getCarts();
Если вам нужна тележка для конкретного магазина в зависимости от контекста, это становится сложнее. Ссылку на "текущий" магазин можно найти через службу текущего магазина:
$store = \Drupal::service('commerce_store.current_store')->getStore();
И корзина, связанная с этим магазином, через поставщика корзины:
$cart = \Drupal::service('commerce_cart.cart_provider')
->getCart('default', $store);
(кстати, во всех приведенных выше фрагментах, если вы можете внедрить эти сервисы в свой текущий контекст вместо использования статических методов, тем лучше).
Проблема заключается в определении коммерцией "текущего" магазина. Из коробки, которая либо поступает от объекта заказа при просмотре заказа, либо является хранилищем по умолчанию. Судя по вашему описанию, ни один из них не справится с этой задачей, поэтому вам нужно будет написать собственный распознаватель магазина.
Я не знаю, какой контекст у вас есть, когда вам нужна сущность корзины, поэтому вот наивный пример, основанный на странице продукта. Так как продукт может находиться в нескольких хранилищах, он просто возвращает первое в массиве.
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;
}
}
И запись для MODULE.services.yml:
MODULE.product_page_store_resolver:
class: Drupal\MODULE\Resolver\ProductPageStoreResolver
arguments: ['@current_route_match']
tags:
- { name: commerce_store.store_resolver, priority: 100 }
Как только вы очистите кэш, первый фрагмент кода выше вернет первый магазин, которому назначен продукт (при его просмотре).
Просто подумайте, может быть, это может быть полезно, чтобы загрузить (последний) заказ в корзину от определенного пользователя по идентификатору, используйте это.
$orders = \Drupal::entityTypeManager()
->getStorage('commerce_order')
->loadByProperties(['uid' => $user_id, 'cart' => '0']);
Но для загрузки корзины как для вошедшего в систему, так и для анонимного пользователя вы должны использовать это
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
$carts = $cart_provider->getCarts();
$order = array_shift($carts);
Чтобы получить корзину текущего пользователя (если у вас только 1 магазин):
$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);
Чтобы получить корзину конкретного пользователя:
$cart = $cart_provider->getCart($order_type, $store, $account);