symfony/service-contracts
Symfony Service Contracts provides lightweight, battle-tested abstractions extracted from Symfony components. Use these shared interfaces to build interoperable libraries and apps with proven semantics and consistent behavior across the Symfony ecosystem.
Illuminate\Container) implements Psr\Container\ContainerInterface, ensuring compatibility with ServiceLocator and ServiceSubscriberInterface.ServiceSubscriberInterface) reduce custom interface development and technical debt.ServiceSubscriberInterface) require manual adaptation since Laravel lacks native support for auto-registration or ServiceSubscriberTrait.Attribute support in newer versions).Messenger or DependencyInjection components may need adapters for full feature parity.ServiceSubscriberTrait enhancements).ServiceLocator in unit tests requires careful setup to avoid container leaks.ServiceLocator can introduce overhead if overused for frequently accessed services.ServiceLocator for optional dependencies (e.g., third-party APIs) before full architecture adoption.LaravelServiceSubscriber trait).phpunit/phpunit + phpstan/extension-installer).Messenger integration) or just PSR-11 compliance?ServiceProvider binding suffice for our needs?spatie/laravel-service-contracts) that reduces Symfony dependency?ServiceLocator.Attribute support in newer contracts).Phase 1: Proof of Concept (1–2 weeks)
ServiceLocator for one optional dependency (e.g., a third-party API client).use Symfony\Contracts\Service\ServiceLocatorInterface;
class NotificationService implements ServiceSubscriberInterface
{
public static function getSubscribedServices(): array
{
return ['mailer' => MailerInterface::class];
}
public function __construct(private ServiceLocatorInterface $locator) {}
public function sendEmail(): void
{
$mailer = $this->locator->get('mailer');
$mailer->send(...);
}
}
Phase 2: Core Integration (2–4 weeks)
ServiceSubscriberInterface for non-critical services (e.g., background jobs, commands).use Illuminate\Container\Container;
use Symfony\Contracts\Service\ServiceLocatorInterface;
trait LaravelServiceSubscriber
{
protected Container $container;
public function __construct(Container $container)
{
$this->container = $container;
}
protected function getLocator(): ServiceLocatorInterface
{
return new class($this->container) implements ServiceLocatorInterface {
public function __construct(private Container $container) {}
public function get(string $id)
{
return $this->container->make($id);
}
};
}
}
Phase 3: Full Adoption (4–8 weeks)
UserService, OrderService) to use contracts.app()->make()) with ServiceLocator where appropriate.Messenger) via adapters.Psr\Container\ContainerInterface.Attribute support).ServiceLocator.symfony/dependency-injection or symfony/messenger.Illuminate\Foundation\Application extensions).ServiceLocator for high-frequency services (e.g., database connections).app()->make() with ServiceLocator where appropriate.LaravelServiceSubscriber trait).symfony/contracts).ServiceLocator may obscure dependency chains.ServiceSubscriberInterface).How can I help you explore Laravel packages today?