Preventing PO Box shipping addresses

Recently, I wrote a blog post about preventing PO box customer addresses being registered at checkout. Following on from that post, I was asked a rather sensible question: "is it possible to disallow PO boxes for shipping, but allow them for billing?" The answer is yes, but it does require a few more modifications to Magento.

As mentioned in the original post, the if statements with regular expressions required to block PO boxes and locked bags are as follows:

if (preg_match("/p\.* *o\.* *box/i", $this->getStreet(1))) {
  $errors[] = $helper->__('We cannot ship to PO boxes.');
}

and

if (preg_match("/locked *bag/i", $this->getStreet(1))) {
  $errors[] = $helper->__('We cannot ship to locked bags.');
}

Unlike in my original post, we need to add these in a new validation function, which we will only use for validating shipping addresses. In the file:

magento/app/code/core/Mage/Customer/Model/Address/Abstract.php

simply make a copy of the validate() function, name it something like validate_pobox() and insert the above code as before. The result should look something like this:

public function validate_pobox()
{
    $errors = array();
    $helper = Mage::helper('customer');
    $this->implodeStreetAddress();
    if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter first name.');
    }
 
    if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter last name.');
    }
 
    if (!Zend_Validate::is($this->getStreet(1), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter street.');
    }
 
    if (preg_match("/p\.* *o\.* *box/i", $this->getStreet(1))) { 
    	$errors[] = $helper->__('We cannot ship to PO boxes.');
    }
 
    if (preg_match("/locked *bag/i", $this->getStreet(1))) {
        $errors[] = $helper->__('We cannot ship to locked bags.');
    }
 
    if (!Zend_Validate::is($this->getCity(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter city.');
    }
 
    if (!Zend_Validate::is($this->getTelephone(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter telephone.');
    }
 
    if (!Zend_Validate::is($this->getPostcode(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter zip/postal code.');
    }
 
    if (!Zend_Validate::is($this->getCountryId(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter country.');
    }
 
    if ($this->getCountryModel()->getRegionCollection()->getSize()
           && !Zend_Validate::is($this->getRegionId(), 'NotEmpty')) {
        $errors[] = $helper->__('Please enter state/province.');
    }
 
    if (empty($errors)) {
        return true;
    }
    return $errors;
}

Now that we have the necessary validation function, we need to ensure that it is used instead of the default function in the checkout module. The file to be modified is this one:

/magento/app/code/core/Mage/Checkout/Model/Type/Onepage.php

In the Onepage.php file we need to modify three functions:

  • saveBilling
  • saveShipping
  • validateOrder

The first function requires a small block of code to be added, while the last two just need the instance of validate() changed to validate_pobox(). To avoid ambiguities, I have attached the modified Onepage.php file. Simply download the file and search for 'TODO', as I have wrapped all three of the required changes in comments that start with the word 'TODO'.

Finally, the standard warning about modifying core files applies here as well. Rather than directly modifying core files make copies of the affected files before modifying them and place them in the local directory.


Magento Compatibility

Post originally written for Magento version: 1.3.2.3
Tested with Magento version(s): 1.3.2.3
AttachmentSize
Onepage.php.txt24.78 KB

Comments

WOW! Great write-up! Your tutorial was super-easy to follow and very thorough (especially compared to other Magento tutorials out there).

Thanks so much! That was terrific.

Thanks for this post! It really should be a lot simpler to things like this in Magento.

In my case, I also added a pattern check against a 2nd line of street address:

if( preg_match("/p\.* *o\.* *box/i", $this->getStreet(1))
|| preg_match("/p\.* *o\.* *box/i", $this->getStreet(2)) )
{
$errors[] = $helper->__('We cannot ship to PO boxes.');
}

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <apache>, <bash>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <perl>, <php>, <python>, <ruby>, <xml>. The supported tag styles are: <foo>, [foo].

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.