I started with a very simple web-based cashbook in PHP where all data was stored in a local JSON file.
Later I switched the backend to a DBF file via a microservice β and the same pattern would also work with SQL.
The nice part: the UI code did not change, only loadData().
- Original JSON-based version
// Old: JSON file "data.json" as backend
// {
// "users": [...],
// "transactions": [...]
// }
function loadData() {
$file = __DIR__ . '/data.json';
$data = json_decode(@file_get_contents($file), true);
if (!is_array($data)) {
$data = ['users' => [], 'transactions' => []];
}
return $data;
}Everywhere else I just used:
$data = loadData();
$transactions = $data['transactions'];
- DBF backend via microservice (same UI)
Now the data lives in a DBF file (Kasse.DBF).
Instead of reading data.json, I call a microservice endpoint xWH_hub_readdbf.php which returns JSON.
2.1 Minimal helper to call the microservice
function hubRequest(string $endpoint, array $payload): array
{
$url = $endpoint; // e.g. "xWH_hub_readdbf.php" in the same directory
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => json_encode($payload, JSON_UNESCAPED_UNICODE),
'timeout' => 30,
]
]);
// For demo purposes: no error handling, expect valid JSON
$response = file_get_contents($url, false, $context);
return json_decode($response, true) ?? [];
}2.2 New loadData() using DBF field names 1:1
function loadData() {
// DBF field names 1:1 β no mapping layer in PHP
$payload = [
'databasePath' => 'x:\\xwhdaten\\datawin\\Kasse.DBF',
'start' => 1,
'end' => 500,
'fields' => [
'TEXT', // description
'EINNAHMEN', // income (N, 11,2)
'AUSGABEN', // expense (N, 11,2)
'DATUM', // date (D)
'USER', // user code
],
];
$response = hubRequest('xWH_hub_readdbf.php', $payload);
// Adjust this key to your real microservice output: "records", "rows", "data", ...
$rows = $response['records'] ?? [];
// Keep the same structure the UI expects
return [
'users' => [],
'transactions' => $rows,
];
}The HTML/JS part still works with $data['transactions'], so the UI does not care if the backend is JSON, DBF, or anything else β as long as the JSON shape is the same.
3. Same pattern with an SQL-based microservice
Architecturally, you can do exactly the same with an SQL backend:
the PHP app doesnβt talk to the database directly; it calls a microservice that runs an SQL query and returns JSON.
Example: microservice endpoint xWH_hub_sql_select.php:
function loadData() {
// The microservice will execute this SQL on its side
$payload = [
'sql' => "
SELECT
text AS TEXT,
income AS EINNAHMEN,
expense AS AUSGABEN,
booking_at AS DATUM,
username AS USER
FROM cashbook
ORDER BY booking_at, id
LIMIT 500
"
];
$response = hubRequest('xWH_hub_sql_select.php', $payload);
// Again: use whatever key your microservice returns
$rows = $response['rows'] ?? [];
return [
'users' => [],
'transactions' => $rows,
];
}From the UI perspective:
Old: JSON file β $data['transactions']
New: DBF/microservice β $data['transactions']
Alternative: SQL/microservice β $data['transactions']
Same structure, same rendering logic, just a different backend behind the microservice.