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

Technical Evaluation

Architecture fit Symfony Contracts excels in Laravel applications targeting decoupled infrastructure layers (caching, events, messaging, etc.). The package’s domain-specific interfaces (e.g., CacheInterface, EventDispatcherInterface) align with Laravel’s service container and dependency injection patterns, enabling loose coupling between business logic and framework-specific implementations. For example, replacing Illuminate\Cache\Repository with Symfony\Contracts\Cache\CacheInterface in a service layer allows seamless swapping of cache backends (e.g., Redis, Memcached) without modifying domain logic. However, core Laravel abstractions (e.g., Eloquent, Blade) lack direct contract support, limiting applicability to infrastructure-heavy components.

Integration feasibility Moderate-to-high for new projects or greenfield services, but challenging for legacy Laravel codebases. Key hurdles:

  • No native Laravel implementation: Laravel’s built-in services (e.g., CacheManager) do not implement Symfony Contracts, requiring explicit bindings or adapter classes.
  • Version alignment: Symfony Contracts v3.x requires PHP 8.1+, while Laravel 9.x/10.x may need backward-compatible shims (e.g., symfony/cache-contracts:^2.5 for older PHP).
  • Autowiring limitations: Laravel’s autowiring resolves concrete classes but not interfaces by default—manual bindings (via AppServiceProvider) are mandatory for seamless adoption.

Technical risk

  1. Semantic mismatches: Concrete implementations (e.g., symfony/cache) may deviate from Laravel’s behavior (e.g., cache tagging, event propagation). Validate via reference tests in the symfony/contracts suite.
  2. Dependency bloat: Installing symfony/contracts pulls in all domain contracts, even if only 1–2 are needed (e.g., cache-contracts). Use granular packages (e.g., symfony/event-dispatcher-contracts) to minimize footprint.
  3. Runtime resolution failures: Missing or misconfigured bindings cause Target class does not exist errors. Mitigate with comprehensive alias() mappings in AppServiceProvider.
  4. Testing complexity: Mocking Symfony Contracts requires interface-specific stubs, increasing test setup time compared to Laravel’s concrete facades.

Key questions

  1. Which contracts are critical? Prioritize domains (e.g., CacheInterface, MailerInterface) where Laravel’s native implementations are suboptimal or non-standard.
  2. Will we use Symfony components or third-party implementations? E.g., symfony/mailer vs. spatie/laravel-mail—each may have partial contract compliance.
  3. How will we handle legacy code? Plan for gradual migration via adapter patterns (e.g., wrap CacheManager in a CacheInterface adapter).
  4. What’s the fallback for unsupported contracts? E.g., Laravel lacks a MessengerInterface—will we build one or avoid queueing abstractions?
  5. Who owns contract compliance? Assign a technical owner to validate implementations against Symfony’s reference tests.

Integration Approach

Stack fit Ideal for:

  • Infrastructure services: Cache, event dispatchers, mailers, HTTP clients.
  • Cross-framework libraries: Reusable packages (e.g., payment processors) that must work in Laravel/Symfony.
  • Microservices: Decouple Laravel services from framework-specific dependencies.

Poor fit for:

  • Domain models: Avoid injecting contracts into Eloquent models or value objects.
  • Framework-specific features: Blade directives, queue jobs (unless using Symfony\Contracts\Messenger), or Laravel’s auth system.

Migration path

  1. Assess scope:
    • Identify non-critical services (e.g., logging, caching) for pilot adoption.
    • Map Laravel’s concrete classes to Symfony Contracts (e.g., CacheManagerCacheInterface).
  2. Install dependencies:
    composer require symfony/contracts symfony/cache-contracts symfony/event-dispatcher-contracts
    
    • Use granular packages (e.g., symfony/cache-contracts) to avoid bloat.
  3. Bind contracts to Laravel implementations:
    // app/Providers/AppServiceProvider.php
    public function register(): void
    {
        $this->app->bind(
            Symfony\Contracts\Cache\CacheInterface::class,
            fn($app) => $app->make(Illuminate\Cache\Repository::class)
        );
        $this->app->bind(
            Symfony\Contracts\EventDispatcher\EventDispatcherInterface::class,
            Illuminate\Events\Dispatcher::class
        );
    }
    
  4. Refactor services:
    • Replace type hints:
      // Before
      public function __construct(CacheManager $cache) {}
      
      // After
      public function __construct(Symfony\Contracts\Cache\CacheInterface $cache) {}
      
    • Use constructor injection for new services; avoid facades (e.g., Cache::store()) to preserve decoupling.
  5. Validate implementations:
    • Test edge cases (e.g., cache invalidation, event propagation) to ensure semantic parity with Laravel’s behavior.
    • For missing contracts (e.g., MessengerInterface), build adapter wrappers around Laravel’s queue system.

Compatibility

  • Laravel 10+: Best compatibility with Symfony Contracts v3.x (PHP 8.1+).
  • Laravel 9.x: Use Symfony Contracts v2.5+ with PHP 8.0 compatibility flags.
  • Laravel 8.x: Requires backward-compatible shims or manual polyfills for PHP 7.4.
  • Third-party libraries: Prefer libraries that declare contracts in composer.json (e.g., "provide": { "symfony/cache-implementation": "1.0" }).

Sequencing

  1. Phase 1 (Low Risk): Replace cache and event dispatchers in new services.
  2. Phase 2 (Medium Risk): Migrate legacy services via adapter patterns.
  3. Phase 3 (High Risk): Adopt contracts in core framework interactions (e.g., mailers, HTTP clients).
  4. Phase 4 (Optional): Build framework-agnostic packages using only Symfony Contracts.

Critical dependencies:

  • Ensure concrete implementations (e.g., symfony/cache) are version-locked to avoid contract-breaking updates.
  • Monitor Symfony’s deprecations for contract changes.

Operational Impact

Maintenance

  • Low: Symfony Contracts are stable interfaces with minimal breaking changes (e.g., v2 → v3 added CacheInterface methods).
  • High: Concrete implementations (e.g., symfony/cache) require active version management to avoid compatibility issues.
    • Example: Upgrading symfony/cache from v6.x to v7.x may require contract adapter updates.
  • Tooling: Use composer why symfony/* to audit dependencies and roave/security-advisories to monitor vulnerabilities.

Support

  • Community-driven: Leverage Symfony’s Slack and Laravel’s Forums for contract-specific issues.
  • No official Laravel support: Contract bridging is a community effort; document custom bindings and adapters in your team’s wiki.
  • Debugging: Use php artisan container:inspect to verify bindings and dd($cache instanceof Symfony\Contracts\Cache\CacheInterface) to validate runtime compliance.

Scaling

  • No impact at the contract layer: Interfaces are zero-cost abstractions.
  • Performance depends on implementations:
    • Example: symfony/cache with Redis vs. file-based cache will have dramatically different latency.
    • Benchmark concrete implementations before production adoption.
  • Horizontal scaling: Contracts enable implementation swaps (e.g., switch from Illuminate\Cache to Predis for Redis) without code changes.

Failure modes

  1. Binding errors:
    • Symptom: Target class [Symfony\Contracts\Cache\CacheInterface] does not exist.
    • Root cause: Missing alias() or bind() in AppServiceProvider.
    • Fix: Verify bindings with php artisan container:inspect.
  2. Semantic mismatches:
    • Symptom: Cache invalidation fails silently or events are not dispatched.
    • Root cause: Laravel’s implementation deviates from Symfony’s contract semantics (e.g., tag-based invalidation).
    • Fix: Write contract-specific tests against reference implementations.
  3. Version conflicts:
    • Symptom: Class not found or Method not found after dependency updates.
    • Root cause: Symfony Contracts v3.x requires PHP 8.1+, but Laravel 9.x uses PHP 8.0.
    • Fix: Pin versions in `composer
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