1

Our site imports customers from external data sources. Part of this import is creating a default billing address from external data if none exists.

I have followed advice from other questions, as wells as tutorials, all of which seem to say the same thing for creating/saving a default billing address. This seems to work at least partially.

// $c is the customer
$data_source  = array(
    'street'   => '',
    'city'     => '',
    'postcode' => '',
);

$a = $c->getPrimaryBillingAddress();

// Create a new default billing if none found
if (!$a)
{
  $a = Mage::getModel("customer/address");
  $a->setCustomerId($c->getId())
    ->setIsDefaultBilling('1')
    ->setSaveInAddressBook('1');
}

foreach ($data_source as $k => $d) $a->setData($k, $d);

$a->save();

After this code has been run, the address is visible on the customer's page in the backend and is marked as the default billing.

However, the following time data is fetched from our external source and the code is run, the address that was saved is not retrieved (getPrimaryBillingAddress returns false). This results in a new address being created every time this code is run.

The exception is when a customer has a default billing address set by magento. In this case, getPrimaryBillingAddress correctly finds the address and the address data is updated and saved.

How can I programatically create a default billing address in such a way that I can retrieve it with $customer->getPrimaryBillingAddress()?

UPDATE

After receiving a possible answer, I have adjusted to code to set customer's default_billing. The main problem persists with the changes.

$a = $c->getPrimaryBillingAddress();

// Create a new default billing if none found
if (!$a)
{
  $a = Mage::getModel("customer/address");
  $a->setCustomerId($c->getId())            // <-- variations of customer/customerID 
    ->setCustomer($c)                       //     don't seem to affect
    ->setIsDefaultBilling('1')
    ->setSaveInAddressBook('1')
    ->save();                               // <--- SAVE SO WE CAN ACCESS ID

  $c->addAddress($a)                        // <--|
    ->setDefaultBilling($a->getId())        // <--+ SAVE default_billing IN CUSTOMER
    ->save();                               // <--|

}

foreach ($data_source as $k => $d) $a->setData($k, $d);

$a->save();

// ---------------- SUBSEQUENT RUNS --------------

$c->getDefaultBilling();                    // null
$c->getPrimaryBillingAddress();             // false

References

Variations on this method for creating/setting a customer default address were found at these locations:

5
  • If you want to reuse it in one run, you should also invoke $customer->addAddress($newAddress); Will update my answer
    – Jeroen
    Mar 11, 2015 at 11:52
  • That code was just intended to show the continued problem. On the next run getDefaultBilling actually returns null, and getPrimaryBillingAddress returns false. Mar 11, 2015 at 11:55
  • You also need to understand the difference between addData and setData as setData overwrites all data(including resetting the id and therefore creating a new address)
    – Jeroen
    Mar 11, 2015 at 11:58
  • The addData vs setData comes from a simplication to my example. Apologies. setData is called with both params (updated question). Mar 11, 2015 at 12:11
  • Take a look at Mage_Customer_Model_Resource_Customer->_afterSave() and _saveAddresses() Addresses are saved here if added with customer->addAddress() So save the customer and addresses will be saved to, if the isDefaultBilling flag is set, it will be updated in the customer object
    – Jeroen
    Mar 11, 2015 at 12:39

2 Answers 2

4

You need to set it the other way around. The default_billing for the customer.

$customerId = 1234; // Customer id
$data = array(); // Address data

$customer = Mage::getModel('customer/customer');

// Load customer
$customer->load($customerId);

// Get current address
$address = $customer->getPrimaryBillingAddress();

// Do we add a new address
$isNewAddress = false;
if (!$address) {
    $address = Mage::getModel('customer/address');

    $address->setCustomer($customer);
    $isNewAddress = true;
}

// Append data
$address->addData($data);
$address->save();

if ($isNewAddress) {
    // Add address to customer and save
    $customer->addAddress($address)
        ->setDefaultBilling($address->getId())
        ->save();
}
7
  • I've tried adding setDefaultBilling, but the problem persists, see update in question. Mar 11, 2015 at 11:52
  • See my updated answer
    – Jeroen
    Mar 11, 2015 at 11:54
  • addAddress does not seem to have any affect on the problem. Nor does changing setCustomer or setCustomerId on the address. Mar 11, 2015 at 12:12
  • I've used the order above to be sure that the address is only save once. It is even true that customer->save also saves the addresses in the _afterSave() of the resource
    – Jeroen
    Mar 11, 2015 at 12:35
  • I continue to get a new address every time. The created address is never returned by getPrimaryBillingAddress. Mar 12, 2015 at 8:57
1

I came across this exact problem. The tricky part is that there's nothing wrong with the code that you've shown - the problem lies in the omitted code before it (how you load $c).

Crucially you need to reload the customer model before $c->getPrimaryBillingAddress(). In my case it was because I was loading the product via a [collection]->getFirstItem() call - which presumably didn't load the address (I didn't delve all the way to the source of the problem once it was fixed). I fixed it by adding the the following code before the call to $c->getPrimaryBillingAddress() (your first line):

$c = Mage::getModel('customer/customer')->load($c->getId());

(as horribly pointless as it may seem).

Your situation would presumably be the same, but I can't be sure without seeing how $c was initially loaded.

Your problem is most likely long solved or circumvented now, but I thought this answer may be useful for others like me, who stumbled upon it with the same confusing symptoms. The struggle is that although all the answers online are correct code, they all implicitly rely on the customer model being loaded directly.

1
  • Yes, this was ages ago and solved with essentially the solution you mention (if memory serves). I believe this $c was provided to an observer... Jun 16, 2016 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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