We are trying to give our clients the ability to update an order's shipping address before the order has been actually shipped.

We've created a members area where they can list their orders and access them individually. When in an order, we have a link that loads a specific address form template e.g. /addresses/edit/{{order.shippingAddress.id}} but the address form doesn't load throwing the error Impossible to access an attribute ("id") on a null variable.

This exact same address edit form works fine when loading the address from the craft.commerce.customer.addresses model e.g. addresses/edit/{{ address.id }}. Having a look at the DB, we've found that the address if from the order model doesn't actually exists in the craft_commerce_customers_addresses table which would explain it.

Is there anything we've missed?

Cheers, Alberto

  • Does that same order load in the Control Panel fine? If so, does it show the correct address?
    – Brad Bell
    Jul 5 '17 at 18:07
  • Hi Brad, yes in Control Panel the order loads fine and if you click on the edit address button the address form loads correctly and you can edit it. Both frontend and backend links point to the same address id. I think it might have to do with duplication of addresses when the order is completed but I can't seem to find the duplicated order address in the craft_commerce_customers_addresses and not sure why
    – Alberto
    Jul 6 '17 at 2:59

As mentioned previously, addresses can not be edited on the order once the order is complete (from the front-end).

Right now completed order's addresses can only be edited by admins.

The only way around that at the moment would be to create your own plugin controller action that your form would post to. The controller action would look like this:

public function actionSave()
    $id = craft()->request->getRequiredPost('id');
    // IMPORTANT - Validate the current user is allowed to update the address $id

    $address = craft()->commerce_addresses->getAddressById($id);

    if (!$address)
        $address = new Commerce_AddressModel();

    // Shared attributes
    $attrs = [
    foreach ($attrs as $attr)
        $address->$attr = craft()->request->getPost($attr);

    // Save it
    if (craft()->commerce_addresses->saveAddress($address))

        if (craft()->request->isAjaxRequest)
            $this->returnJson(['success' => true, 'address' => $address]);

        craft()->userSession->setNotice(Craft::t('Address saved.'));

        // save address ID to the order (shipping or billing)

        if (craft()->request->isAjaxRequest)
                'error'  => Craft::t("Couldn’t save address."),
                'errors' => $address->errors

        craft()->userSession->setError(Craft::t('Couldn’t save address.'));

    // Send the model back to the template
    craft()->urlManager->setRouteVariables(['address' => $address]);
  • Thanks Luke, for pointing us in the right direction with such detail, greatly appreciated. Will put together the plugin and let you know how we go
    – Alberto
    Jul 12 '17 at 6:07

When the order is completed a copy of the address is made which is created for that specific order, that explains why it doesn't show up in the customers_addresses table.

This is so that the address is unique to that order and can be edited by an admin without affecting the customers address book. Are you wanting customers to be able to edit that address after the order is complete?

  • Hi Luke, that's what we thought it might be happening. It makes sense to keep order addresses and customer addresses separate so they don't get on each other's way. In our case, it would be good to allow customers to update an order address before the order has shipped so they don't need to contact support to do so. Do you have an idea on what would be the best way to accomplish that?
    – Alberto
    Jul 7 '17 at 5:39

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.