openclassrooms/service-proxy
A lightweight Laravel/PHP service proxy from OpenClassrooms that sits between your application and its services, centralizing calls behind a clean, testable interface so business logic stays decoupled from transport details. Useful for wrapping external APIs or internal service layers.
composer require openclassrooms/service-proxy. There is no indication of a Laravel service provider with auto-discovery; check vendor/openclassrooms/service-proxy/composer.json for extra.laravel.providers and register manually in config/app.php (or bootstrap/providers.php on Laravel 11+) if one exists."openclassrooms/service-proxy": "11.0.*" (or an exact version) and read the diff between v10.0.1 and v11.0.0 before adopting.src/ first, not the README. With zero stars and few dependents, documentation is thin. The authoritative contract is the public classes in src/: the base ServiceProxy/AbstractServiceProxy, the generator/factory that turns a class-string into a proxy, and any Contracts/ folder. The docblock reader lives in the generator — that is the code the v11 change touched, so start there.@param/@return/@method/@property), not a hand-written decorator. Check whether the constructor takes an instance (decorator) or a class-string/closure (generated lazy proxy); the parser migration only matters in the generated case.// app/Services/Billing/StripeGateway.php (implements BillingGateway)
final class StripeGateway implements BillingGateway { /* vendor calls */ }
// app/Services/Billing/BillingGatewayProxy.php
class BillingGatewayProxy extends ServiceProxy implements BillingGateway
{
public function charge(int $cents): Receipt
{
return $this->proxy()->charge($cents); // delegate + intercept
}
}
Bind it in a service provider:
$this->app->bind(BillingGateway::class, fn ($app) =>
new BillingGatewayProxy($app->make(StripeGateway::class))
);
Mailer, Search, Storage), several concrete implementations, a proxy that selects or falls back between them. Good for migrating from a legacy provider behind a feature flag.new Proxy(...) inside a domain object. Bind once in a service provider so it is swappable and config:cache works.chore: label. A major version bump for a dependency migration means consumers must treat it as potentially breaking. Concrete risks: docblocks that were previously tolerated may now throw or be ignored; exotic types (generics, conditional types, array{...} shapes, @method/@property annotations) may render differently in generated signatures. Regenerate every proxy and diff before shipping.phpstan/phpdoc-parser constraint. If v11 pulls phpstan/phpdoc-parser ^2 (the likely v1→v2 migration), it can conflict with anything in your app still requiring ^1 — Larastan/PHPStan at older majors, Psalm plugins, other codegen tools. Resolve with composer why phpstan/phpdoc-parser before blaming the library, and be ready to bump your static-analysis stack in the same PR.final classes or methods is a hard blocker for generated proxies. Code generation cannot subclass final, override final methods, or proxy private methods. Verify wrapped services are non-final, or use decorator mode.self/static return types, by-ref parameters, variadics, and union types. Smoke-test every proxied method returning static or taking &$ref — especially after a major, since the parser produces the type text.ProxyManagerGeneratedProxy\...) as the failing frame. Unwrap with getWrappedValue() / getWrappedInstance() if exposed, otherwise filter debug_backtrace().config:cache and generated proxies don't always mix. If proxies are generated on first use and cached to disk, warm them during build/deploy, add the cache directory to .gitignore, and clear it (php artisan optimize:clear plus the library's cache path) after every upgrade — v11 in particular. Stale generated code from v10 is the most likely cause of "it worked locally but breaks in CI".src/ — that is where auth headers and correlation IDs belong, rather than copy-pasted delegation methods.v10.0.1...v11.0.0) before upgrading, and upgrade on your schedule rather than via composer update.How can I help you explore Laravel packages today?