Answers.Body: <p>If I am reading you right you are wanting to update the shipping address on the order rather than create a new one. </p>
  
  <p>You should be able to do that right now:</p>
  
  <pre><code>{% set cart = craft.commerce.carts.cart %}
  
  {% set flashNotice = craft.app.session.getFlash('notice') %}
  
  {% if flashNotice %}
      &lt;div class="bg-blue-500 text-white"&gt;
          &lt;div class="flash container mx-auto px-6 py-4"&gt;
              {{ flashNotice }}
          &lt;/div&gt;
      &lt;/div&gt;
  {% endif %}
  
  {% set flashError = craft.app.session.getFlash('error') %}
  
  {% if flashError %}
  &lt;div class="bg-red-500 text-white"&gt;
    &lt;div class="flash container mx-auto px-6 py-4"&gt;
      {{ flashError }}
    &lt;/div&gt;
  &lt;/div&gt;
  {% endif %}
  
  
  //meat and potatoes:
  
  
  {{ cart.number }}&lt;br&gt;
  
  Shipping Address ID: {{ cart.shippingAddressId }}
  
  &lt;form method="post"&gt;
    &lt;input type="hidden" name="action" value="commerce/cart/update-cart"/&gt;
    &lt;input type="hidden" name="cartUpdatedNotice" value="The address was updated."&gt;
    {{ redirectInput('shop/address') }}
    {{ csrfInput() }}
  
    &lt;!-- THIS IS WHAT WILL UPDATE THE ADDRESS VS ADDING A NEW ONE --&gt;
    {% if cart.shippingAddress.id %}
    &lt;input type="hidden" name="shippingAddress[id]" value="{{cart.shippingAddress.id}}"/&gt;
    {% endif %}
  
    First Name:
    &lt;input name="shippingAddress[firstName]" value="{{cart.shippingAddress.firstName ?? ''}}"/&gt;
  
    &lt;button type="submit"&gt;Update&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>As demonstrated above, using an input with <code>name="shippingAddress[id]"</code> with the address ID set as the value will update the address with that ID on the <code>commerce/cart/update-cart</code> controller action just fine.</p>
  
  <p>You would only use <code>name="shippingAddressId"</code> if you wanted to let the user select an existing one. </p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-08T11:31:49.917Z
Answers.Text: Let me know if I am not understanding.
Answers.UserDisplayName: Luke Holder
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-08T12:11:10.850Z
Answers.Text: Thanks Luke. Appreciate it’s perhaps not that common but there’s a situation (at least in our checkout process) where a duplicate address is more likely. For example, in our simple form rather than display previous addresses and give the option to add a new one. It just asks for the billingAddress[countryId]. That’s it. So that form opens up the likelihood of duplicates if they’ve checked out before, or have to go back a step in the process and submit the same form twice. Therefore, I’m trying to check against existing  addresses on the plugin side.
Answers.UserDisplayName: James
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-08T12:13:10.993Z
Answers.Text: Also, less likely to happen but even with radio buttons to select a saved address, they could still opt to enter a new one and input a duplicate. Or maybe I’m missing something?
Answers.UserDisplayName: James
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-09T10:11:12.703Z
Answers.Text: I’ve updated the question to hopefully make it clearer. I still think there’s a need to catch duplicates.
Answers.UserDisplayName: James
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-08T11:26:51.070Z
Answers.LastActivityDate: 2020-04-08T11:26:51.070Z
Answers.UserDisplayName: Luke Holder
Body: <p>I want to try and stop Commerce 3 creating a new customer address if it’s a duplicate of an existing one.</p>
  
  <p>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 <em>could</em> 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.</p>
  
  <p>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 <code>billingAddressId</code>. If I use <code>Craft::$app-&gt;getElements()-&gt;saveElement($cart)</code> it results in a loop in this case.</p>
  
  <p>How can I complete this to update the cart, or perhaps the post data in this case, with the matched <code>billingAddressId</code>?</p>
  
  <pre><code>Event::on(Address::class, Address::EVENT_BEFORE_VALIDATE, function (Event $e) {
  
      $sentCountryId = $e-&gt;sender-&gt;countryId;
      $currentUser = Craft::$app-&gt;user;
      $cart = craft\commerce\Plugin::getInstance()-&gt;getCarts()-&gt;getCart();
      $addresses = $cart-&gt;customer-&gt;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-&gt;countryId;
  
                  if ($sentCountryId == $savedCountryId) {
                      $match = $address-&gt;id;
                  }
  
              }
  
          };
  
          // If there’s a match set the cart’s billingAddressId
          // to stop a new address being created:
          if ($match) {
  
              $cart-&gt;billingAddressId = $match; // This doesn’t work on it’s own
              // Craft::$app-&gt;getElements()-&gt;saveElement($cart); // Results in a loop
              $e-&gt;handled = true;
  
          }
  
      }
  
  });
  </code></pre>
  
Tags: <craft3><plugin-craftcommerce><plugin-craftcommerce3>
Title: Update Cart’s address ID from plugin
ThreadText: # Update Cart’s address ID from plugin
  
  (Asked by: username_0 on 2020-04-08)
  
  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 = craft\commerce\Plugin::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;
  
          }
  
      }
  
  });
  
  ```
  
  **Tags:** craft3, plugin-craftcommerce, plugin-craftcommerce3
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-04-08. Score: 0
  
  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.
  
  > **Comments:**
  > **username_1**: Let me know if I am not understanding.  
  > **username_0**: Thanks username_1. Appreciate it’s perhaps not that common but there’s a situation (at least in our checkout process) where a duplicate address is more likely. For example, in our simple form rather than display previous addresses and give the option to add a new one. It just asks for the billingAddress[countryId]. That’s it. So that form opens up the likelihood of duplicates if they’ve checked out before, or have to go back a step in the process and submit the same form twice. Therefore, I’m trying to check against existing  addresses on the plugin side.  
  > **username_0**: Also, less likely to happen but even with radio buttons to select a saved address, they could still opt to enter a new one and input a duplicate. Or maybe I’m missing something?  
  > **username_0**: I’ve updated the question to hopefully make it clearer. I still think there’s a need to catch duplicates.  
  
  ---
  
  