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

Neo4J Php Client Laravel Package

laudis/neo4j-php-client

Typed Neo4j PHP client/driver with Bolt and Neo4j (auto-routed) support. Intuitive, extensible API with easy configuration, built with input from the official driver team and validated via Neo4j Testkit for reliability.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require laudis/neo4j-php-client
    

    Ensure PHP ≥ 7.4 and extensions bcmath, json, and sockets are enabled.

  2. Basic Client Setup Configure a Bolt driver (recommended for production) or Neo4j auto-routed driver:

    use Laudis\Neo4j\ClientBuilder;
    
    $client = ClientBuilder::create()
        ->withDriver('bolt', 'bolt+s://neo4j:password@localhost:7687')
        ->withDefaultDriver('bolt')
        ->build();
    
  3. First Query Run a simple Cypher query:

    $result = $client->run('CREATE (n:Test {name: $name}) RETURN n', ['name' => 'Laravel']);
    $node = $result->first()->get('n');
    

Where to Look First


Implementation Patterns

1. Transaction Workflows

Idempotent Transactions (Recommended)

Use writeTransaction/readTransaction for atomic operations with automatic retries:

$userId = Uuid::v4();
$client->writeTransaction(function (TransactionInterface $tx) use ($userId) {
    $tx->run('MERGE (u:User {id: $id}) SET u.name = $name', [
        'id' => $userId,
        'name' => 'John Doe'
    ]);
});
  • Key: Ensure operations are idempotent (e.g., MERGE instead of CREATE).

Unmanaged Transactions (Advanced)

For fine-grained control (e.g., custom rollback logic):

$tx = $client->beginTransaction();
try {
    $tx->run('CREATE (n:Order {id: $id})', ['id' => 'order-123']);
    $tx->commit();
} catch (\Exception $e) {
    $tx->rollback();
    throw $e;
}

2. Query Patterns

Parameterized Queries

Use ParameterHelper to disambiguate empty arrays:

use Laudis\Neo4j\ParameterHelper;

$client->run('MATCH (n) WHERE n.tags CONTAINS ALL $tags RETURN n', [
    'tags' => ParameterHelper::asList(['laravel', 'neo4j'])
]);

Batching

Execute multiple statements in a single transaction:

$client->writeTransaction(function (TransactionInterface $tx) {
    $tx->runStatements([
        Statement::create('CREATE (n1:Node1 {id: $id})', ['id' => 1]),
        Statement::create('CREATE (n2:Node2 {id: $id})', ['id' => 2])
    ]);
});

3. Laravel Integration

Service Provider

Bind the client to Laravel’s container:

// config/neo4j.php
return [
    'connection' => 'bolt+s://user:pass@localhost:7687',
];

// app/Providers/Neo4jServiceProvider.php
public function register()
{
    $this->app->singleton(Neo4jClient::class, function ($app) {
        return ClientBuilder::create()
            ->withDriver('bolt', config('neo4j.connection'))
            ->withDefaultDriver('bolt')
            ->build();
    });
}

Eloquent-like Queries

Create a query builder facade:

// app/Facades/Neo4j.php
public static function run(string $query, array $params = []): CypherList
{
    return app(Neo4jClient::class)->run($query, $params);
}

// Usage in controllers:
$users = Neo4j::run('MATCH (u:User) RETURN u', ['limit' => 10]);

Model Events

Hook into Laravel’s lifecycle to sync with Neo4j:

// app/Models/User.php
protected static function booted()
{
    static::created(function ($user) {
        app(Neo4jClient::class)->run(
            'MERGE (u:User {email: $email}) SET u.name = $name',
            ['email' => $user->email, 'name' => $user->name]
        );
    });
}

4. Result Handling

Hydration

Convert results to Laravel collections or DTOs:

use Laudis\Neo4j\Types\Node;

$results = $client->run('MATCH (u:User) RETURN u');
$users = collect($results)->map(function ($row) {
    $node = $row->get('u');
    return (object) [
        'id' => $node->getProperty('id'),
        'name' => $node->getProperty('name')
    ];
});

Summarized Results

Access query metadata:

$summarized = $client->run('MATCH (n) RETURN n', [], 'default', SummarizedResultFormatter::class);
$summary = $summarized->getSummary();
$plan = $summary->getPlan(); // Query execution plan

Gotchas and Tips

Pitfalls

  1. Non-Idempotent Transactions

    • Issue: Transactions with side effects (e.g., incrementing counters) may fail on retries.
    • Fix: Move side effects outside the transaction or use idempotent operations.
      // ❌ Bad: External counter modified inside transaction
      $client->writeTransaction(function (TransactionInterface $tx) use (&$counter) {
          $tx->run('CREATE (n)');
          $counter++; // ❌ Not idempotent!
      });
      
      // ✅ Good: Idempotent + side effect outside
      $client->writeTransaction(function (TransactionInterface $tx) {
          $tx->run('MERGE (n:Counter {id: "total"}) SET n.value = $value', ['value' => 1]);
      });
      $counter = $client->run('MATCH (n:Counter) RETURN n.value AS value')->first()->get('value');
      
  2. Parameter Type Ambiguity

    • Issue: Empty arrays default to CypherList. Use ParameterHelper for clarity.
      // ❌ Ambiguous: Is this a list or map?
      $client->run('UNWIND $tags AS tag RETURN tag', ['tags' => []]);
      
      // ✅ Explicit
      $client->run('UNWIND $tags AS tag RETURN tag', ['tags' => ParameterHelper::asList([])]);
      
  3. Connection Timeouts

    • Issue: Bolt connections may hang in high-latency environments.
    • Fix: Configure timeouts in the driver URI:
      ->withDriver('bolt', 'bolt+s://user:pass@localhost:7687?connection_timeout=5s')
      
  4. Result Caching

    • Issue: Large result sets consume memory.
    • Fix: Stream results or use LIMIT:
      $results = $client->run('MATCH (n) RETURN n SKIP $offset LIMIT $limit', [
          'offset' => 0,
          'limit' => 100
      ]);
      

Debugging Tips

  1. Enable Logging Configure the driver to log queries and errors:

    $client = ClientBuilder::create()
        ->withDriver('bolt', 'bolt://user:pass@localhost')
        ->withLogging(true)
        ->build();
    
  2. Query Profiling Use PROFILE to analyze slow queries:

    $result = $client->run('PROFILE MATCH (n) WHERE n.property = $value RETURN n', ['value' => 'test']);
    $plan = $result->getSummary()->getPlan();
    
  3. Bookmarks for Consistency Use bookmarks to ensure read-your-writes consistency in clusters:

    $client->run('MATCH (n) RETURN n', [], null, null, ['bookmark' => 'bm_123']);
    

Extension Points

  1. Custom Formatters Override result formatting (e.g., for JSON APIs):
    use Laudis\Neo4j\Formatters\ResultFormatterInterface;
    
    class JsonResultFormatter implements ResultFormatterInterface {
        public function format(array $data): string {
            return json_encode($data);
        }
    }
    
    $client->run('MATCH (n) RETURN n', [],
    
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.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony