Unable to create anonymous cart programatically

Created on 9 August 2017, over 7 years ago
Updated 18 November 2024, 5 months ago

Unable to create cart programmatically under anonymous users.

Working on some custom code to add multiple products to the cart at once. Tried adapting this code: https://www.drupal.org/node/2866020

But even when I use that exact code (swapping out the values at the top for ones relevant to my store), it will not successfully added products under anonymous user unless a cart already exists for the anonymous user. (ie. by adding items using commerce's add-to-cart form, then running custom code to add products.

Furthermore, I can see that the carts are being created with products added, by viewing them under the cart admin page, however, anonymous user's cart is still empty / non-existent; as if cart is not being associated with the anonymous user.

Works just fine for authenticated users, and anonymous users with products already in cart.

Code I'm using (same issue occurs with me using exact code from https://www.drupal.org/node/2866020 as well

function commerce_better_with_add_multiple_to_cart(array $product_ids = array()) {
  $order_type = 'default';

  $entity_manager = \Drupal::entityManager();
  $cart_manager = \Drupal::service('commerce_cart.cart_manager');
  $cart_provider = \Drupal::service('commerce_cart.cart_provider');

  foreach ($product_ids as $variation_id) {
    if ($variation_id <= 0) {
      continue;
    }

    $variation = \Drupal\commerce_product\Entity\ProductVariation::load($variation_id);
    if (!$variation) {
      \Drupal::logger('commerce_better_with')->warning('Failed to add non-existent variation @variation_id to cart on page <a href=":page">:page</a>', array(
        '@variation_id' => $variation_id,
        ':page' => \Drupal\Core\Url::fromRoute('<current>'),
      ));
      continue;
    }

    // Load product variation and get store.
    $variation_price = $variation->getPrice();
    $stores = $variation->getStores();
    $store = reset($stores);

    // get or create cart for the store.
    $cart = $cart_provider->getCart($order_type, $store);
    if (!$cart) {
      $cart = $cart_provider->createCart($order_type, $store);
    }

    $order_item = $entity_manager->getStorage('commerce_order_item')->create([
      'type' => 'default',
      'purchased_entity' => (string) $variation_id,
      'quantity' => 1,
      'unit_price' => $variation_price,
    ]);
    $order_item->save();
    $cart_manager->addOrderItem($cart, $order_item);
  }
}

What am I doing wrong?

💬 Support request
Status

Closed: outdated

Version

2.0

Component

Cart

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    Nowadays with current versions, the solution proposed here is not working anymore. The $session->migrate() does not seem to do anything when the session is not already started...

    In case anybody lands here with that same problem, here is an example of what worked for me :

          // Step 1: Ensure the session is started for anonymous users.
          if ($current_user->isAnonymous()) {
            $session = \Drupal::service('session');
            // If the session is not started, forcefully start it.
            if (!$session->isStarted()) {
              session_start();
            }
          }
    
          // Step 2: Check if there's an existing cart order for the current user session.
          /* @var \Drupal\commerce_cart\CartProviderInterface $cart_provider */
          $cart_provider = \Drupal::service('commerce_cart.cart_provider');
          /* @var \Drupal\commerce_cart\CartManagerInterface $cart_manager */
          $cart_manager = \Drupal::service('commerce_cart.cart_manager');
    
          // Get the current cart if any
          $order = $cart_provider->getCart('default');
    
          // If there's an existing cart order, empty it.
          if (!empty($order)) {
            $cart_manager->emptyCart($order);
          } else {
            // Create a new empty cart if it doesn't exist.
            $order = $cart_provider->createCart('default');
          }
    
          $checkout_url = '/checkout/' . $order->id();
          $response = new RedirectResponse($checkout_url);
          $response->send();
    

    This starts the session first when it was not already to fix the access denied on the checkout for anonymous users!

    The call to createCart() adds the order id to user's cart session, no need to do that manually.

    Hope this helps!

    Thanks!

Production build 0.71.5 2024