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

Contracts Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package:

    composer require symfony/contracts
    

    This installs all domain-specific contracts (e.g., cache, event-dispatcher, translation).

  2. Identify your first use case:

    • Need caching? Use Symfony\Contracts\Cache\CacheInterface.
    • Need events? Use Symfony\Contracts\EventDispatcher\EventDispatcherInterface.
    • Need translation? Use Symfony\Contracts\Translation\TranslatorInterface.
  3. Install a compatible implementation:

    composer require symfony/cache  # For caching
    composer require symfony/event-dispatcher  # For events
    
  4. 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);
        });
    }
    
  5. Type-hint the contract in your service:

    use Symfony\Contracts\Cache\CacheInterface;
    
    class MyService
    {
        public function __construct(private CacheInterface $cache) {}
    }
    

Implementation Patterns

1. Infrastructure Layer Abstraction

Use contracts for framework-agnostic infrastructure services (cache, events, mailers, etc.). Example: Replace Illuminate\Cache\Repository with CacheInterface in non-Laravel-bound services.

2. Laravel Service Binding

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
);

3. Framework-Agnostic Packages

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) {}
}

4. Leveraging Laravel’s Built-in Contracts

Laravel already uses some Symfony contracts under the hood (e.g., Mailer uses Symfony\Contracts\Mailer\MailerInterface). Extend this pattern for custom services.

5. Event-Driven Architecture

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());
    }
}

6. Translation and Localization

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');
    }
}

Gotchas and Tips

1. No Runtime Code

  • symfony/contracts is only interfaces and traits. No configuration, no commands, no database migrations.
  • Fix: Install a concrete implementation (e.g., symfony/cache) to get runtime behavior.

2. Package Granularity

  • Avoid installing the entire symfony/contracts meta-package if you only need specific contracts.
  • Fix: Install only what you need:
    composer require symfony/cache-contracts
    composer require symfony/event-dispatcher-contracts
    

3. PSR ≠ Symfony Contracts

  • Symfony contracts often extend PSR interfaces (e.g., CacheInterface extends Psr\SimpleCache\CacheInterface) but add extra methods or semantics.
  • Fix: Always check docblocks for differences. Example:
    // PSR-16 (SimpleCache) lacks retry logic, but Symfony's CacheInterface may include it.
    

4. Laravel Autowiring Quirks

  • Laravel won’t autowire Symfony contracts unless explicitly bound.
  • Fix: Use bind() or alias() in AppServiceProvider:
    $this->app->bind(
        Symfony\Contracts\Cache\CacheInterface::class,
        Illuminate\Cache\Repository::class
    );
    

5. Avoid Leaking Contracts into Domain Models

  • Use contracts only at infrastructure boundaries (repositories, APIs, event listeners).
  • Fix: Keep domain models pure. Example:
    // ❌ Avoid in domain models
    class User { public function __construct(private CacheInterface $cache) {} }
    
    // ✅ Correct (infrastructure layer)
    class UserRepository { public function __construct(private CacheInterface $cache) {} }
    

6. Debugging Missing Implementations

  • If you get Target class does not exist for a contract, verify:
    • The contract package is installed (composer why symfony/cache-contracts).
    • A concrete implementation is bound (composer why-not symfony/cache).
    • No version conflicts exist (e.g., symfony/cache 6.x vs. symfony/contracts 3.x).

7. Version Pinning

  • Symfony contracts and implementations must be version-compatible.
  • Fix: Pin versions in composer.json:
    "require": {
        "symfony/contracts": "^3.0",
        "symfony/cache": "^6.0"
    }
    

8. Testing with Mocks

  • Use 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);
    

9. Performance Considerations

  • Symfony contracts are lightweight, but performance depends on the concrete implementation.
  • Tip: Benchmark implementations (e.g., symfony/cache with Redis vs. file cache).

10. Extending Contracts

  • Need a custom contract? Extend an existing one or create a new interface in your project.
  • Example:
    namespace App\Contracts;
    
    use Symfony\Contracts\Cache\CacheInterface;
    
    interface ExtendedCacheInterface extends CacheInterface
    {
        public function getWithRetry(string $key, int $retries = 3);
    }
    
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai