This is the official PHP SDK for Genesis DB, an awesome and production ready event store database system for building event-driven apps.
- Incredibly fast when reading, fast when writing 🚀
- Easy backup creation and recovery
- CloudEvents compatible
- GDPR-ready
- Easily accessible via the HTTP interface
- Auditable. Guarantee database consistency
- Logging and metrics for Prometheus
- SQL like query language called Genesis DB Query Language (GDBQL)
Just run:
composer require genesisdb/client-sdk
use GenesisDB\GenesisDB\Client;
final class AcmeClass
{
/**
* @return Client
*/
private function genesisDbClient(): Client
{
return new Client($this->apiUrl, $this->apiVersion, $this->authToken);
}
/**
* @param string $subject
* @param string|null $lowerBound
* @param bool|null $includeLowerBoundEvent
* @param string|null $latestByEventType
* @return array
*/
public function streamEvents(
string $subject,
?string $lowerBound = null,
?bool $includeLowerBoundEvent = null,
?string $latestByEventType = null
): array
{
return $this->genesisDbClient()->streamEvents(
$subject,
$lowerBound,
$includeLowerBoundEvent,
$latestByEventType
);
}
/**
* @param string $subject
* @param string|null $lowerBound
* @param bool|null $includeLowerBoundEvent
* @param string|null $latestByEventType
* @return \Generator
*/
public function observeEvents(
string $subject,
?string $lowerBound = null,
?bool $includeLowerBoundEvent = null,
?string $latestByEventType = null
): \Generator
{
return $this->genesisDbClient()->observeEvents(
$subject,
$lowerBound,
$includeLowerBoundEvent,
$latestByEventType
);
}
/**
* @param array $events Array of events with subject, type, and data
* @param array|null $preconditions Optional preconditions for the commit
* @return void
*/
public function commitEvents(array $events, ?array $preconditions = null): void
{
$this->genesisDbClient()->commitEvents($events, $preconditions);
}
/**
* @param string $subject
* @return void
*/
public function eraseData(string $subject): void
{
$this->genesisDbClient()->eraseData($subject);
}
/**
* @param string $query
* @return array
*/
public function queryEvents(string $query): array
{
return $this->genesisDbClient()->q($query);
}
/**
* @return string
*/
public function audit(): string
{
return $this->genesisDbClient()->audit();
}
/**
* @return string
*/
public function ping(): string
{
return $this->genesisDbClient()->ping();
}
}
// Stream all events for a subject
$events = $client->streamEvents('/customer');
foreach ($events as $event) {
echo "Event Type: " . $event['type'] . ", Data: " . json_encode($event['data']) . "\n";
}
// Stream events from a specific lower bound
$events = $client->streamEvents(
'/',
'2d6d4141-6107-4fb2-905f-445730f4f2a9',
true
);
foreach ($events as $event) {
echo "Event Type: " . $event['type'] . ", Data: " . json_encode($event['data']) . "\n";
}
// Get latest events by event type
$latestEvents = $client->streamEvents(
'/',
null,
null,
'io.genesisdb.app.customer-updated'
);
foreach ($latestEvents as $event) {
echo "Latest Event: " . $event['type'] . "\n";
}
// Observe events as they occur
foreach ($client->observeEvents('/customer') as $event) {
echo "Received event: " . $event->getType() . "\n";
echo "Data: " . json_encode($event->getData()) . "\n";
}
// Observe events from a specific point
foreach ($client->observeEvents('/customer', '2d6d4141-6107-4fb2-905f-445730f4f2a9', true) as $event) {
echo "Received event: " . $event->getType() . "\n";
}
// Observe only latest events of a specific type
foreach ($client->observeEvents('/customer', null, null, 'io.genesisdb.app.customer-updated') as $event) {
echo "Latest event: " . $event->getType() . "\n";
}
// Commit events without preconditions
$events = [
[
'source' => 'io.genesisdb.app',
'subject' => '/customer',
'type' => 'io.genesisdb.app.customer-added',
'data' => [
'firstName' => 'Bruce',
'lastName' => 'Wayne',
'emailAddress' => 'bruce.wayne@enterprise.wayne'
]
],
[
'source' => 'io.genesisdb.app',
'subject' => '/customer',
'type' => 'io.genesisdb.app.customer-added',
'data' => [
'firstName' => 'Alfred',
'lastName' => 'Pennyworth',
'emailAddress' => 'alfred.pennyworth@enterprise.wayne'
]
],
[
'source' => 'io.genesisdb.store',
'subject' => '/article',
'type' => 'io.genesisdb.store.article-added',
'data' => [
'name' => 'Tumbler',
'color' => 'black',
'price' => 2990000.00
]
],
[
'source' => 'io.genesisdb.app',
'subject' => '/customer/fed2902d-0135-460d-8605-263a06308448',
'type' => 'io.genesisdb.app.customer-personaldata-changed',
'data' => [
'firstName' => 'Angus',
'lastName' => 'MacGyver',
'emailAddress' => 'angus.macgyer@phoenix.foundation'
]
]
];
$client->commitEvents($events);
Preconditions allow you to enforce certain checks on the server before committing events. Genesis DB supports multiple precondition types:
Ensures that a subject is new (has no existing events):
$events = [
[
'source' => 'io.genesisdb.app',
'subject' => '/user/456',
'type' => 'io.genesisdb.app.user-created',
'data' => [
'firstName' => 'John',
'lastName' => 'Doe',
'email' => 'john.doe@example.com'
]
]
];
$preconditions = [
[
'type' => 'isSubjectNew',
'payload' => [
'subject' => '/user/456'
]
]
];
$client->commitEvents($events, $preconditions);
Evaluates a query and ensures the result is truthy. Supports the full GDBQL feature set including complex WHERE clauses, aggregations, and calculated fields.
Basic uniqueness check:
$events = [
[
'source' => 'io.genesisdb.app',
'subject' => '/user/456',
'type' => 'io.genesisdb.app.user-created',
'data' => [
'firstName' => 'John',
'lastName' => 'Doe',
'email' => 'john.doe@example.com'
]
]
];
$preconditions = [
[
'type' => 'isQueryResultTrue',
'payload' => [
'query' => "STREAM e FROM events WHERE e.data.email == 'john.doe@example.com' MAP COUNT() == 0"
]
]
];
$client->commitEvents($events, $preconditions);
Business rule enforcement (transaction limits):
$events = [
[
'source' => 'io.genesisdb.banking',
'subject' => '/user/123/transactions',
'type' => 'io.genesisdb.banking.transaction-processed',
'data' => [
'amount' => 500.00,
'currency' => 'EUR'
]
]
];
$preconditions = [
[
'type' => 'isQueryResultTrue',
'payload' => [
'query' => "STREAM e FROM events WHERE e.subject UNDER '/user/123' AND e.type == 'transaction-processed' AND e.time >= '2024-01-01T00:00:00Z' MAP SUM(e.data.amount) + 500 <= 10000"
]
]
];
$client->commitEvents($events, $preconditions);
Complex validation with aggregations:
$events = [
[
'source' => 'io.genesisdb.events',
'subject' => '/conference/2024/registrations',
'type' => 'io.genesisdb.events.registration-created',
'data' => [
'attendeeId' => 'att-789',
'ticketType' => 'premium'
]
]
];
$preconditions = [
[
'type' => 'isQueryResultTrue',
'payload' => [
'query' => "STREAM e FROM events WHERE e.subject UNDER '/conference/2024/registrations' AND e.type == 'registration-created' GROUP BY e.data.ticketType HAVING e.data.ticketType == 'premium' MAP COUNT() < 50"
]
]
];
$client->commitEvents($events, $preconditions);
Supported GDBQL Features in Preconditions:
- WHERE conditions with AND/OR/IN/BETWEEN operators
- Hierarchical subject queries (UNDER, DESCENDANTS)
- Aggregation functions (COUNT, SUM, AVG, MIN, MAX)
- GROUP BY with HAVING clauses
- ORDER BY and LIMIT clauses
- Calculated fields and expressions
- Nested field access (e.data.address.city)
- String concatenation and arithmetic operations
If a precondition fails, the commit returns HTTP 412 (Precondition Failed) with details about which condition failed.
$events = [
[
'source' => 'io.genesisdb.app',
'subject' => '/user/456',
'type' => 'io.genesisdb.app.user-created',
'data' => [
'firstName' => 'John',
'lastName' => 'Doe',
'email' => 'john.doe@example.com'
],
'options' => [
'storeDataAsReference' => true
]
]
];
$client->commitEvents($events);
// Erase all data for a specific subject (GDPR compliance)
$client->eraseData('/user/456');
// Query using GDBQL
$query = 'STREAM e FROM events WHERE e.type == "io.genesisdb.app.customer-added" ORDER BY e.time DESC LIMIT 20 MAP { subject: e.subject, firstName: e.data.firstName }';
$results = $client->q($query);
foreach ($results as $result) {
echo "Result: " . json_encode($result) . "\n";
}
// Check API status
$pingResponse = $client->ping();
echo "Ping response: " . $pingResponse . "\n";
// Run audit to check event consistency
$auditResponse = $client->audit();
echo "Audit response: " . $auditResponse . "\n";
MIT
- E-Mail: mail@genesisdb.io
- URL: https://www.genesisdb.io
- Docs: https://docs.genesisdb.io