stefanak-michal/bolt
Low-level PHP library for communicating with graph databases over TCP using the Bolt protocol. Works with Neo4j, Memgraph, Amazon Neptune and others, supports Bolt up to version 6, requires PHP 8.1+ with mbstring, and needs sockets or openssl only for certain connection classes.
Log facade / Monolog channels with no shim.AProtocol constructor arguments changed, but this is explicitly safe only for consumers that obtain the protocol via Bolt::build. Any Laravel service provider or test double that instantiated AProtocol directly is impacted.autoload.php removed: Composer-only installation now required. Non-Composer or manual-vendored deployments break.UnsupportedType structure added: unknown protocol types now surface as an explicit value rather than an ambiguous failure — a real reduction in silent-corruption risk for heterogeneous graph stores.run/pull chaining reduces latency for batch operations — useful for Laravel queue jobs and bulk ingestion.autoload.php removed) — irrelevant for standard Laravel apps, blocking for hand-vendored setups.Psr\Log\LoggerInterface, so Bolt traffic lands in existing Monolog channels and stack drivers. This collapses a previously bespoke integration into a container binding.GraphQueryBuilder; unchanged in principle:
class GraphQueryBuilder {
public function run(string $cypher, array $params): array {
$bolt = (new Bolt(new Socket('127.0.0.1', 7687)))
->setProtocolVersions(6.1)
->setLogger(app(\Psr\Log\LoggerInterface::class)) // v7.5.0+
->build();
return $bolt->run($cypher, $params)->pullAll()->getResponses();
}
}
hello/logon/run/pull) still requires boilerplate; the Client helper or a Laravel service wrapper remains the mitigation.DatabaseManager abstraction. Bookmarks partially mitigate the correctness half of this problem (consistent reads), but not the resource-exhaustion half.composer.json and treat minor bumps as review-required.AProtocol Construction — the constructor signature change is safe only via Bolt::build. Mock-based unit tests that instantiate AProtocol directly will fail at upgrade time.Response::isSuccess(). The new UnsupportedType structure reduces (but does not eliminate) silent mis-typing across heterogeneous backends.Psr\Log\LoggerInterface to the driver; route Bolt diagnostics through config/logging.php channels. Replaces the previous custom debug-mode approach.Illuminate\Database\Connectors\ConnectionFactory, or service-container binding.Illuminate\Database\Query\Builder for Cypher.$bolt = app(BoltService::class);
foreach (User::all() as $user) {
$bolt->run("CREATE (u:User {id: \$id, name: \$name})", [
'id' => $user->id,
'name' => $user->name,
]);
}
setProtocolVersions(...).autoload.php breaks manual vendoring.Bolt::build; do not construct AProtocol directly.UnsupportedType, which should be handled explicitly rather than cast.begin/commit/rollback supported; bookmarks complement transactions for cross-connection consistency.7687; confirm the server's Bolt version.v7.5.0, pin the version, audit for PackStream setter usage and direct AProtocol instantiation, and confirm Composer-only install.'connections' => [
'neo4j' => [
'driver' => 'bolt',
'host' => env('NEO4J_HOST', '127.0.0.1'),
'port' => env('NEO4J_PORT', 7687),
'username' => env('NEO4J_USER'),
'password' => env('NEO4J_PASSWORD'),
'protocol_versions' => [6.1], // lower if the server requires it
'log_channel' => env('NEO4J_LOG_CHANNEL', 'stack'),
],
],
Illuminate\Database\Connection; inject the PSR-3 logger; wrap bookmark capture/consume.
class BoltConnection extends Connection {
public function run($query, $bindings = [], $useReadPdo = true) {
$bolt = (new Bolt(new Socket($this->config['host'], $this->config['port'])))
->setProtocolVersions($this->config['protocol_versions'])
->setLogger(app(\Psr\Log\LoggerInterface::class))
->build();
return $bolt->run($query, $bindings)->pullAll()->getResponses();
}
}
DatabaseMigrations; add a Bolt-version compatibility test for the pinned server; load-test with Laravel Dusk/Artillery.sockets/openssl/mbstring enabled in php.ini.AProtocol construction this quarter.Bolt::$debug); log query execution time and connection lifecycle events.7687; validate Cypher in Neo4j Bloom; profile with Neo4j Profiler or DB::enableQueryLog().INVALID_SIGNATURE) and documented Cypher traversal patterns.max_connections.
Note that pooling and bookmarks must be designed together: a pooled read connection must consume the bookmark produced by the write connection, or consistency guarantees silently lapse.AProtocol use or PackStream setter calls — mitigated by the audit checklist.How can I help you explore Laravel packages today?