Weave 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

Client Laravel Package

tarantool/client

Pure PHP client for Tarantool 1.7.1+, supporting Unix sockets, SQL, custom types like decimals and UUIDs, middleware, and full customization with thorough testing.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup (v0.11 requires PHP 8.2+)

  1. Check your runtime first — this release is a hard break:

    • PHP 8.2 or newer (7.x and 8.0–8.1 are dropped). Laravel 10/11/12 projects on 8.2+ are fine; older Sail/Homestead images are not.
    • rybakit/msgpack >= 0.11.2 (pulled in automatically, but pin it if you constrain it yourself).
  2. Installation:

    composer require tarantool/client:^0.11
    

    For Decimal (Tarantool >= 2.3) and UUID support, install the PHP extensions:

    pecl install decimal uuid
    
  3. First connection:

    use Tarantool\Client\Client;
    
    $client = Client::fromDsn('tcp://127.0.0.1:3301');
    

    Or via defaults:

    $client = Client::fromDefaults(); // 127.0.0.1:3301
    
  4. First query (binary protocol):

    $space  = $client->getSpace('users');
    $result = $space->select(\Tarantool\Client\Criteria::key([1]));
    print_r($result); // [[1, "user_data"]]
    
  5. First SQL query (if enabled server-side):

    print_r($client->execute("SELECT * FROM users WHERE id = 1"));
    

Where to look first

  • Tarantool\Client\Client (entry point), Tarantool\Client\Schema\Space, Tarantool\Client\Criteria, Tarantool\Client\Operations.
  • In v0.11 every public method now has native parameter and property types — your IDE/reflection is now the source of truth for accepted arguments. Read the signatures before guessing.
  • Bind it in Laravel rather than new-ing it in controllers:
    // AppServiceProvider::register()
    $this->app->singleton(Client::class, fn () => Client::fromOptions(config('services.tarantool')));
    

Implementation Patterns

1. Connection management

  • Reusable/persistent connections — avoid reconnecting per request:
    $client = Client::fromOptions([
        'uri'        => 'tcp://127.0.0.1:3301',
        'persistent' => true,
    ]);
    
  • Container singleton (see above) is the day-to-day pattern; for Octane/queue workers the singleton survives across requests, so pair it with RetryMiddleware rather than assuming the socket is alive.

2. Middleware workflows

Middleware is the normal extension seam: authentication, retries, logging.

$client = Client::fromDefaults()
    ->withMiddleware(
        \Tarantool\Client\Middleware\RetryMiddleware::exponential(3),   // outer
        new \Tarantool\Client\Middleware\AuthenticationMiddleware('user', 'pass') // inner
    );

Logging:

$client->withMiddleware(new \Tarantool\Client\Middleware\LoggingMiddleware(
    new \Monolog\Logger('tarantool')
));

3. Space operations (CRUD)

$space->insert([1, 'data']);

$user = $space->select(\Tarantool\Client\Criteria::key([1]))[0];

$space->update([1], \Tarantool\Client\Operations::set(1, 'updated_data'));

$space->delete([1]);

Indexed / bounded queries:

$space->select(
    \Tarantool\Client\Criteria::index('secondary')->andKey(['value'])->andLimit(10)
);

4. SQL protocol

$result = $client->execute("SELECT * FROM users WHERE id = ?", [1]);

$client->beginTransaction();
try {
    $client->execute("INSERT INTO users VALUES (?, ?)", [2, 'new_user']);
    $client->commit();
} catch (\Throwable $e) {
    $client->rollback();
    throw $e;
}

5. Custom types

$space->insert([
    1,
    \Tarantool\Client\Decimal::fromString('123.45'),
    \Ramsey\Uuid\Uuid::uuid4(),
]);

With typed APIs in v0.11, pass the real objects/values — no stringly-typed shortcuts.

6. Error handling

try {
    $client->execute("SELECT * FROM nonexistent");
} catch (\Tarantool\Client\Exception\CommunicationFailed $e) {
    // socket/connection level
} catch (\Tarantool\Client\Exception\RequestFailed $e) {
    // server rejected the request
} catch (\TypeError $e) {
    // NEW in 0.11: argument failed a native type check
}

Catching \TypeError explicitly is worth it during the upgrade — it distinguishes "my code is wrong" from "the server said no".


Gotchas and Tips

Pitfalls

  1. PHP 8.2 is a hard floor. Composer will refuse to install on 8.1 and below. If you support multiple PHP versions in CI, split the matrix or drop the old legs; otherwise composer update fails at resolution time, not runtime.

  2. Native types are now enforced at runtime — coercion is gone. Previously loose arguments (numeric strings for keys, null for non-nullable params, ints where floats/strings were declared) were silently accepted. Now they throw TypeError.

    • Cast at the boundary: (int) $request->input('id'), (string) $value.
    • Add declare(strict_types=1); to new files so behaviour matches between dev and prod.
    • Run your static analyser before deploying; Psalm 5/6 will flag the same mismatches the runtime now throws.
  3. Custom implementations must be re-signed. If you wrote your own Middleware, Packer, or similar, v0.11's typed interfaces mean a missing parameter type, missing return type, or widened type is a fatal error at class load, not a soft deprecation. Update signatures to match the interface exactly before upgrading.

  4. Middleware order still matters. Retry must be outside authentication so a retried request re-authenticates:

    // correct
    ->withMiddleware(RetryMiddleware::exponential(3), new AuthenticationMiddleware($u, $p))
    
  5. Persistent connections cost you on cold-start-heavy local dev but pay off in long-running apps. Common compromise:

    'persistent' => ! app()->isLocal(),
    

    With Octane/queues, always pair persistence with retry logic.

  6. SQL vs binary protocol. SQL is off by default on the server (box.cfg{sql_enabled = true}). Binary protocol is faster for bulk work but requires you to know the schema. Don't reach for SQL "because it's familiar" in hot paths.

  7. Decimal/UUID extensions. Without decimal/uuid you'll get UnsupportedTypeException. Fall back to strings if you can't install extensions on the host.

  8. Timeouts. Defaults (connect_timeout 5s, socket_timeout 5s) are short for cross-AZ/cloud traffic:

    'connect_timeout' => 10.0,
    'socket_timeout'  => 30.0,
    
  9. Large payloads. Tuples above ~1MB can hit PHP/msgpack limits. Split the work or move it into a Lua function and call it.

  10. No client-side batching primitive. Each request is a round trip; for bulk writes use a stored procedure (call) that loops server-side, or chunk your loop and measure. Don't assume a multi()-style API exists.

Debugging tips

  1. Logging middleware — raw request/response visibility:

    $client->withMiddleware(new \Tarantool\Client\Middleware\LoggingMiddleware(
        new \Monolog\Logger('tarantool', [
            'handlers' => [new \Monolog\Handler\StreamHandler('php://stderr')],
        ])
    ));
    
  2. Verify the connection is alive inside middleware:

    class ConnectionGuard implements \Tarantool\Client\Middleware
    {
        public function handle(\Tarantool\Client\Request $request, callable $next): \Tarantool\Client\Response
        {
            if (! $request->getConnection()->isConnected()) {
                throw new \RuntimeException('Connection lost');
            }
    
            return $next($request);
        }
    }
    
  3. Schema mismatches are quiet. Sending a string to a number field fails without much ceremony. Use named-field operations (Operations::set('field_name', $value), Tarantool >= 2.3) to make intent explicit.

  4. Bound the retries. Cap attempts and delay to avoid hammering a dead node:

    \Tarantool\Client\Middleware\RetryMiddleware::exponential(3, 100); // attempts, max delay ms
    
  5. Upgrade checklist after 0.11: bump PHP in CI/Docker/Sail → composer require tarantool/client:^0.11 → run Psalm/PHPStan → grep for custom Middleware/Packer implementations → re-run integration tests against a real Tarantool instance (unit tests won't catch type/signature breakage in the wire protocol).

Extension points

  1. Custom middleware — request/response transformation, rate limiting, circuit breaking:

    class PingShortcut implements \Tarantool\Client\Middleware
    {
        public function handle(\Tarantool\Client\Request $request, callable $next): \Tarantool\Client\Response
        {
            if ($request instanceof \Tarantool\Client\Request\CallRequest
                && $request->getFunction() === 'admin.ping') {
                return new \Tarantool\Client\Response\SuccessResponse([['pong']]);
            }
    
            return $next($request);
        }
    }
    
  2. Custom Packer — swap serialization (e.g. Protobuf). Implement the typed \Tarantool\Client\Packer interface exactly, then inject via a handler:

    $client = new \Tarantool\Client\Client(
        new \Tarantool\Client\Handler\DefaultHandler($connection, $packer)
    );
    
  3. Custom DSN handling — extend \Tarantool\Client\DsnParser for non-standard URI schemes and drive it from config/services.php.

  4. Testing hooks — v0.11 moved the test tooling to PHPUnit 10 attributes and tarantool/phpunit-extras 0.3. If you extend the package's test helpers, drop the old annotation-style/compatibility helper usages in favour of attributes.

Performance tips

  • Keep one client per process, not per query.
  • Prefer binary protocol + indexed Criteria for hot paths; keep SQL for ad-hoc/reporting.
  • Batch writes server-side via a Lua call rather than N round trips.
  • Cache Space lookups if you resolve the same spaces repeatedly in a request.
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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums