Check Australian Business Number (ABN) in PHP and Laravel

Note: Newer versions of Laravel now have a different interface for creating custom validation rules. See the ValidationRule class. This post hasn’t been updated yet. (2024).

ABNs use a checksum, so their basic format can be validated. There is also an API to check that the ABN also corresponds to a real business, but as a preliminary check this function will tell you that the format is correct.

See the rules behind the check here.

<?php

// Remove spaces from an ABN string before passing to function.

function validAbnFormat(int $abn): bool
{
  if (strlen($abn) !== 11) {
    return false;
  }

  $nums = array_map('intval', str_split($abn, 1));
  $nums[0] -= 1;

  $weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];

  foreach($nums as $pos => $num) {
    $weight = $weights[$pos];
    $nums[$pos] = $num * $weight;
  }

  $sum = array_sum($nums);
  return $sum % 89 === 0;
}

Creating a Laravel Validation Rule

If you would like to validate ABNs in a Laravel application you can register a custom validation rule that you can use in Form Requests or Validators.

Create the new rule class using artisan

php artisan make:rule Abn

Then use a variation of the function above to validate the ABN. The Abn class should look like this:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Abn implements Rule
{
    public function __construct() {}

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $abn)
    {
        $abn = str_replace(' ', '', $abn);

        if (strlen($abn) !== 11) {
            return false;
        }
        
        $nums = array_map('intval', str_split($abn, 1));
        $nums[0] -= 1;
        
        $weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
        
        foreach($nums as $pos => $num) {
            $weight = $weights[$pos];
            $nums[$pos] = $num * $weight;
        }
        
        return array_sum($nums) % 89 === 0;
    }

    /**
     * Get the validation error message.
     */
    public function message(): string
    {
        return 'Invalid ABN';
    }
}

You can then use this validation rule by importing the class and adding it to your set of rules for an input.

<?php

use App\Rules\Abn;

// ...

$validator = Validator::make(
   $input->all(),
   ['abn' => ['required', new Abn]]
);