symfony/contracts
Symfony Contracts provides small, stable PHP interfaces and traits extracted from Symfony components. Use them as type hints for loose coupling and interoperability, with proven implementations and backward compatibility across the Symfony ecosystem.
Install the package:
composer require symfony/contracts
This installs all domain-specific contracts (e.g., cache, event-dispatcher, translation).
Identify your first use case:
Symfony\Contracts\Cache\CacheInterface.Symfony\Contracts\EventDispatcher\EventDispatcherInterface.Symfony\Contracts\Translation\TranslatorInterface.Install a compatible implementation:
composer require symfony/cache # For caching
composer require symfony/event-dispatcher # For events
Bind the contract to Laravel’s implementation (in AppServiceProvider):
use Symfony\Contracts\Cache\CacheInterface;
use Illuminate\Cache\Repository;
public function register()
{
$this->app->bind(CacheInterface::class, function ($app) {
return $app->make(Repository::class);
});
}
Type-hint the contract in your service:
use Symfony\Contracts\Cache\CacheInterface;
class MyService
{
public function __construct(private CacheInterface $cache) {}
}
Use contracts for framework-agnostic infrastructure services (cache, events, mailers, etc.).
Example: Replace Illuminate\Cache\Repository with CacheInterface in non-Laravel-bound services.
Map Symfony contracts to Laravel’s concrete implementations via bind() or alias():
// In AppServiceProvider
$this->app->alias(
Symfony\Contracts\Cache\CacheInterface::class,
Illuminate\Cache\Repository::class
);
Build reusable libraries that depend only on symfony/contracts. Consumers can then inject their own implementations (Symfony, Laravel, Doctrine, etc.).
Example:
// In a reusable package
use Symfony\Contracts\Cache\CacheInterface;
class PaymentProcessor
{
public function __construct(private CacheInterface $cache) {}
}
Laravel already uses some Symfony contracts under the hood (e.g., Mailer uses Symfony\Contracts\Mailer\MailerInterface). Extend this pattern for custom services.
Use Symfony\Contracts\EventDispatcher\EventDispatcherInterface for decoupled event handling:
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class OrderService
{
public function __construct(private EventDispatcherInterface $dispatcher) {}
public function placeOrder(): void
{
$this->dispatcher->dispatch(new OrderPlacedEvent());
}
}
Use Symfony\Contracts\Translation\TranslatorInterface for multi-language support:
use Symfony\Contracts\Translation\TranslatorInterface;
class LocalizedService
{
public function __construct(private TranslatorInterface $translator) {}
public function greet(): string
{
return $this->translator->trans('welcome');
}
}
symfony/contracts is only interfaces and traits. No configuration, no commands, no database migrations.symfony/cache) to get runtime behavior.symfony/contracts meta-package if you only need specific contracts.composer require symfony/cache-contracts
composer require symfony/event-dispatcher-contracts
CacheInterface extends Psr\SimpleCache\CacheInterface) but add extra methods or semantics.// PSR-16 (SimpleCache) lacks retry logic, but Symfony's CacheInterface may include it.
bind() or alias() in AppServiceProvider:
$this->app->bind(
Symfony\Contracts\Cache\CacheInterface::class,
Illuminate\Cache\Repository::class
);
// ❌ Avoid in domain models
class User { public function __construct(private CacheInterface $cache) {} }
// ✅ Correct (infrastructure layer)
class UserRepository { public function __construct(private CacheInterface $cache) {} }
Target class does not exist for a contract, verify:
composer why symfony/cache-contracts).composer why-not symfony/cache).symfony/cache 6.x vs. symfony/contracts 3.x).composer.json:
"require": {
"symfony/contracts": "^3.0",
"symfony/cache": "^6.0"
}
symfony/contracts for easy mocking in tests:
use Symfony\Contracts\Cache\CacheInterface;
$mockCache = $this->createMock(CacheInterface::class);
$mockCache->method('get')->willReturn('cached_value');
$service = new MyService($mockCache);
symfony/cache with Redis vs. file cache).namespace App\Contracts;
use Symfony\Contracts\Cache\CacheInterface;
interface ExtendedCacheInterface extends CacheInterface
{
public function getWithRetry(string $key, int $retries = 3);
}
How can I help you explore Laravel packages today?