A zero dependencies PHP Parser for CFONB statements
Supports CFONB 120/240 format
The preferred method of installation is via Composer. Run the following
command to install the package and add it as a requirement to your project's
composer.json
:
composer require silarhi/cfonb-parser
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
//Gets all statements day by day
foreach($reader->parse('My Content') as $statement) {
if ($statement->hasOldBalance()) {
echo sprintf("Old balance : %f\n", $statement->getOldBalance()->getAmount());
}
foreach($statement->getOperations() as $operation) {
//Gets all statement operations
}
if ($statement->hasNewBalance()) {
echo sprintf("New balance : %f\n", $statement->getNewBalance()->getAmount());
}
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
$content = file_get_contents('/path/to/cfonb120-file.txt');
foreach($reader->parse($content) as $statement) {
// Process each daily statement
echo "Statement date: " . $statement->getOldBalance()->getDate()->format('Y-m-d') . "\n";
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
foreach($reader->parse($content) as $statement) {
foreach($statement->getOperations() as $operation) {
echo "Date: " . $operation->getDate()->format('Y-m-d') . "\n";
echo "Value Date: " . $operation->getValueDate()->format('Y-m-d') . "\n";
echo "Amount: " . $operation->getAmount() . "\n";
echo "Label: " . $operation->getLabel() . "\n";
echo "Reference: " . $operation->getReference() . "\n";
echo "Bank Code: " . $operation->getBankCode() . "\n";
echo "Account: " . $operation->getAccountNumber() . "\n";
// Access optional fields
if ($operation->getInternalCode()) {
echo "Internal Code: " . $operation->getInternalCode() . "\n";
}
// Process operation details (additional information)
foreach($operation->getDetails() as $detail) {
echo "Additional Info: " . $detail->getAdditionalInformations() . "\n";
}
echo "---\n";
}
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
use Silarhi\Cfonb\Exceptions\ParseException;
$reader = new Cfonb120Reader();
// Strict mode (default) - throws exception on parsing errors
try {
$statements = $reader->parse($content); // strict=true by default
} catch (ParseException $e) {
echo "Parsing error: " . $e->getMessage() . "\n";
}
// Non-strict mode - continues parsing despite errors
$statements = $reader->parse($content, false); // strict=false
<?php
use Silarhi\Cfonb\Cfonb240Reader;
use Silarhi\Cfonb\Banking\Transfer;
$reader = new Cfonb240Reader();
foreach($reader->parse('My Content') as $transfer) {
assert($transfer instanceof Transfer);
}
<?php
use Silarhi\Cfonb\Cfonb240Reader;
$reader = new Cfonb240Reader();
foreach($reader->parse($content) as $transfer) {
// Access transfer header information
$header = $transfer->getHeader();
echo "Transfer Date: " . $header->getPrevTransactionFileDate()->format('Y-m-d') . "\n";
echo "Bank Code: " . $header->getRecipientBankCode1() . "\n";
echo "Account: " . $header->getRecipientAccountNumber1() . "\n";
// Process all transactions in the transfer
foreach($transfer->getTransactions() as $transaction) {
echo "Transaction Date: " . $transaction->getSettlementDate()->format('Y-m-d') . "\n";
echo "Amount: " . $transaction->getTransactionAmount() . "\n";
echo "Recipient: " . $transaction->getRecipientName1() . "\n";
echo "Reference: " . $transaction->getPresenterReference() . "\n";
}
// Access transfer total
$total = $transfer->getTotal();
echo "Total Amount: " . $total->getTotalAmount() . "\n";
echo "Sequence Number: " . $total->getSequenceNumber() . "\n";
}
<?php
use Silarhi\Cfonb\Cfonb240Reader;
use Silarhi\Cfonb\Exceptions\ParseException;
use Silarhi\Cfonb\Exceptions\HeaderUnavailableException;
$reader = new Cfonb240Reader();
try {
$content = file_get_contents('/path/to/cfonb240-file.txt');
foreach($reader->parse($content) as $transfer) {
// Safely access optional header
try {
$header = $transfer->getHeader();
echo "Processing transfer from: " . $header->getRecipientBankCode1() . "\n";
} catch (HeaderUnavailableException $e) {
echo "Transfer header not available\n";
}
// Process transactions...
}
} catch (ParseException $e) {
echo "Failed to parse CFONB file: " . $e->getMessage() . "\n";
}
<?php
use Silarhi\Cfonb\CfonbReader;
use Silarhi\Cfonb\Banking\Statement;
use Silarhi\Cfonb\Banking\Transfer;
$reader = new CfonbReader();
foreach($reader->parseCfonb120('My Content') as $statement) {
assert($statement instanceof Statement);
}
foreach($reader->parseCfonb240('My Content') as $transfer) {
assert($transfer instanceof Transfer);
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
use Silarhi\Cfonb\Banking\Operation;
$reader = new Cfonb120Reader();
$statements = $reader->parse($content);
// Filter operations by amount
foreach ($statements as $statement) {
$largeOperations = array_filter(
$statement->getOperations(),
fn(Operation $op) => abs($op->getAmount()) > 1000
);
foreach ($largeOperations as $operation) {
echo "Large operation: {$operation->getAmount()} - {$operation->getLabel()}\n";
}
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
$statements = $reader->parse($content);
$summary = [
'total_debit' => 0,
'total_credit' => 0,
'operation_count' => 0
];
foreach ($statements as $statement) {
foreach ($statement->getOperations() as $operation) {
$amount = $operation->getAmount();
if ($amount > 0) {
$summary['total_credit'] += $amount;
} else {
$summary['total_debit'] += abs($amount);
}
$summary['operation_count']++;
}
}
echo "Summary:\n";
echo "Total Credits: {$summary['total_credit']}\n";
echo "Total Debits: {$summary['total_debit']}\n";
echo "Operation Count: {$summary['operation_count']}\n";
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
$statements = $reader->parse($content);
$data = [];
foreach ($statements as $statement) {
$statementData = [
'date' => $statement->getOldBalance()->getDate()->format('Y-m-d'),
'opening_balance' => $statement->hasOldBalance() ? $statement->getOldBalance()->getAmount() : null,
'closing_balance' => $statement->hasNewBalance() ? $statement->getNewBalance()->getAmount() : null,
'operations' => []
];
foreach ($statement->getOperations() as $operation) {
$statementData['operations'][] = [
'date' => $operation->getDate()->format('Y-m-d'),
'value_date' => $operation->getValueDate()->format('Y-m-d'),
'amount' => $operation->getAmount(),
'label' => $operation->getLabel(),
'reference' => $operation->getReference(),
'bank_code' => $operation->getBankCode(),
'account_number' => $operation->getAccountNumber()
];
}
$data[] = $statementData;
}
// Convert to JSON for API response
echo json_encode($data, JSON_PRETTY_PRINT);
<?php
use Silarhi\Cfonb\Cfonb120Reader;
$reader = new Cfonb120Reader();
$statements = $reader->parse($content);
// Group statements by account
$accountStatements = [];
foreach ($statements as $statement) {
if ($statement->hasOldBalance()) {
$accountNumber = $statement->getOldBalance()->getAccountNumber();
$accountStatements[$accountNumber][] = $statement;
}
}
// Process each account separately
foreach ($accountStatements as $accountNumber => $statements) {
echo "Account: $accountNumber\n";
echo "Number of statements: " . count($statements) . "\n";
$totalBalance = 0;
foreach ($statements as $statement) {
if ($statement->hasNewBalance()) {
$totalBalance = $statement->getNewBalance()->getAmount();
}
}
echo "Final balance: $totalBalance\n\n";
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
use Silarhi\Cfonb\Exceptions\ParseException;
$reader = new Cfonb120Reader();
try {
$statements = $reader->parse($content);
} catch (ParseException $e) {
// Common issues:
// - Invalid line length (should be 120 characters)
// - Malformed line format
// - Invalid date format
// - Invalid amount format
echo "Parse error on line: " . $e->getMessage() . "\n";
// Try non-strict mode to continue parsing
$statements = $reader->parse($content, false);
}
<?php
use Silarhi\Cfonb\Cfonb120Reader;
function validateCfonbFormat(string $content): bool {
$lines = explode("\n", trim($content));
foreach ($lines as $line) {
// Skip empty lines
if (empty(trim($line))) continue;
// Check line length for CFONB 120
if (strlen($line) !== 120) {
return false;
}
// Check if line starts with valid CFONB code
$lineCode = substr($line, 0, 2);
if (!in_array($lineCode, ['01', '04', '05', '07'])) {
return false;
}
}
return true;
}
// Usage
if (validateCfonbFormat($content)) {
$reader = new Cfonb120Reader();
$statements = $reader->parse($content);
} else {
echo "Invalid CFONB format\n";
}