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

Service Contracts Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Pros:
    • Laravel’s native container (Illuminate\Container) implements Psr\Container\ContainerInterface, ensuring compatibility with ServiceLocator and ServiceSubscriberInterface.
    • Aligns with Laravel’s DI philosophy (PSR-11) while enabling Symfony interoperability for cross-framework libraries.
    • Enables modular architecture by standardizing service contracts, reducing coupling between components.
    • Battle-tested abstractions (e.g., ServiceSubscriberInterface) reduce custom interface development and technical debt.
  • Cons:
    • Limited core Laravel integration: Symfony-specific contracts (e.g., ServiceSubscriberInterface) require manual adaptation since Laravel lacks native support for auto-registration or ServiceSubscriberTrait.
    • No runtime implementations: Pure interfaces mean no "out-of-the-box" services—requires custom implementation or third-party integrations (e.g., Symfony Messenger).
    • Overhead for simple apps: Adds complexity for projects without DI-heavy workflows (e.g., CLI scripts, lightweight APIs).

Integration Feasibility

  • Low-friction adoption: Composer install + minimal configuration (no Laravel service provider needed).
  • Key dependencies:
    • PSR-11 compliance: Laravel’s container meets this, but custom container extensions (e.g., legacy or monolithic DI) may need validation.
    • PHP 8.1+: Required for modern Symfony contracts (e.g., Attribute support in newer versions).
  • Gaps:
    • ServiceSubscriberInterface: Laravel lacks auto-wiring for subscribers; requires manual binding or trait implementation.
    • Symfony-specific integrations: E.g., Messenger or DependencyInjection components may need adapters for full feature parity.

Technical Risk

  • Medium risk for greenfield projects; high risk for legacy systems.
    • Breaking changes: Symfony contracts evolve slowly, but Laravel’s DI may not align with future updates (e.g., ServiceSubscriberTrait enhancements).
    • Testing complexity: Mocking ServiceLocator in unit tests requires careful setup to avoid container leaks.
    • Performance: Lazy-loading via ServiceLocator can introduce overhead if overused for frequently accessed services.
  • Mitigations:
    • Adopt incrementally: Start with ServiceLocator for optional dependencies (e.g., third-party APIs) before full architecture adoption.
    • Wrapper classes: Create Laravel-specific adapters for Symfony contracts (e.g., LaravelServiceSubscriber trait).
    • CI validation: Test compatibility with Laravel’s container in CI pipelines (e.g., phpunit/phpunit + phpstan/extension-installer).

Key Questions

  1. Use Case Clarity:
    • Is this for cross-framework libraries (low risk) or core Laravel services (higher risk)?
    • Will we need Symfony-specific features (e.g., Messenger integration) or just PSR-11 compliance?
  2. Team Alignment:
    • Does the team have experience with Symfony’s DI or PSR-11 containers? If not, budget for ramp-up.
    • Are stakeholders aware of the no-runtime-implementation limitation?
  3. Long-Term Strategy:
    • How does this fit with Laravel’s roadmap (e.g., Laravel 11’s DI improvements)?
    • Will we maintain custom adapters for Symfony contracts, or push for upstream Laravel integration?
  4. Alternatives:
    • Could PSR-15 (HTTP Server Request Handlers) or Laravel’s native ServiceProvider binding suffice for our needs?
    • Is there a Laravel-first package (e.g., spatie/laravel-service-contracts) that reduces Symfony dependency?

Integration Approach

Stack Fit

  • Primary Fit:
    • Laravel + Symfony interoperability: Ideal for projects using both frameworks (e.g., shared domain libraries).
    • Framework-agnostic libraries: Enables reusable services (e.g., payment processors, notification handlers) that work in Laravel, Symfony, or custom PHP apps.
    • Testability: Simplifies mocking services in unit/integration tests via ServiceLocator.
  • Secondary Fit:
    • Enterprise Laravel apps: Useful for strict separation of concerns (e.g., domain-driven design layers).
    • Legacy system modernization: Gradually introduce contracts to decouple monolithic services.
  • Non-Fit:
    • Trivial applications: Overkill for scripts or APIs with minimal DI needs.
    • Legacy PHP (<8.1): Missing modern features (e.g., Attribute support in newer contracts).

Migration Path

  1. Phase 1: Proof of Concept (1–2 weeks)

    • Install the package and implement ServiceLocator for one optional dependency (e.g., a third-party API client).
    • Example:
      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(...);
          }
      }
      
    • Goal: Validate PSR-11 compatibility and performance impact.
  2. Phase 2: Core Integration (2–4 weeks)

    • Replace constructor injection with ServiceSubscriberInterface for non-critical services (e.g., background jobs, commands).
    • Create a custom trait to bridge Laravel’s container with Symfony contracts:
      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);
                  }
              };
          }
      }
      
    • Goal: Standardize service resolution across the app.
  3. Phase 3: Full Adoption (4–8 weeks)

    • Migrate domain-specific services (e.g., UserService, OrderService) to use contracts.
    • Replace global helpers (e.g., app()->make()) with ServiceLocator where appropriate.
    • Optional: Integrate with Symfony components (e.g., Messenger) via adapters.
    • Goal: Achieve modular, testable architecture with minimal coupling.

Compatibility

  • Laravel Compatibility:
    • Container: Fully compatible with Psr\Container\ContainerInterface.
    • ⚠️ ServiceSubscriberInterface: Requires custom implementation (Laravel lacks auto-registration).
    • PHP 8.1+: Required for modern Symfony contracts (e.g., Attribute support).
  • Symfony Compatibility:
    • DependencyInjection: Works seamlessly with Symfony’s ServiceLocator.
    • ⚠️ Messenger/Console: May need adapters for full feature parity.
  • Third-Party Risks:
    • Package conflicts: Ensure no version skew with symfony/dependency-injection or symfony/messenger.
    • Legacy code: Avoid mixing with non-PSR-11 containers (e.g., old Illuminate\Foundation\Application extensions).

Sequencing

  1. Start with optional dependencies (low risk) before critical paths.
  2. Prioritize testability gains (e.g., mocking services in unit tests).
  3. Avoid mixing patterns: Don’t use ServiceLocator for high-frequency services (e.g., database connections).
  4. Document custom integrations: Clearly mark where Symfony contracts diverge from Laravel conventions.
  5. Phase out global helpers: Replace app()->make() with ServiceLocator where appropriate.

Operational Impact

Maintenance

  • Pros:
    • Reduced technical debt: Standardized contracts eliminate custom interface sprawl.
    • Easier refactoring: Decoupled services simplify dependency changes.
    • Symfony alignment: Future-proofs against ecosystem shifts (e.g., PSR-15, PSR-16).
  • Cons:
    • Additional abstractions: Requires maintaining custom adapters (e.g., LaravelServiceSubscriber trait).
    • Dependency updates: Must align with Symfony’s contract releases (e.g., symfony/contracts).
    • Debugging complexity: Lazy-loaded services via ServiceLocator may obscure dependency chains.

Support

  • Pros:
    • Community backing: 2,600+ stars and MIT license reduce vendor lock-in risk.
    • Symfony ecosystem: Leverages battle-tested patterns (e.g., ServiceSubscriberInterface).
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