Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Bolt Laravel Package

stefanak-michal/bolt

Low-level PHP Bolt protocol driver (Bolt <= 6) for TCP socket communication with graph databases like Neo4j, Memgraph, Amazon Neptune, and others. Supports PHP 8.1+ and tracks official protocol message specifications across versions.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require stefanak-michal/bolt
    
  2. Basic connection:

    use Bolt\Bolt;
    use Bolt\connection\Socket;
    
    $connection = new Socket('localhost', 7687); // Default Neo4j Bolt port
    $bolt = new Bolt($connection);
    $protocol = $bolt->build(); // Auto-selects latest supported version (4.3-6)
    
  3. First query:

    $protocol
        ->hello()
        ->logon(['scheme' => 'basic', 'principal' => 'neo4j', 'credentials' => 'password'])
        ->run('MATCH (n) RETURN n LIMIT 10')
        ->pullAll();
    

Key Starting Points

  • Bolt class: Factory for protocol versions (default: 4.3-6).
  • Socket/StreamSocket: Connection classes (use Socket for plain TCP, StreamSocket for SSL).
  • Client helper: Simplified CRUD operations (see Implementation Patterns).

Implementation Patterns

Core Workflow

  1. Connection & Handshake:

    $protocol = (new Bolt(new Socket('host', 7687)))
        ->setProtocolVersions(5.4) // Optional: Force specific version
        ->build();
    $protocol->hello()->getResponse();
    
  2. Query Execution:

    // Pipeline pattern (recommended for performance)
    $protocol
        ->run('MATCH (n) WHERE n.name = $name RETURN n', ['name' => 'Alice'])
        ->pullAll(); // Fetch all records at once
    
  3. Transactions:

    $protocol
        ->begin()
        ->run('CREATE (n:Test {id: $id})', ['id' => 1])
        ->commit();
    

Integration Tips

  • Laravel Service Provider:

    // config/bolt.php
    'connections' => [
        'neo4j' => [
            'host' => env('NEO4J_HOST', 'localhost'),
            'port' => env('NEO4J_PORT', 7687),
            'user' => env('NEO4J_USER', 'neo4j'),
            'pass' => env('NEO4J_PASS', 'password'),
            'version' => '5.4',
        ],
    ];
    
    // app/Providers/BoltServiceProvider.php
    public function register()
    {
        $this->app->singleton('bolt', function ($app) {
            $config = config('bolt.connections.neo4j');
            $connection = new Socket($config['host'], $config['port']);
            return (new Bolt($connection))
                ->setProtocolVersions($config['version'])
                ->build();
        });
    }
    
  • Query Builder Helper:

    // app/Services/Neo4jQueryBuilder.php
    class Neo4jQueryBuilder {
        protected $protocol;
    
        public function __construct($protocol) {
            $this->protocol = $protocol;
        }
    
        public function findNodes(string $label, array $conditions = []) {
            $query = "MATCH (n:$label)";
            if (!empty($conditions)) {
                $query .= ' WHERE ' . $this->buildConditions($conditions);
            }
            $query .= ' RETURN n';
    
            return $this->protocol
                ->run($query, $conditions)
                ->pullAll();
        }
    }
    
  • Event Listeners:

    // Listen for model events (e.g., Eloquent)
    public function handle(NodeCreated $event) {
        $bolt = app('bolt');
        $bolt->run('CREATE (n:User {email: $email})', ['email' => $event->user->email]);
    }
    

Performance Patterns

  • Batching:

    // Process large datasets in chunks
    $protocol->run('MATCH (n) RETURN n SKIP $skip LIMIT 100', ['skip' => 0]);
    while (true) {
        $records = $protocol->pull()->getResponse();
        if (empty($records)) break;
        // Process records...
        $protocol->discard(); // Free server memory
        $protocol->run('... SKIP $skip LIMIT 100', ['skip' => $skip += 100]);
    }
    
  • Parameterized Queries:

    // Avoid string concatenation for security/performance
    $protocol->run(
        'MATCH (n:User {email: $email}) RETURN n',
        ['email' => $user->email]
    );
    

Gotchas and Tips

Common Pitfalls

  1. Protocol Version Mismatch:

    • Issue: Using Bolt 6 with Neo4j 4.x will fail.
    • Fix: Explicitly set supported versions:
      $bolt->setProtocolVersions(4.4, 5.0); // Only allow these
      
  2. Connection Timeouts:

    • Issue: Default socket timeouts may be too short for large queries.
    • Fix: Extend the Socket class or use StreamSocket with custom timeout:
      $socket = new StreamSocket('ssl://host:7687', [
          'timeout' => 30, // 30 seconds
      ]);
      
  3. Memory Leaks with Large Results:

    • Issue: pullAll() loads all records into memory.
    • Fix: Use pull() in a loop with discard():
      $protocol->run('MATCH (n) RETURN n');
      while (true) {
          $records = $protocol->pull()->getResponse();
          if (empty($records)) break;
          // Process records...
          $protocol->discard();
      }
      
  4. Authentication Errors:

    • Issue: Incorrect logon scheme/credentials.
    • Fix: Verify the scheme (e.g., basic, bearer) and debug responses:
      $bolt->debug(true); // Enable hex debugging
      $response = $protocol->logon(['scheme' => 'basic', ...])->getResponse();
      
  5. Cypher Parameter Types:

    • Issue: Passing wrong types (e.g., array instead of object for dictionaries).
    • Fix: Use Bytes class for binary data or implement IPackListGenerator for custom types.

Debugging Tips

  • Enable Debugging:
    Bolt::$debug = true; // Hex dump of all messages
    
  • Inspect Responses:
    $response = $protocol->getResponse();
    if ($response->isSuccess()) {
        // Handle success
    } else {
        throw new \RuntimeException($response->getFailureMessage());
    }
    
  • Check Server Logs: Neo4j logs Bolt protocol messages at DEBUG level. Enable in neo4j.conf:
    dbms.logs.query.debug=true
    

Extension Points

  1. Custom Connection Classes:

    • Extend AbstractConnection to support custom protocols (e.g., WebSocket):
      class WebSocketConnection extends AbstractConnection {
          public function connect() { /* ... */ }
      }
      
  2. Protocol Extensions:

    • Add custom Bolt messages by extending AbstractProtocol:
      class CustomProtocol extends AbstractProtocol {
          public function customMessage(array $extra = []) {
              return $this->sendMessage('+Custom', $extra);
          }
      }
      
  3. Response Decorators:

    • Wrap Response objects to transform data:
      $response = $protocol->run('...')->pull()->getResponse();
      $nodes = collect($response->getRecords())->map(function ($record) {
          return (object) $record['n'];
      });
      

Configuration Quirks

  • PackStream Version:
    • Defaults to 1. For Bolt 6, set explicitly:
      $bolt->setPackStreamVersion(2);
      
  • Pipeline Limits:
    • Neo4j may reject pipelines with >1000 messages. Monitor server logs for PipelineTooLarge.
  • SSL/TLS:
    • Ensure openssl extension is enabled for StreamSocket with SSL:
      $socket = new StreamSocket('ssl://host:7687', [
          'ssl' => [
              'verify_peer' => false, // Disable for self-signed certs (not recommended)
          ],
      ]);
      

Performance Gotchas

  • Large Transactions:
    • Avoid long-running transactions (>5 minutes). Use commit()/rollback() frequently.
  • Parameter Binding:
    • Bind parameters after the query string to avoid syntax errors:
      // Correct
      $protocol->run('MATCH (n) WHERE n.id = $id', ['id' => 1]);
      
      // Incorrect (syntax error)
      $protocol
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony