This guide will help you get up and running with the FoundationDB PHP client library.
Before you begin, ensure you have the following:
- PHP 8.2+ with the
ext-ffiextension enabled - ext-gmp (optional, but recommended for arbitrary-precision integers in the tuple layer)
- FoundationDB server (for running operations)
- libfdb_c.so (FoundationDB C client library)
Download and install the FoundationDB client library from the official GitHub releases:
# Download and install the client library
wget https://github.com/apple/foundationdb/releases/download/7.3.75/foundationdb-clients_7.3.75-1_amd64.deb
sudo dpkg -i foundationdb-clients_7.3.75-1_amd64.debFor local development, also install the FoundationDB server:
# Download and install the server
wget https://github.com/apple/foundationdb/releases/download/7.3.75/foundationdb-server_7.3.75-1_amd64.deb
sudo dpkg -i foundationdb-server_7.3.75-1_amd64.debDownload the .pkg installer from the FoundationDB releases page and run it.
A docker-compose.yml file is available in this repository for easy local development with Docker.
Install the library via Composer:
composer require crazy-goat/fdb-phpphp -m | grep FFIIf not enabled, add the following to your php.ini:
ffi.enable=truephp -m | grep gmpThe GMP extension is required for working with arbitrary-precision integers in the tuple layer.
Here is a complete working example to get you started:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use CrazyGoat\FoundationDB\FoundationDB as FDB;
use CrazyGoat\FoundationDB\Transaction;
// 1. Select API version (must be called once, before anything else)
FDB::apiVersion(730);
// 2. Open a database connection
$db = FDB::open();
// 3. Write data
$db->set('hello', 'world');
// 4. Read data
$value = $db->get('hello');
echo "hello = {$value}\n"; // hello = world
// 5. Use a transaction for multiple operations
$db->transact(function (Transaction $tr) {
$tr->set('user:1:name', 'Alice');
$tr->set('user:1:email', 'alice@example.com');
$name = $tr->get('user:1:name')->await();
echo "Name: {$name}\n";
});
// 6. Clean up
$db->clear('hello');The FDB::apiVersion(730) call is crucial and must be made exactly once per process, before any other FoundationDB operations.
- Locks API behavior: The version number locks the API behavior to that specific version
- Called once per process: Must be called before any other FDB calls
- Version correspondence: The version number corresponds to the FoundationDB release (7.3.x = 730)
- Maximum version: Use
FDB::getMaxApiVersion()to get the maximum API version supported by your installed client library
There are several ways to open a database connection:
$db = FDB::open();Uses the default cluster file or the FDB_CLUSTER_FILE environment variable.
$db = FDB::open('/path/to/fdb.cluster');$db = FDB::openWithConnectionString('description:id@host:port');Database instances are cached. Calling open() multiple times with the same arguments will return the same instance.
The Database class provides convenient methods for common operations:
| Method | Description |
|---|---|
$db->get($key) |
Returns ?string (null if key doesn't exist) |
$db->set($key, $value) |
Write a key-value pair |
$db->clear($key) |
Delete a single key |
$db->clearRange($begin, $end) |
Delete a range of keys |
$db->clearRangeStartsWith($prefix) |
Delete all keys with a given prefix |
All Database convenience methods automatically wrap operations in transactions with automatic retry logic.
For atomic, multi-operation transactions, use the transact() method:
$db->transact(function (Transaction $tr) {
// Reads return Futures - must call await()
$value = $tr->get('key')->await();
// Writes are immediate (no Future)
$tr->set('key', 'value');
});The transact() method provides:
- Automatic retry: On conflicts or transient errors
- Atomic operations: All operations succeed or fail together
For full details on transactions, see docs/transactions.md.
Now that you have the basics, explore these topics:
- Transactions in depth — Advanced transaction patterns and error handling
- Range reads — Querying multiple keys efficiently
- Tuple layer — Structured key encoding for complex data types
- Subspaces — Organizing your keyspace
- Directory layer — Dynamic keyspace management