datastax/php-driver
PHP extension (wrapper over DataStax C/C++ driver) providing a feature-rich, tunable client for Apache Cassandra 2.1+ via CQL3 and the native binary protocol. Prebuilt binaries available. Driver is in maintenance mode; use DSE PHP driver for DSE.
Install the PECL extension:
pecl install cassandra
Add to php.ini:
extension=cassandra.so
Basic Laravel Integration:
Create a service provider (app/Providers/CassandraServiceProvider.php):
use Cassandra;
class CassandraServiceProvider extends ServiceProvider {
public function register() {
$this->app->singleton('cassandra', function() {
$cluster = Cassandra::cluster()
->withContactPoints(['127.0.0.1'])
->withPort(9042)
->build();
return $cluster->connect('your_keyspace');
});
}
}
First Query:
$session = app('cassandra');
$result = $session->execute('SELECT * FROM users LIMIT 10');
foreach ($result as $row) {
dd($row); // Debug row data
}
SimpleStatement.executeAsync().$session->schema().Connection Management:
// Singleton pattern (recommended)
$cluster = Cassandra::cluster()
->withContactPoints(config('cassandra.contact_points'))
->withPort(config('cassandra.port'))
->withLoadBalancingPolicy(new \Cassandra\LoadBalancing\DCAwareRoundRobinPolicy(
config('cassandra.local_dc')
))
->build();
Query Execution:
// Simple query
$result = $session->execute('SELECT * FROM users WHERE id = ?', [1]);
// Prepared statement (reused)
$prepared = $session->prepare('INSERT INTO users (id, name) VALUES (?, ?)');
$session->execute($prepared, [2, 'John Doe']);
Async + Parallelism:
$future1 = $session->executeAsync('SELECT * FROM table1');
$future2 = $session->executeAsync('SELECT * FROM table2');
$result1 = $future1->get();
$result2 = $future2->get();
Pagination:
$statement = new \Cassandra\SimpleStatement('SELECT * FROM large_table');
$statement->setFetchSize(100);
$result = $session->execute($statement);
while ($result->hasMorePages()) {
$result = $session->execute($statement, [], ['result_set' => $result->getPagingStateToken()]);
}
Eloquent Integration (Custom Model):
class CassandraUser extends Model {
protected $connection = 'cassandra';
protected $table = 'users';
public $incrementing = false;
protected $primaryKey = 'id';
public static function boot() {
static::addGlobalScope('cassandra', function (Builder $builder) {
$builder->getQuery()->from('users');
});
}
}
Query Builder Wrapper:
// app/Database/Cassandra/QueryBuilder.php
class CassandraQueryBuilder {
protected $session;
public function __construct($session) {
$this->session = $session;
}
public function select($columns, $table) {
$query = "SELECT " . implode(', ', $columns) . " FROM $table";
return $this->session->execute($query);
}
}
Event Listeners for Schema Changes:
// Listen for model events to sync Cassandra schema
Model::saved(function ($model) {
if ($model->connection === 'cassandra') {
// Trigger schema update logic
}
});
Caching Layer:
// Use Cassandra as a cache backend
Cache::extend('cassandra', function ($app) {
return Cache::repository(new CassandraStore(
$app['cassandra'],
config('cache.cassandra')
));
});
Memory Leaks:
FutureSession or Timestamp::toDateTime() may leak memory.executeAsync() with explicit timeouts:
$future = $session->executeAsync($statement, [], ['timeout' => 5]);
Hashing Quirks:
IS_TRUE/IS_FALSE hash inconsistently to 1 in PHP 7.$hash = spl_object_hash($row['is_active'] ? true : false);
Type Mismatches:
tinyint/smallint may not map cleanly to PHP integers.$value = (int) $row['tiny_column'];
Async Deadlocks:
get() or wait() on futures:
$future->get(); // Release resources
Schema Metadata:
$cluster = Cassandra::cluster()->withSchemaMetadata(false);
Enable Logging:
$cluster = Cassandra::cluster()
->withLogLevel(\Cassandra\Logger::LOG_DEBUG)
->withLogFile('/var/log/cassandra_driver.log');
Query Tracing:
$options = ['tracing' => true];
$result = $session->execute($statement, [], $options);
dd($result->getTracingInfo());
Connection Pooling:
$cluster = Cassandra::cluster()
->withConnectionsPerHost(3)
->withIoThreads(4);
Custom Load Balancing:
$cluster = Cassandra::cluster()
->withLoadBalancingPolicy(new CustomPolicy());
Retry Policies:
$cluster = Cassandra::cluster()
->withRetryPolicy(new \Cassandra\RetryPolicy\DowngradingConsistencyRetryPolicy());
Type Serialization:
Override Cassandra\Type\Type::serialize() for custom types.
Event Hooks:
Extend Cassandra\Event\EventListener for pre/post-query hooks.
Service Container Binding:
$this->app->singleton('cassandra.cluster', function () {
return Cassandra::cluster()->build();
});
Configuration: Use Laravel’s config system:
// config/cassandra.php
return [
'contact_points' => env('CASSANDRA_CONTACT_POINTS', '127.0.0.1'),
'port' => env('CASSANDRA_PORT', 9042),
'keyspace' => env('CASSANDRA_KEYSPACE', 'default'),
'timeout' => env('CASSANDRA_TIMEOUT', 5),
];
Migration Support: Create a custom migrator for Cassandra schema changes:
class CassandraSchema {
public static function createTable($table, $columns) {
$query = "CREATE TABLE $table (" . implode(', ', $columns) . ")";
app('cassandra')->execute($query);
}
}
Testing:
Use Cassandra\Future for async testing:
public function testAsyncQuery() {
$future = $this->session->executeAsync('SELECT * FROM test');
$this->assertTrue($future->isReady());
$result = $future->get();
$this->assertCount(1, $result);
}
How can I help you explore Laravel packages today?