ebrana/cz-bank-account-validator-bundle
Symfony bundle providing a PHP attribute validation constraint for Czech bank account numbers (e.g., prefix-number/bankcode). Works on full string properties or computed methods with separate parts, supports custom error paths/messages, and allows custom bank code providers via service decoration.
Install the package via Composer:
composer require ebrana/cz-bank-account-validator-bundle
Publish the bundle configuration (if needed for custom bank codes):
php artisan vendor:publish --provider="Ebrana\CzBankAccountValidatorBundle\CzBankAccountValidatorBundle"
First Use Case: Validate a Czech bank account number in a Symfony Form or DTO.
use Ebrana\CzBankAccountValidatorBundle\Validator\AccountNumberValid;
class PaymentRequest {
#[AccountNumberValid]
public string $accountNumber; // Format: "123-45678901/2010"
}
Use the attribute on properties containing full account numbers (e.g., 123-45678901/2010):
class Invoice {
#[AccountNumberValid]
public string $payerAccount;
#[AccountNumberValid]
public ?string $recipientAccount = null;
}
For split account components (prefix, IBAN, bank code), use the method-based approach:
class Payment {
public string $prefix; // e.g., "123"
public string $accountNumber; // e.g., "45678901"
public string $bankCode; // e.g., "2010"
#[AccountNumberValid(
bankCodePath: 'bankCode',
prefixPath: 'prefix'
)]
public function getFullAccountNumber(): string {
return $this->prefix . '-' . $this->accountNumber . '/' . $this->bankCode;
}
}
Bind the validator to Symfony Forms:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class PaymentFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('accountNumber', TextType::class, [
'constraints' => [new AccountNumberValid()]
]);
}
}
Use in Laravel API resources or DTOs:
use Ebrana\CzBankAccountValidatorBundle\Validator\AccountNumberValid;
class CreatePaymentRequest {
#[AccountNumberValid]
public string $accountNumber;
}
Override default validation messages:
#[AccountNumberValid(
message: 'Invalid Czech bank account format. Expected: XXX-XXXXXXXX/XXXX.'
)]
public string $accountNumber;
XXX-XXXXXXXX/XXXX).
123456789012345678 (no separators)123-45678901/2010$normalized = preg_replace('/[^\d\/-]/', '', $rawInput);
// config/services.php
'decorated.cz_bank_account_validator.bank_code_provider' => [
'class' => App\Services\CustomBankCodeProvider::class,
'decorates' => 'cz_bank_account_validator.bank_code_provider',
],
null by default.
#[AccountNumberValid] on a nullable property with null value.nullable: true:
#[AccountNumberValid(nullable: true)]
public ?string $optionalAccount;
$validator = new AccountNumberValid();
$errors = $validator->validate('invalid-account', new ConstraintValidator());
dd($errors); // Array of error messages
// app/Providers/AppServiceProvider.php
public function boot() {
Cache::remember('cz_bank_codes', now()->addHours(1), function () {
return (new BankCodeProvider())->getCodes();
});
}
$this->app->instance(
'cz_bank_account_validator.bank_code_provider',
new class implements BankCodeProviderInterface {
public function getCodes(): array { return ['2010' => 'ČSOB']; }
}
);
$request->validate([
'account_number' => ['required', new AccountNumberValid()]
]);
ConstraintValidator interface may conflict with Laravel’s Validator.
Fix: Ensure the bundle’s validator is registered in Laravel’s container:
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->bind(
ConstraintValidatorInterface::class,
Ebrana\CzBankAccountValidatorBundle\Validator\AccountNumberValidator::class
);
}
bankCodePath/prefixPath.
Action Required: Update all method-based usages to explicitly define paths.
// Before (v1.x)
#[AccountNumberValid] // ❌ Fails in v2.0.1
public function getAccountNumber() { ... }
// After (v2.0.1+)
#[AccountNumberValid(bankCodePath: 'bankCode', prefixPath: 'prefix')]
public function getAccountNumber() { ... }
How can I help you explore Laravel packages today?