1

Drupal: 8.7.2 Commerce: 2.13

I have a custom module set up that adds the following functionality to Commerce:

  1. It prevents the user from adding more than one item to their cart. If they try to add a second item, it removes the first item from their cart and adds the second item.

  2. When clicking "Add to Cart", it redirects the user to a confirmation page.

  3. On that page is a button that links to the order's checkout page.

I am handling all of these via queries that use the user ID and order ID to pull the correct order/cart information.

This all works great for logged in users. Most of our customers will be anonymous, though. It does work for anonymous users, but my concern is that if multiple anonymous users are placing orders at the same time, their carts will get mixed up, because all anonymous users have a UID of 0.

How can I better differentiate between anonymous user's carts? Is there a way to store their IP in the database, and then use that?

Here is my module's code:

commerce_custom.module (handles removing first item from cart, redirecting to confirmation page):

<?php


use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_order\Entity\Order;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_custom_form_commerce_order_item_add_to_cart_form_alter(&$form, FormStateInterface $form_state, $form_id) {
   $form['actions']['submit']['#value']='Sponsor';
   $form['#validate'][] = 'commerce_custom_form_validate';
   $form['actions']['submit']['#submit'][] = 'commerce_custom_cart_alter_redirect';
}

function commerce_custom_form_validate(array &$form, FormStateInterface $form_state) {

    $user = \Drupal::currentUser()->id();
    $connection = \Drupal::database();
    $query = $connection->query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' => $user]);
    $result = $query->fetchAll();
    //dpm($result);

    $cart_count = $result[0]->quantity;
    $order_id = $result[0]->order_id;

    if ($cart_count > 0 && $order_id) {
        $order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id);
        $items = $order->getItems();
        foreach($items as $item_key => $item) {
            $order->removeItem($item);
            $item->delete();
        }
    }
}

function commerce_custom_cart_alter_redirect(&$form, FormStateInterface $form_state) {
  $responce =  new RedirectResponse('/how-it-works');
  $responce->send();
}

ContinueCheckoutBlock.php (creates block with button linking to checkout page):

<?php

namespace Drupal\commerce_custom\Plugin\Block;
use Drupal\Core\Block\BlockBase;

class ContinueCheckoutBlock extends BlockBase {

   public function build() {

        $user = \Drupal::currentUser()->id();
        $connection = \Drupal::database();
        $query = $connection->query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' => $user]);
        $result = $query->fetchAll();
        $order_id = $result[0]->order_id;

        return array(
            '#type' =>'markup',
            '#markup' => '<a href=checkout/' . $order_id . '/order_information class=button>Continue</a>',
        );
   }
}
  • I’m curious if it would be feasible for you to use JavaScript to store data in localStorage, and then use localStorage to populate form data? This would give you anonymous usage in the scope of users clearing their browser cache. I’m not sure how feasible it is to store anonymous data beyond that... – Prestosaurus Jun 19 at 19:56
  • So, I found a way to use the IP. It ends up that the IP is stored in the drupal commerce data - I don't know why I didn't see that before. The issue I am having now is that the block is cached, and is pulling in old data until the cache is cleared. Do you know of a way to prevent it from being cached? – Kimberlie Davis Jun 24 at 15:46
0

Perhaps you could use PHP's session_id()?

session_id() is used to get or set the session id for the current session.

Basically copied from this answer.


You may also find useful information here: Anonymous Personalization Without Leaving Drupal, which appears to be a topic from DrupalCon Seattle 2019.

  • So, I found a way to use the IP. It ends up that the IP is stored in the drupal commerce data - I don't know why I didn't see that before. – Kimberlie Davis Jun 24 at 15:45
  • The issue I am having now is that the block is cached, and is pulling in old data until the cache is cleared. Do you know of a way to prevent it from being cached? – Kimberlie Davis Jun 24 at 15:46
  • Note that using a user's IP may not be wise, because of the GDPR law. – mbomb007 Jun 24 at 16:12
  • Why don't you just clear the specific data from the cache after saving? – mbomb007 Jun 24 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.