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

Digital Ocean Bundle Laravel Package

dunglas/digital-ocean-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Bundle:

    composer require dunglas/digital-ocean-bundle symfony/http-client nyholm/psr7 guzzlehttp/promises
    

    For non-Flex projects, add the bundle to config/bundles.php:

    Dunglas\DigitalOceanBundle\DunglasDigitalOceanBundle::class => ['all' => true],
    
  2. Configure API Token: Add your DigitalOcean token to config/packages/dunglas_digital_ocean.yaml:

    dunglas_digital_ocean:
        token: "%env(DIGITAL_OCEAN_TOKEN)%"
    

    Or use the shorthand:

    dunglas_digital_ocean: "%env(DIGITAL_OCEAN_TOKEN)%"
    
  3. First Use Case: Inject the Client into a controller or service and interact with DigitalOcean resources:

    use DigitalOceanV2\Client;
    
    class DropletController {
        public function listDroplets(Client $client) {
            $droplets = $client->droplet()->getAll();
            // Process droplets...
        }
    }
    

Where to Look First


Implementation Patterns

Core Workflows

1. Resource Management (CRUD)

Use the Client to interact with DigitalOcean resources (droplets, databases, etc.):

// Create a droplet
$droplet = $client->droplet()->create([
    'name' => 'app-server',
    'region' => 'nyc3',
    'size' => 's-1vcpu-1gb',
    'image' => 'ubuntu-22-04-x64',
]);

// List droplets with pagination
$droplets = $client->droplet()->getAll();
foreach ($droplets as $droplet) {
    // Process each droplet
}

// Delete a droplet
$client->droplet()->delete($dropletId);

2. Multi-Connection Setup

Configure multiple connections in config/packages/dunglas_digital_ocean.yaml:

dunglas_digital_ocean:
    connections:
        primary:
            token: "%env(DO_PRIMARY_TOKEN)%"
        secondary:
            token: "%env(DO_SECONDARY_TOKEN)%"
    default_connection: primary

Inject specific clients via autowiring aliases:

use DigitalOceanV2\Client;

class MultiClientService {
    public function __construct(
        private Client $primaryClient,
        private Client $secondaryClient
    ) {}
}

3. Pagination with ResultPager

Handle large datasets efficiently:

use DigitalOceanV2\ResultPager;

$pager = new ResultPager($client);
$allDroplets = $pager->fetchAll($client->droplet(), 'getAll');

4. Async Operations with Messenger

Offload long-running tasks (e.g., droplet creation) to Symfony Messenger:

use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
public function handleCreateDroplet(CreateDropletMessage $message) {
    $client = $this->doClient;
    $client->droplet()->create($message->getConfig());
}

5. API Platform Integration

Expose DigitalOcean resources as REST endpoints:

# config/api_platform/resources.yaml
resources:
    App\Model\Droplet:
        collectionOperations:
            get: ~
        itemOperations:
            get: ~

Create a custom Droplet entity and hydrate it with data from the Client.


Integration Tips

1. Environment Variables

Store tokens in .env:

DIGITAL_OCEAN_TOKEN=your_token_here

Reference them in config:

dunglas_digital_ocean: "%env(DIGITAL_OCEAN_TOKEN)%"

2. Error Handling

Wrap API calls in try-catch blocks to handle DigitalOcean API errors:

try {
    $droplet = $client->droplet()->create($config);
} catch (\DigitalOceanV2\Exception\ApiException $e) {
    // Log or handle the error (e.g., retry or notify)
    $this->logger->error('Failed to create droplet: ' . $e->getMessage());
}

3. Caching Responses

Cache frequent API calls (e.g., listing droplets) using Symfony Cache:

use Symfony\Contracts\Cache\CacheInterface;

public function listDroplets(Client $client, CacheInterface $cache) {
    $cacheKey = 'droplets_list';
    $droplets = $cache->get($cacheKey, function() use ($client) {
        return $client->droplet()->getAll();
    });
}

4. Webhooks for Real-Time Events

Use Symfony’s HttpClient to listen to DigitalOcean webhooks:

use Symfony\Contracts\HttpClient\HttpClientInterface;

public function handleWebhook(HttpClientInterface $client, string $payload) {
    $data = json_decode($payload, true);
    // Process webhook event (e.g., droplet created/deleted)
}

5. Testing

Mock the Client in tests using PHPUnit:

use DigitalOceanV2\Client;

public function testListDroplets() {
    $mockClient = $this->createMock(Client::class);
    $mockClient->method('droplet')->willReturnSelf();
    $mockClient->method('getAll')->willReturn([/* mock data */]);

    $service = new MyService($mockClient);
    $result = $service->listDroplets();
    $this->assertEquals([/* expected */], $result);
}

Gotchas and Tips

Pitfalls

1. Rate Limiting

  • DigitalOcean enforces rate limits. Exceeding limits (e.g., 500 requests/minute for unauthenticated endpoints) will return 429 Too Many Requests.
  • Solution: Implement retries with exponential backoff using Symfony’s HttpClient:
    $client->withOptions([
        'timeout' => 30,
        'retries' => 3,
        'delay' => 1000, // 1 second delay between retries
    ]);
    

2. Token Expiry

  • API tokens can be revoked or expire. Always handle 401 Unauthorized errors gracefully.
  • Solution: Implement token rotation logic or notify admins when errors occur.

3. Pagination Quirks

  • The ResultPager is useful but may not handle all edge cases (e.g., malformed responses). Test with large datasets.
  • Solution: Add validation for paginated responses:
    $pager = new ResultPager($client);
    $allItems = $pager->fetchAll($resource, 'getAll');
    if (empty($allItems)) {
        throw new \RuntimeException('Failed to fetch all items');
    }
    

4. Deprecation Warnings

  • The underlying DigitalOceanPHP/Client library may evolve. Check for breaking changes in its changelog.
  • Solution: Monitor updates and test against new versions early.

5. Symfony Version Compatibility

  • The bundle supports Symfony 7+ (as of v1.2.1). Ensure your project’s Symfony version is compatible.
  • Solution: Pin the bundle version in composer.json if using an older Symfony version:
    "dunglas/digital-ocean-bundle": "^1.1.0"
    

6. CORS and Webhooks

  • If using webhooks, ensure your DigitalOcean app’s IP is whitelisted in your Symfony app’s firewall.
  • Solution: Configure Symfony’s HttpClient to verify SSL certificates and validate webhook signatures.

Debugging Tips

1. Enable Debug Logging

Configure Monolog to log DigitalOcean API requests/responses:

# config/packages/monolog.yaml
monolog:
    handlers:
        main:
            type: stream
            path: "%kernel.logs_dir%/%kernel.environment%.log"
            level: debug
            channels: ["
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.
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
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata