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

Ovh Bundle Laravel Package

tilleuls/ovh-bundle

Symfony bundle integrating the OVH API SDK, providing configured services and dependency injection for calling OVH endpoints from PHP applications. Simplifies API client setup and authentication within Symfony.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: tilleuls/ovh-bundle is a Symfony bundle, not a Laravel package. It has no service provider, no facade, and its composer.json targets Symfony 3/4/5 and PHP 7.x (last release 2020-08-11). For a Laravel app the practical move is to consume the underlying SDK — ovh/ovh — and copy the bundle's configuration shape. The bundle itself is worth reading as documentation, not installing.

Where to look first in the repo:

  1. DependencyInjection/Configuration.php — shows the actual knobs: endpoint_name, application_key, application_secret, consumer_key.
  2. Resources/config/services.xml — shows there is essentially one useful object: a configured Ovh\Api instance.
  3. CoopTilleulsOvhBundle.php — trivial; nothing else is hooked.

Minimal steps in Laravel:

composer require ovh/ovh
php artisan make:provider OvhServiceProvider

config/ovh.php:

return [
    'endpoint'           => env('OVH_ENDPOINT', 'ovh-eu'),
    'application_key'    => env('OVH_APPLICATION_KEY'),
    'application_secret' => env('OVH_APPLICATION_SECRET'),
    'consumer_key'       => env('OVH_CONSUMER_KEY'),
];

app/Providers/OvhServiceProvider.php:

public function register(): void
{
    $this->app->singleton(\Ovh\Api::class, function ($app) {
        $c = $app['config']->get('ovh');

        return new \Ovh\Api(
            $c['application_key'],
            $c['application_secret'],
            $c['endpoint'],          // ovh-eu | ovh-ca | kimsufi-eu | soyoustart-eu
            $c['consumer_key']
        );
    });
}

First use case: verify credentials, then a real read.

$ovh = app(\Ovh\Api::class);
$me  = $ovh->get('/me');                       // sanity check
$rec = $ovh->get('/domain/zone/example.com/record'); // list DNS records

Implementation Patterns

Wrap the SDK behind your own class. This is the single most valuable pattern. Symfony users inject Ovh\Api directly; that's fine there, but in Laravel you want an interface for testing and for adding retries/logging.

interface OvhClient
{
    public function me(): array;
    public function dnsRecords(string $zone): array;
    public function createDnsRecord(string $zone, array $payload): array;
}

final class SdkOvhClient implements OvhClient
{
    public function __construct(private \Ovh\Api $api) {}

    public function me(): array { return $this->api->get('/me'); }

    public function dnsRecords(string $zone): array
    {
        return $this->api->get("/domain/zone/{$zone}/record");
    }

    public function createDnsRecord(string $zone, array $payload): array
    {
        return $this->api->post("/domain/zone/{$zone}/record", $payload);
    }
}

Bind OvhClient to SdkOvhClient in the provider, and inject OvhClient everywhere.

Credential bootstrap as an artisan command. OVH requires a consumer key obtained via a token request:

$ovh = new \Ovh\Api($appKey, $appSecret, 'ovh-eu');
$access = $ovh->requestCredentials([
    ['method' => 'GET',  'path' => '/domain/zone/*'],
    ['method' => 'POST', 'path' => '/domain/zone/*'],
], 'https://your-app.test/ovh/callback');
// $access['consumerKey'], $access['validationUrl']

Ship this as php artisan ovh:request-token and store the returned consumerKey out-of-band. Never build it at request time.

One client per account/tenant. The bundle assumes a single configuration tree, so multi-tenant OVH usage is awkward under it. In Laravel, register a factory and cache clients by tenant:

class OvhClientFactory
{
    protected array $clients = [];

    public function for(string $tenant): \Ovh\Api
    {
        return $this->clients[$tenant] ??= new \Ovh\Api(
            config("tenants.$tenant.ovh.app_key"),
            config("tenants.$tenant.ovh.app_secret"),
            config("tenants.$tenant.ovh.endpoint"),
            config("tenants.$tenant.ovh.consumer_key"),
        );
    }
}

Queue the writes. OVH calls (orders, DNS updates, email migrations) are slow and rate-limited. Put them in jobs and use ->timeout(60); the default Guzzle client in the SDK has no per-request timeout until you supply one.

Inject a Guzzle client when you need observability. Ovh\Api accepts a ClientInterface as one of its trailing constructor args (verify against your installed version). Use it to add logging middleware and a sane connect_timeout/timeout.

Gotchas and Tips

  • Don't try to install the bundle on a modern app. Its constraints will fail under PHP 8.1+ / Symfony 6/7. Use ovh/ovh directly; the bundle contributes zero runtime behaviour beyond wiring an Ovh\Api service and a coop_tilleuls_ovh config tree.
  • Clock skew breaks signing. Every request is timestamped and signed locally. If your server drifts, you get Invalid signature or Timestamp expired. The SDK caches the OVH server time, so drift after boot still bites. Run chrony/ntpd on the host.
  • Consumer keys are scoped, not global. A key minted for /domain/zone/* cannot call /me or /email/*. Mint narrow keys per feature and per tenant; keep them in .env or a secret manager, never in a config file tracked by git (the bundle's YAML config is easy to leak).
  • config:cache freezes credentials. Since config/ovh.php reads env(), changing .env requires php artisan config:clear. Rotating keys without redeploying cache is a common self-inflicted 403.
  • Exception types matter. Catch \Ovh\Exceptions\NotCredentialException (bad/missing key), \Ovh\Exceptions\InvalidParameterException (malformed payload — 400, no retry), \Ovh\Exceptions\ApiException (everything else; inspect getResponse() for body and status). Don't blanket-catch \Throwable and retry — OVH POSTs like POST /order/* are not idempotent.
  • Rate limits punish retries. OVH throttles per-endpoint. Retry with exponential backoff only on 5xx and on 429; do not retry order creation without an idempotency strategy (OVH exposes X-Ovh-* headers but no generic idempotency key).
  • No mocking layer exists. Ovh\Api is a concrete class with no interface, and the bundle does not ship fakes. Bind OvhClient to a fake in tests; never bind a mock \Ovh\Api unless you're prepared to stub all the constructor side effects.
  • Debug against the API console first. https://eu.api.ovh.com/console (or ca.api.ovh.com) lets you replay calls with the same credentials and paths. Confirm the call works there before blaming your code.
  • Extension points that exist in the bundle (if you do load it in a legacy Symfony app): the coop_tilleuls_ovh configuration section, and the OVH service definition in Resources/config/services.xml — which you can override via a compiler pass or by aliasing Ovh\Api in your own services.yaml. There is no event dispatching, no named-client support, and no factory — anything beyond one account means writing your own wiring regardless.
  • Endpoint strings are not URLs. ovh-eu, ovh-ca, kimsufi-eu, soyoustart-eu (and their -ca variants) are the recognised values. Passing an URL or a bare eu silently produces confusing 4xx errors.
  • Response shapes are raw arrays. The SDK does not hydrate DTOs. /domain/zone/{zone}/record returns arrays with id, fieldType, subDomain, target, ttl. Normalise to DTOs in your wrapper so your app isn't coupled to OVH's JSON.
  • Apply changes after writes. DNS record POSTs create records but do not publish them — you must call POST /domain/zone/{zone}/refresh (and POST .../refresh on the zone after deletes) for changes to go live. This trips up nearly every first integration, and the bundle gives no hint that it's needed.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package