ably/ably-php
Ably Pub/Sub PHP SDK for building realtime messaging apps in PHP. Publish/subscribe, message history, presence, and push via Ably’s scalable platform. Install with Composer and use REST APIs to connect, manage channels, and publish messages.
Installation
composer require ably/ably-php
For Laravel, prefer ably/ably-php-laravel for seamless integration.
First Use Case: Publishing a Message
use Ably\Lib\Ably;
$ably = new Ably\AblyRest([
'key' => env('ABLY_API_KEY'), // Use Laravel's .env
'clientId' => 'laravel-app-' . Str::uuid(),
]);
$channel = $ably->channel('notifications');
$channel->publish('user.created', ['id' => 123, 'name' => 'John Doe']);
Where to Look First
ably/ably-php-laravel for facades and broadcasting.Channel Management
// Attach to a channel (for subscriptions)
$channel = $ably->channel('live-updates');
$channel->attach();
// Detach when done
$channel->detach();
Message Handling
// Subscribe to events
$channel->subscribe('user.updated', function ($message) {
Log::info('Received update:', $message->data);
});
// Publish with metadata
$channel->publish('order.placed', ['orderId' => 456], [
'extras' => ['priority' => 'high'],
'ttl' => 3600, // 1-hour TTL
]);
Batch Operations
// Batch publish to multiple channels
$batch = $ably->batch();
$batch->publish('channel1', 'event1', ['data' => '...']);
$batch->publish('channel2', 'event2', ['data' => '...']);
$batch->send();
Presence Management
$presence = $channel->presence;
$presence->update(['status' => 'online']);
$presence->subscribe(function ($presenceEvent) {
Log::debug('User joined:', $presenceEvent->clientId);
});
Push Notifications
// Configure push for a device
$push = $ably->push;
$push->admin->deviceRegistrations->save([
'deviceId' => 'device123',
'deviceSecret' => 'secret',
'deviceType' => 'ios',
]);
Service Provider Binding:
// config/ably.php
'key' => env('ABLY_API_KEY'),
'clientId' => env('ABLY_CLIENT_ID', 'laravel-app-' . Str::uuid()),
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(AblyRest::class, function ($app) {
return new AblyRest(config('ably'));
});
}
Broadcasting Events:
// Event class
class UserCreated implements ShouldBroadcast
{
public $user;
public function broadcastOn()
{
return new Channel('notifications');
}
}
// Controller
event(new UserCreated($user));
Queue Workers: Use Laravel Queues to defer Ably operations:
Dispatch(new PublishAblyMessage($channel, $event, $data));
Authentication Quirks
clientId matches the token’s clientId to avoid 403 errors.
$ably = new AblyRest([
'authUrl' => 'https://your-auth-service.com/token',
'clientId' => 'user123',
]);
clientId with basic auth unless explicitly required (see #102).Protocol Version
$ably = new AblyRest(['key' => '...', 'protocol' => '1.1']);
Message Serialization
$ably = new AblyRest(['key' => '...', 'useMsgPack' => false]);
Connection Resilience
eu-west-1). Clear cache if needed:
$ably->setOption('rememberedHost', null);
$ably->setOption('timeout', 30); // 30s
Idempotency
$channel->publish('event', $data, ['idempotent' => true, 'id' => uniqid()]);
Enable Logging
$ably->setOption('logLevel', Ably\Lib\LogLevel::DEBUG);
$ably->setOption('logger', new Monolog\Logger('ably'));
HTTP Headers
X-Ably-Lib and Ably-Agent are set:
$ably->setOption('headers', ['X-Custom-Header' => 'value']);
Common Errors
401 Unauthorized: Check API key or token.404 Not Found: Validate channel names (case-sensitive).429 Too Many Requests: Implement exponential backoff:
try {
$channel->publish(...);
} catch (Ably\Lib\Exception\RateLimitExceeded $e) {
sleep($e->getRetryAfter());
retry();
}
Custom HTTP Client Replace the default Guzzle client for advanced use cases:
$ably = new AblyRest([
'key' => '...',
'httpClient' => new CustomHttpClient(),
]);
Event Hooks Extend the SDK’s event system:
$ably->on('messageReceived', function ($message) {
// Pre-process messages
});
Message Transformers Serialize/deserialize messages before sending/receiving:
$channel->setSerializer(new JsonSerializer());
Laravel Broadcasting
Extend the ably/laravel-broadcaster for custom event handling:
// app/Providers/BroadcastServiceProvider.php
public function boot()
{
$this->app->make(AblyBroadcaster::class)->extend('ably', function () {
return new CustomAblyBroadcaster();
});
}
Environment Variables
ABLY_API_KEY in .env:
ABLY_API_KEY=your_key_here
ABLY_CLIENT_ID=laravel-app-${APP_UUID}
Broadcasting Failures
ShouldQueue with retryAfter() for transient failures.Presence Channel Conflicts
users vs. presence:users).Testing
Ably\Lib\Mock\AblyMock for unit tests:
$mock = new AblyMock();
$mock->channel('test')->publish('event', ['data' => 'test']);
$this->assertEquals(['data' => 'test'], $mock->lastPublishedMessage()->data);
How can I help you explore Laravel packages today?