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

Laminas Servicemanager Laravel Package

laminas/laminas-servicemanager

Powerful dependency injection and service container for PHP. Manage factories, abstract factories, delegators, aliases, and shared services, with PSR-11 interoperability and robust configuration for complex applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require laminas/laminas-servicemanager
    

    Ensure friendsofphp/proxy-manager-lts is installed for lazy services:

    composer require friendsofphp/proxy-manager-lts
    
  2. Basic Setup: Create a ServiceManager instance with a minimal configuration:

    use Laminas\ServiceManager\ServiceManager;
    
    $serviceManager = new ServiceManager([
        'factories' => [
            MyService::class => MyServiceFactory::class,
        ],
    ]);
    
  3. First Use Case: Retrieve a service:

    $myService = $serviceManager->get(MyService::class);
    

Where to Look First

  • Documentation for core concepts like factories, plugin managers, and delegators.
  • Cookbook for practical examples (e.g., ConfigAbstractFactory, lazy services).
  • Plugin Managers for specialized service groups (e.g., validators, filters).

Implementation Patterns

Core Workflows

  1. Service Registration:

    • Factories: Map services to factory classes (explicit) or abstract factories (implicit).
      'factories' => [
          MyService::class => MyServiceFactory::class, // Explicit
          // OR
          MyService::class => ConfigAbstractFactory::class, // Implicit (via config)
      ],
      
    • Invokable Factories: For simple classes with no dependencies:
      'factories' => [
          MyService::class => InvokableFactory::class,
      ],
      
  2. Plugin Managers:

    • Extend AbstractPluginManager for homogeneous services (e.g., validators, filters).
    • Validate instances via $instanceOf or custom validate() logic.
    • Register the plugin manager as a service:
      'factories' => [
          ValidatorPluginManager::class => function($container) {
              return new ValidatorPluginManager($container, [
                  'factories' => [
                      StringLengthValidator::class => InvokableFactory::class,
                  ],
              ]);
          },
      ],
      
  3. Lazy Services:

    • Use LazyServiceFactory as a delegator to defer instantiation:
      'delegators' => [
          ExpensiveService::class => LazyServiceFactory::class,
      ],
      'lazy_services' => [
          'class_map' => [ExpensiveService::class => ExpensiveService::class],
      ],
      
  4. Delegators:

    • Modify service behavior dynamically (e.g., logging, caching):
      'delegators' => [
          MyService::class => [
              LoggerDelegatorFactory::class,
              CacheDelegatorFactory::class,
          ],
      ],
      

Integration Tips

  • Laravel Integration: Leverage Laravel’s App\ServiceProvider to bootstrap ServiceManager:

    public function register()
    {
        $this->app->singleton('ServiceManager', function ($app) {
            return new ServiceManager([
                'factories' => [
                    MyService::class => MyServiceFactory::class,
                ],
            ]);
        });
    }
    
  • Configuration: Use ConfigAbstractFactory to auto-configure services from arrays:

    'factories' => [
        'config' => ConfigAbstractFactory::class,
    ],
    

    Then inject config into services:

    'services' => [
        MyService::class => [
            'config' => ['param' => 'value'],
        ],
    ],
    
  • Testing: Mock the ServiceManager in tests:

    $mockServiceManager = $this->createMock(ServiceManager::class);
    $mockServiceManager->method('get')->willReturn(new MyService());
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies:

    • ServiceManager throws CircularReferenceException if services depend on each other.
    • Fix: Restructure dependencies or use lazy loading.
  2. Plugin Manager Validation:

    • Forgetting to set $instanceOf or override validate() can lead to runtime errors when invalid services are injected.
    • Tip: Always validate plugin manager instances in tests.
  3. Lazy Service Limitations:

    • Lazy services require class_map configuration to map service names to classes.
    • Gotcha: ProxyManager must be installed; otherwise, LazyServiceFactory fails silently or throws errors.
  4. Delegator Order:

    • Delegators execute in the order they’re defined. Reordering can break functionality.
    • Tip: Document delegator order in comments or config.
  5. Abstract Factory Performance:

    • Abstract factories add lookup overhead. Benchmark critical paths if performance is sensitive.
    • Tip: Use explicit factories for production-ready code (generate with vendor/bin/generate-factory-for-class).

Debugging

  • Service Not Found:

    • Check spelling in factories, aliases, or delegators.
    • Use has() to verify service registration:
      if (!$serviceManager->has(MyService::class)) {
          throw new \RuntimeException("Service not registered!");
      }
      
  • Factory Errors:

    • Wrap factory logic in try-catch to provide meaningful errors:
      public function __invoke($container, $requestedName, array $options = null) {
          try {
              return new MyService($options['config']);
          } catch (\Exception $e) {
              throw new \RuntimeException("Failed to create {$requestedName}: " . $e->getMessage(), 0, $e);
          }
      }
      
  • Lazy Service Debugging:

    • Verify class_map includes all lazy services:
      $serviceManager->get('config')['lazy_services']['class_map'];
      
    • Check ProxyManager logs for initialization issues.

Extension Points

  1. Custom Factories:

    • Implement FactoryInterface for reusable logic:
      class MyAbstractFactory implements AbstractFactoryInterface {
          public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
              // Shared logic for multiple services
          }
      }
      
  2. Custom Delegators:

    • Extend DelegatorFactory to modify service behavior:
      class LoggingDelegatorFactory extends DelegatorFactory {
          public function __invoke(ContainerInterface $container, $name, $requestedName, array $options = null) {
              $service = parent::__invoke($container, $name, $requestedName, $options);
              $logger = $container->get(LoggerInterface::class);
              return new LoggingProxy($service, $logger);
          }
      }
      
  3. Plugin Manager Extensions:

    • Override createService() to add pre/post-processing:
      class MyPluginManager extends AbstractPluginManager {
          protected function createService($name, $requestedName, $options = null) {
              $service = parent::createService($name, $requestedName, $options);
              // Modify $service here
              return $service;
          }
      }
      
  4. Configuration Overrides:

    • Use mergeConfig() in ServiceManager to override settings dynamically:
      $serviceManager->mergeConfig([
          'factories' => [
              MyService::class => NewFactory::class,
          ],
      ]);
      

Laravel-Specific Tips

  • Service Provider Bootstrapping: Register ServiceManager as a singleton to avoid recreation:

    public function register()
    {
        $this->app->singleton('ServiceManager', function ($app) {
            return new ServiceManager($app['config']['services']);
        });
    }
    
  • Service Binding: Bind Laravel’s container services to ServiceManager for consistency:

    $serviceManager->setService('request', $app->make('request'));
    
  • Middleware Integration: Use ServiceManager to resolve middleware in Laravel’s pipeline:

    $middleware = $serviceManager->get(Middleware::class);
    
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