toin0u/digitalocean-v2
Modern DigitalOcean API v2 client for PHP 8.1–8.5. PSR-7/17/18 and HTTPlug compatible, decoupled from any HTTP client. Install via Composer (e.g., with Guzzle) with optional Laravel integration.
Installation:
composer require toin0u/digitalocean-v2 guzzlehttp/guzzle
For Laravel, use the framework-specific package:
composer require graham-campbell/digitalocean
Authentication:
use DigitalOceanV2\Client;
$client = new Client();
$client->authenticate(env('DIGITALOCEAN_TOKEN')); // Store token in .env
First Use Case: Fetch all droplets to verify connectivity:
$droplets = $client->droplet()->getAll();
$client->droplet(), $client->database(), etc.ResultPager for collections (e.g., $client->droplet()->getAll() returns paginated results).Create/Read/Update/Delete (CRUD):
// Create a droplet
$droplet = $client->droplet()->create([
'name' => 'my-droplet',
'region' => 'nyc3',
'size' => 's-1vcpu-1gb',
'image' => 'ubuntu-22-04-x64'
]);
// Update droplet
$client->droplet()->resize($droplet->id, 's-2vcpu-2gb');
// Delete droplet
$client->droplet()->remove($droplet->id);
Tagging Resources:
$client->droplet()->addTags($droplet->id, ['env:production', 'team:backend']);
$client->droplet()->removeTags($droplet->id, ['env:staging']);
Managed Databases:
// Create a PostgreSQL cluster
$cluster = $client->database()->createCluster(
'my-postgres-cluster',
'pg',
'db-s-1vcpu-1gb',
'nyc3',
1
);
// Create a database user
$user = $client->database()->createUser(
$cluster->id,
'app_user',
'mysql_native_password'
);
Replicas and Backups:
// Create a replica
$replica = $client->database()->createReplica(
$cluster->id,
'replica-db',
'db-s-1vcpu-1gb'
);
// Trigger a backup
$client->database()->createBackup($cluster->id);
Deployments:
// Trigger a deployment
$deployment = $client->app()->createAppDeployment('app-123');
// Stream logs
$logs = $client->app()->getAggregateDeploymentLogs('app-123', $deployment->id);
Configuration:
// Update app specs
$client->app()->update('app-123', [
'services' => [
[
'name' => 'web',
'instance_count' => 3,
]
]
]);
$endpoint = $client->cdnEndpoint()->create([
'origin' => 'my-bucket.nyc3.digitaloceanspaces.com',
'ttl' => 3600,
'certificate_id' => 'cert-123'
]);
Service Provider Binding:
// In AppServiceProvider
$this->app->singleton(DigitalOceanV2\Client::class, function ($app) {
$client = new DigitalOceanV2\Client();
$client->authenticate(config('services.digitalocean.token'));
return $client;
});
Artisan Commands:
use Illuminate\Console\Command;
use DigitalOceanV2\Client;
class DropletListCommand extends Command
{
protected $client;
public function __construct(Client $client)
{
parent::__construct();
$this->client = $client;
}
public function handle()
{
$droplets = $this->client->droplet()->getAll();
$this->table(['ID', 'Name', 'Region'], $droplets);
}
}
Jobs/Queues:
use DigitalOceanV2\Client;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class CreateDropletJob implements ShouldQueue
{
use Queueable;
public function handle(Client $client)
{
$client->droplet()->create([
'name' => 'scheduled-droplet',
'region' => 'sfo3',
'size' => 's-1vcpu-1gb',
]);
}
}
HTTP Errors:
try {
$client->droplet()->remove('invalid-id');
} catch (DigitalOceanV2\Exception\ApiErrorException $e) {
Log::error('Droplet deletion failed: ' . $e->getMessage());
}
Rate Limiting:
try {
$client->account()->getUserInformation();
} catch (DigitalOceanV2\Exception\RateLimitException $e) {
sleep($e->getRetryAfter());
retry();
}
Authentication:
.env or a secrets manager.read/write for droplets).Pagination:
fetchAll() loads all records into memory. Use fetchAllLazy() for large datasets:
foreach ($client->droplet()->getAllLazy() as $droplet) {
// Process one by one
}
Idempotency:
idempotency_key to avoid duplicate charges:
$client->droplet()->create([
'name' => 'unique-droplet',
'region' => 'nyc3',
'idempotency_key' => 'abc123'
]);
Region-Specific Features:
nyc3).Deprecations:
getAllDroplets()) are deprecated. Use $client->droplet()->getAll() instead.Enable Debugging:
$client = new Client();
$client->setDebug(true); // Logs HTTP requests/responses
Inspect Raw Responses:
$response = $client->droplet()->getById('123');
$rawBody = $response->getRawBody(); // Raw JSON response
Common Issues:
Custom HTTP Clients: Override the default Guzzle client for retries or middleware:
use DigitalOceanV2\Http\Client\ClientInterface;
use DigitalOceanV2\Http\Client\GuzzleClient;
$httpClient = new GuzzleClient([
'timeout' => 30,
'headers' => ['User-Agent' => 'MyApp/1.0']
]);
$client = new DigitalOceanV2\Client($httpClient);
Event Listeners: Use Laravel’s events to react to API changes:
// Example: Log droplet creation
$client->droplet()->create([...])->then(function ($droplet) {
Log::info("Droplet created: {$droplet->id}");
});
Mocking for Tests:
use DigitalOceanV2\Client;
use DigitalOceanV2\Exception\ApiErrorException;
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('droplet')
->andReturnSelf()
->shouldReceive('getAll')
->andThrow(new ApiErrorException('Mock error', 404));
How can I help you explore Laravel packages today?