Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Iban Laravel Package

rikudou/iban

Validate, parse, and format International Bank Account Numbers in PHP with rikudou/iban. Country-aware checks, compact and electronic IBAN formatting, and simple integration for banking, payment, and Laravel validation workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require rikudou/iban

This is a plain library, not a Laravel package — there's no service provider, config file, or facade to publish. You get two things:

  • Rikudou\Iban\IBAN\Iban — a value object that parses an IBAN and exposes its parts (country code, BBAN, bank identifier, account number) plus a formatted rendering.
  • Rikudou\Iban\Validator\* — IbanValidator for the ISO 13616 structure + mod-97 check, ChainValidator to stack several checks, and country-specific validators (Czech/Slovak bank-code and account-number verification are the notable ones).

Read first, in this order: README.md (it's short), then src/IBAN/IbanInterface.php (the accessor surface you'll actually call), then src/Validator/ValidatorInterface.php (signature and error reporting). Everything else is implementation detail.

First use case: validate and normalize an IBAN captured on a billing or payout form.

use Rikudou\Iban\IBAN\Iban;
use Rikudou\Iban\Validator\IbanValidator;

$raw = "CZ65 0800 0000 1920 0014 5399";
$normalized = strtoupper(preg_replace('/[\s\p{Z}]+/u', '', $raw));

try {
    $iban = new Iban($normalized);            // throws on malformed input
} catch (\Throwable $e) {
    return false;                             // length / charset / country problem
}

$valid = (new IbanValidator())->isValid($iban);  // mod-97 + country rules

Note the two failure modes: the constructor throws on bad input, the validator returns a bool. Any wrapper you build has to handle both.

Implementation Patterns

1. A Laravel validation rule

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Rikudou\Iban\IBAN\Iban;
use Rikudou\Iban\Validator\IbanValidator;

final class ValidIban implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $normalized = strtoupper(preg_replace('/[\s\p{Z}]+/u', '', (string) $value));

        try {
            $iban = new Iban($normalized);
        } catch (\Throwable) {
            $fail('The :attribute is not a well-formed IBAN.');
            return;
        }

        if (! (new IbanValidator())->isValid($iban)) {
            $fail('The :attribute failed IBAN checksum validation.');
        }
    }
}

Use it in a FormRequest as 'iban' => ['required', 'string', 'max:42', new ValidIban()]. The max:42 accommodates the spaced form; the canonical form is at most 34 characters.

2. Normalize once, at the edge

Store the canonical ungrouped uppercase form — never the spaced one. An attribute cast keeps it consistent across controllers, jobs and imports:

protected function iban(): Attribute
{
    return Attribute::make(
        set: fn (?string $v) => $v === null
            ? null
            : strtoupper(preg_replace('/[\s\p{Z}]+/u', '', $v)),
    );
}

3. Format only at the presentation layer

The concrete IBAN classes implement __toString() for the canonical value, and expose the grouped 4-character form for display (getFormattedIban() — confirm the name against IbanInterface in your version). Expose both in API resources / Blade:

'iban'           => (string) $account->iban,
'iban_formatted' => $account->iban->getFormattedIban(),

If you'd rather not couple views to the library, trim(chunk_split($iban, 4, ' ')) produces the same output.

4. Bind the validator in a service provider

Wrap it — don't sprinkle new IbanValidator() through the app:

// app/Providers/BankingServiceProvider.php
$this->app->singleton(ValidatorInterface::class, function () {
    return new ChainValidator([
        new IbanValidator(),
        // new CzechIbanValidator(), new SlovakIbanValidator(), ...
    ]);
});

ChainValidator is the main extension point: the base IbanValidator only verifies structure and checksum, so "is this a real Czech account?" requires stacking the country-specific validator.

5. Generate fixtures instead of pasting them

For CZ/SK the package can compose an IBAN from bank code + account number (CzechIban, SlovakIban under src/IBAN/), which beats hard-coded strings in factories:

// database/factories/AccountFactory.php
'iban' => (string) new CzechIban('0800', '0000192000145399'),

For other countries, keep a small fixture helper class with published example IBANs and reuse it across tests and seeders.

6. Payout flow

Validate in the FormRequest → persist the canonical form → re-validate when the payout job runs, because CSV imports and manual DB edits bypass your rule. Route both validations through a single IbanService so the failure path (log, notify, block payout) is identical.

Gotchas and Tips

  • License is WTFPL. Permissive, but it is not MIT/Apache and procurement checklists will occasionally flag it. Put it on your dependency-license inventory before it reaches a regulated product.
  • Very low adoption (4 stars, 0 dependents, last release September 2023). Assume maintenance may stop. Hide it behind your own IbanValidatorContract / value object so swapping to Symfony's IBAN constraint, another IBAN port, or a 30-line mod-97 check is a one-file change.
  • Exceptions vs. booleans. Construction throws (InvalidIbanException and friends); isValid() returns false. Catch \Throwable at the boundary — a stray library exception escaping a FormRequest becomes a 500.
  • Signature drift between versions. Recent releases expect a parsed IbanInterface in isValid(); older tags accepted a raw string. If behaviour changes after composer update, read src/Validator/ValidatorInterface.php before assuming your data is wrong.
  • Don't size the column at 22. ISO 13616 permits up to 34 characters (Malta and several Middle East countries exceed 22). Use varchar(34) for canonical, 42 if you also persist the grouped form.
  • Whitespace is presentation. Strip with /[\s\p{Z}]+/u, not /\s/, or a non-breaking space pasted from a PDF will fail validation.
  • Iban is a generic class name. Alias on import (use Rikudou\Iban\IBAN\Iban as IbanValue;) to avoid colliding with your own model or DTO names.
  • Checksum-valid ≠ real account. Mod-97 only proves internal consistency. IBANs copied from docs, blogs and Stack Overflow are frequently fabricated — never assert "reachable" in a test.
  • Country coverage is uneven. Structural/length validation covers every IBAN country; bank-code and account-number verification is only implemented for a subset (CZ/SK being this library's focus). Document that limitation for whoever triages payout failures.
  • IBAN only — no BIC/SWIFT. Pair with a separate BIC validator if you need both fields.
  • No releases since 2023. Nothing guarantees it is exercised against your current PHP version; run your suite after PHP upgrades and pin the constraint if you move fast.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle