globalcitizen/php-iban
PHP library to parse, validate, generate, and format IBAN/IIBANs. Extracts country, checksum, BBAN, bank/branch/account codes, supports legacy national checksums, conversions (human/machine), obfuscation, test IBANs, and typo-based correction suggestions.
Installation
composer require globalcitizen/php-iban
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"GlobalCitizen\\IBAN\\": "vendor/globalcitizen/php-iban/src/"
}
}
Run composer dump-autoload.
Basic Validation
use GlobalCitizen\IBAN\IBAN;
$iban = new IBAN('DE89370400440532013000');
if ($iban->isValid()) {
echo "Valid IBAN for " . $iban->getBank()->getCountryCode();
}
Generate an IBAN
$iban = IBAN::generate('DE', '37040044', '5320130000');
echo $iban->getNumber();
use GlobalCitizen\IBAN\IBAN;
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'account_number' => [
'required',
function ($attribute, $value, $fail) {
$iban = new IBAN($value);
if (!$iban->isValid()) {
$fail('The '.$attribute.' must be a valid IBAN.');
}
}
]
]);
Validation & Parsing
$iban = new IBAN('LT9273000100123456789');
if ($iban->isValid()) {
$country = $iban->getBank()->getCountryCode();
$bic = $iban->getBank()->getBIC();
$account = $iban->getAccountNumber();
}
Error Correction
$iban = new IBAN('LT92730001001234567890'); // Invalid (extra digit)
$corrected = $iban->correct();
if ($corrected) {
echo "Corrected IBAN: " . $corrected->getNumber();
}
IBAN Generation
// Generate for Germany (DE)
$iban = IBAN::generate('DE', 'DEUTDEBB', '12345678');
echo $iban->getNumber(); // DE89370400440123456789
Country-Specific Rules
$iban = new IBAN('FR1420041010050500013M02606');
if ($iban->isValid()) {
$countryRules = $iban->getBank()->getCountryRules();
echo "Account length: " . $countryRules->getAccountNumberLength();
}
Laravel Request Validation
Use custom validation rules in app/Providers/AppServiceProvider.php:
Validator::extend('valid_iban', function ($attribute, $value, $parameters, $validator) {
return (new IBAN($value))->isValid();
});
Then in your form request:
$this->rules = [
'iban' => 'required|valid_iban',
];
Database Storage
Store IBANs as strings (e.g., VARCHAR(34)) in MySQL. The package handles all validation logic in PHP.
Internationalization
Use IBAN::getCountryList() to fetch supported countries for dropdowns:
$countries = IBAN::getCountryList();
foreach ($countries as $country) {
echo "<option value='{$country->getCode()}'>{$country->getName()}</option>";
}
Testing
Use the IBANTestCase trait (if available) or mock the IBAN class:
$mockIban = $this->createMock(IBAN::class);
$mockIban->method('isValid')->willReturn(true);
Case Sensitivity IBANs are case-insensitive, but the package may return uppercase letters. Normalize with:
$iban->getNumber(); // Always uppercase
Country-Specific Validation Not all IBANs follow the same rules. For example:
if (!$iban->isValid()) {
$errors = $iban->getErrors();
// Handle country-specific errors (e.g., wrong length)
}
IIBAN Support The package supports IIBAN (International IBAN-like formats, e.g., for cryptocurrencies). Ensure you’re not mixing them with standard IBANs:
if ($iban->isIIBAN()) {
// Handle IIBAN-specific logic
}
BIC/BICSF Validation Some countries (e.g., Germany) require BIC/BICSF validation. The package may not auto-validate these—check manually:
$bic = $iban->getBank()->getBIC();
if (empty($bic)) {
throw new \InvalidArgumentException("BIC is required for this country.");
}
Performance
Avoid instantiating IBAN for every request in a loop. Cache validated IBANs or use a service layer:
class IBANService {
private $cache = [];
public function validate($ibanString) {
if (!isset($this->cache[$ibanString])) {
$this->cache[$ibanString] = (new IBAN($ibanString))->isValid();
}
return $this->cache[$ibanString];
}
}
Error Messages
Use getErrors() to debug validation failures:
$iban = new IBAN('INVALID123');
print_r($iban->getErrors());
// Output: Array ( [0] => Invalid IBAN checksum )
Logging Log invalid IBANs for analysis:
if (!$iban->isValid()) {
\Log::warning("Invalid IBAN submitted: {$iban->getNumber()}", [
'errors' => $iban->getErrors(),
'country' => $iban->getBank()?->getCountryCode(),
]);
}
Testing Edge Cases Test with:
AL47212110090000000235698741 for Albania).LT9273000100123456789).Custom Country Rules
Extend GlobalCitizen\IBAN\Country\CountryRules for unsupported countries:
class CustomCountryRules extends CountryRules {
public function __construct() {
$this->setAccountNumberLength(16);
$this->setBranchCodeLength(8);
}
}
Register in a service provider:
IBAN::addCountry('XX', new CustomCountryRules());
Override Validation Logic
Extend the IBAN class to add custom checks:
class CustomIBAN extends IBAN {
public function isBlacklisted() {
return in_array($this->getNumber(), ['BLACKLISTED1', 'BLACKLISTED2']);
}
}
Hooks for Post-Validation Use events (if supported) or callbacks:
$iban = new IBAN('DE89370400440532013000');
if ($iban->isValid()) {
event(new \App\Events\ValidIBANSubmitted($iban));
}
Fallback for Unsupported Countries Handle unsupported IBANs gracefully:
try {
$iban = new IBAN('ZZ1234567890');
} catch (\InvalidArgumentException $e) {
// Fallback logic for unsupported countries
}
How can I help you explore Laravel packages today?