TransWikia.com

Update Cart’s address ID from plugin

Craft CMS Asked on April 13, 2021

I want to try and stop Commerce 3 creating a new customer address if it’s a duplicate of an existing one.

As an example, a store selling digital products has a checkout form that simply asks for the customer’s country, no other address info is required. All we need is one select field for the country (pre-checked if we already have that info). We could add radio buttons to select any previously saved addresses as well as a field to select a (new) country. However, even if we do that, there’s still a chance the user opts to enter a new address and actually submits a duplicate.

I’ve created a plugin that catches a duplicate address and then tries to set the cart’s billingAddressId so a new address isn’t created. What I have so far though doesn’t work. It doesn’t successfully update the billingAddressId. If I use Craft::$app->getElements()->saveElement($cart) it results in a loop in this case.

How can I complete this to update the cart, or perhaps the post data in this case, with the matched billingAddressId?

Event::on(Address::class, Address::EVENT_BEFORE_VALIDATE, function (Event $e) {

    $sentCountryId = $e->sender->countryId;
    $currentUser = Craft::$app->user;
    $cart = craftcommercePlugin::getInstance()->getCarts()->getCart();
    $addresses = $cart->customer->addresses;
    $match = 0;

    // Only check against saved addresses if currentUser has any
    if ($currentUser and $addresses) {

        // If true, loop saved address to check for a country match
        foreach($addresses as $address) {

            // Loop until a match is found
            if ($match == 0) {

                $savedCountryId = $address->countryId;

                if ($sentCountryId == $savedCountryId) {
                    $match = $address->id;
                }

            }

        };

        // If there’s a match set the cart’s billingAddressId
        // to stop a new address being created:
        if ($match) {

            $cart->billingAddressId = $match; // This doesn’t work on it’s own
            // Craft::$app->getElements()->saveElement($cart); // Results in a loop
            $e->handled = true;

        }

    }

});

One Answer

If I am reading you right you are wanting to update the shipping address on the order rather than create a new one.

You should be able to do that right now:

{% set cart = craft.commerce.carts.cart %}

{% set flashNotice = craft.app.session.getFlash('notice') %}

{% if flashNotice %}
    <div class="bg-blue-500 text-white">
        <div class="flash container mx-auto px-6 py-4">
            {{ flashNotice }}
        </div>
    </div>
{% endif %}

{% set flashError = craft.app.session.getFlash('error') %}

{% if flashError %}
<div class="bg-red-500 text-white">
  <div class="flash container mx-auto px-6 py-4">
    {{ flashError }}
  </div>
</div>
{% endif %}


//meat and potatoes:


{{ cart.number }}<br>

Shipping Address ID: {{ cart.shippingAddressId }}

<form method="post">
  <input type="hidden" name="action" value="commerce/cart/update-cart"/>
  <input type="hidden" name="cartUpdatedNotice" value="The address was updated.">
  {{ redirectInput('shop/address') }}
  {{ csrfInput() }}

  <!-- THIS IS WHAT WILL UPDATE THE ADDRESS VS ADDING A NEW ONE -->
  {% if cart.shippingAddress.id %}
  <input type="hidden" name="shippingAddress[id]" value="{{cart.shippingAddress.id}}"/>
  {% endif %}

  First Name:
  <input name="shippingAddress[firstName]" value="{{cart.shippingAddress.firstName ?? ''}}"/>

  <button type="submit">Update</button>
</form>

As demonstrated above, using an input with name="shippingAddress[id]" with the address ID set as the value will update the address with that ID on the commerce/cart/update-cart controller action just fine.

You would only use name="shippingAddressId" if you wanted to let the user select an existing one.

Answered by Luke Holder on April 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP