latysh/aba-bundle
latysh/aba-bundle packages ABA functionality into a reusable PHP bundle, offering straightforward configuration and a clean service interface for adding it to your application. Lightweight, easy to install, and framework-friendly.
First, calibrate expectations. This is a Symfony2 bundle, not a Laravel package. It ships no ServiceProvider, no facade, and its composer.json almost certainly pins symfony/symfony: ~2.x and friends. On any modern Laravel (9/10/11) composer require latysh/aba-bundle will either fail resolution or drag in EOL Symfony components you do not want in vendor/. With 1 star and 0 dependents, treat it as a reference implementation, not a dependency.
Practical entry path:
src/ — you want the ABA record/writer classes (header record, detail/transaction records, trailer, file-total) and the DI extension. There is no docs site; the code is the spec.app/Support/Aba/ and bind them in AppServiceProvider, or (b) if you are on a legacy Symfony 2 app, wire them via services.yml. For Laravel, (a) is the only sane route — 3–5 small classes, trivially vendor-free..aba file to Storage::disk('local').$file = app(AbaFile::class)
->header($companyBsb, $companyAccount, 'ACME PTY LTD', now())
->addDetail($supplierBsb, $supplierAccount, 5000, /* cents */ 'INV-1024')
->addDetail(...);
$file->close(); // computes totals
Storage::put("aba/{$batch->id}.aba", $file->toString());
DTO-per-transaction. Map Eloquent models (Invoice, PayrollLine) into plain ABA detail objects in a single transformer class. Keep the file writer dumb — it takes an array of details and emits text. This makes golden-file tests trivial and lets you unit-test the mapping without a database.
Money is integer cents, always. (int) round($amount * 100). Never let a float or a formatted string near the writer; ABA amounts are zero-padded fixed-width and 1,234.56 silently corrupts the file.
Config over hardcoding. Put BSB, account number, remitter name (16 chars), user-preferred name (12 chars), and transaction codes in config/aba.php. Transaction codes are the thing finance teams change: 50 = credit to external account, 53 = payroll, 13 = debit. Don't bury them in the writer.
Queued job + audit trail. Generate inside GenerateAbaFileJob, write to local or s3, then persist a row: file hash, batch id, detail count, credit total, debit total. When the bank statement lands, you reconcile by hash and by the remitter/withheld reference, not by eyeballing the file.
Testing. Snapshot the exact byte output of a small fixture (e.g. 3 details). Assert line length is 120 on every record and that trailer totals equal the sum of details. This catches 90% of real-world rejections.
Validation before hand-off. Add a AbaValidator that checks BSB is 6 digits, account ≤ 9 digits, names contain only uppercase ASCII/punctuation, amounts > 0, and totals balance. Run it before you ever email the file to the bank.
strlen($line) === 120 on write.\r\n), some tolerate LF. Get a known-good sample .aba from your actual bank and diff yours against it byte-for-byte. diff <(xxd yours) <(xxd theirs) is your friend.& and ' behaviour varies by bank. Sanitise at the transformer, not the writer.How can I help you explore Laravel packages today?