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' => \Laminas\ServiceManager\Factory\InvokableFactory::class,
        ],
    ]);
    
  3. First Use Case: Retrieve a service:

    $myService = $serviceManager->get('MyService');
    $myService->doSomething();
    

Where to Look First

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

Implementation Patterns

Core Workflows

  1. Service Registration:

    • Use factories for explicit service-to-factory mappings (best for performance and clarity):
      'factories' => [
          MyService::class => MyServiceFactory::class,
      ],
      
    • Use abstract_factories for dynamic discovery (convenience over performance):
      'abstract_factories' => [
          \Laminas\ServiceManager\Factory\ReflectionBasedAbstractFactory::class,
      ],
      
  2. Plugin Managers:

    • Extend AbstractPluginManager for homogeneous services (e.g., validators, filters):
      class MyPluginManager extends AbstractPluginManager {
          protected $instanceOf = MyInterface::class;
      }
      
    • Register the plugin manager in the root ServiceManager:
      'factories' => [
          MyPluginManager::class => function($container) {
              return new MyPluginManager($container, [
                  'factories' => [
                      MyService::class => InvokableFactory::class,
                  ],
              ]);
          },
      ],
      
  3. Lazy Services:

    • Enable lazy loading for expensive-to-instantiate services:
      'delegators' => [
          ExpensiveService::class => [
              \Laminas\ServiceManager\Proxy\LazyServiceFactory::class,
          ],
      ],
      'lazy_services' => [
          'class_map' => [
              ExpensiveService::class => ExpensiveService::class,
          ],
      ],
      
  4. Delegators:

    • Use delegators to modify service behavior (e.g., logging, caching):
      'delegators' => [
          MyService::class => [
              \Laminas\ServiceManager\Delegator\ServiceDelegatorFactory::class,
              \App\Delegator\LoggingDelegator::class,
          ],
      ],
      

Integration Tips

  • Laravel Integration: Leverage Laravel’s built-in ServiceProvider and bind()/singleton() methods to register services with laminas-servicemanager:

    public function register()
    {
        $this->app->singleton(MyService::class, function ($app) {
            return new MyService($app->make(Dependency::class));
        });
    }
    

    For plugin managers, use Laravel’s extend() or macro() to integrate with Laravel’s container:

    $this->app->extend('validator', function ($validator) {
        return new MyPluginManager($this->app, $validator->getConfig());
    });
    
  • Configuration: Use Laravel’s config() helper to load service configurations from config/services.php:

    $serviceManager = new ServiceManager(config('services'));
    
  • Testing: Mock the ServiceManager in tests:

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

Gotchas and Tips

Pitfalls

  1. Circular Dependencies:

    • Avoid circular dependencies between services. Use LazyServiceFactory or Proxy\LazyServiceFactory to defer initialization:
      'delegators' => [
          ServiceA::class => [LazyServiceFactory::class],
          ServiceB::class => [LazyServiceFactory::class],
      ],
      
  2. Plugin Manager Validation:

    • Forgetting to set $instanceOf or override validate() in a plugin manager can lead to runtime errors when invalid services are injected:
      // Wrong: No validation
      class MyPluginManager extends AbstractPluginManager {}
      
      // Correct: Enforce interface validation
      class MyPluginManager extends AbstractPluginManager {
          protected $instanceOf = MyInterface::class;
      }
      
  3. Abstract Factory Performance:

    • Abstract factories add overhead during service lookup. Profile your application if performance is critical, and switch to explicit factories for hot paths.
  4. Lazy Service Limitations:

    • Lazy services require ProxyManager. Ensure it’s installed and configured correctly. Lazy services cannot be serialized/deserialized directly (use ProxyManager's serialize()/unserialize() methods if needed).
  5. Delegator Order:

    • Delegators are applied in the order they are defined. The last delegator in the array runs first. Plan your delegator chain carefully:
      // Wrong: Logging runs after modification
      'delegators' => [
          MyService::class => [
              LoggingDelegator::class,
              ModifyingDelegator::class,
          ],
      ];
      
      // Correct: Modifying runs first
      'delegators' => [
          MyService::class => [
              ModifyingDelegator::class,
              LoggingDelegator::class,
          ],
      ];
      

Debugging Tips

  1. Service Not Found:

    • Check for typos in service names or factory class names. Enable debug mode to see detailed error messages:
      $serviceManager->setService('debug', true);
      
  2. Factory Errors:

    • Wrap factory logic in try-catch blocks to provide meaningful error messages:
      function ($container, $requestedName, array $options = []) {
          try {
              return new MyService($container->get(Dependency::class));
          } catch (Exception $e) {
              throw new Exception("Failed to create {$requestedName}: " . $e->getMessage());
          }
      }
      
  3. Plugin Manager Issues:

    • Use getRegisteredFactories() to inspect registered services:
      $pluginManager = $serviceManager->get(MyPluginManager::class);
      print_r($pluginManager->getRegisteredFactories());
      
  4. Lazy Service Debugging:

    • Verify lazy services are proxied by checking the class name:
      $service = $serviceManager->get(MyService::class);
      var_dump(class_exists('ProxyManager\Proxy\LazyLoadingInterface') &&
               $service instanceof ProxyManager\Proxy\LazyLoadingInterface);
      

Extension Points

  1. Custom Factories:

    • Create reusable factories for common patterns (e.g., database connections, HTTP clients):
      class DatabaseConnectionFactory implements FactoryInterface {
          public function __invoke(ContainerInterface $container, $requestedName, array $options = []) {
              return new PDO(
                  $options['dsn'],
                  $options['username'],
                  $options['password']
              );
          }
      }
      
  2. Custom Delegators:

    • Extend AbstractDelegatorFactory to add cross-cutting concerns (e.g., caching, metrics):
      class CacheDelegatorFactory extends AbstractDelegatorFactory {
          public function __invoke(ContainerInterface $container, $name, $requestedName, array $options = []) {
              $service = $this->getService($container, $name);
              return new CacheProxy($service, $container->get('cache'));
          }
      }
      
  3. Custom Plugin Managers:

    • Extend AbstractPluginManager for domain-specific validation (e.g., API clients, payment gateways):
      class ApiClientPluginManager extends AbstractPluginManager {
          protected $instanceOf = ApiClientInterface::class;
      
          public function validate($instance) {
              if (!$instance instanceof ApiClientInterface) {
                  throw new InvalidServiceException('Invalid API client');
              }
              if (!$instance->isConnected()) {
                  throw new InvalidServiceException('Disconnected API client');
              }
          }
      }
      
  4. Service Manager Extensions:

    • Override ServiceManager methods to add custom behavior (e.g., auto-registration, lifecycle hooks):
      class CustomServiceManager extends ServiceManager {
          public function get($name, $plugin = null) {
              if
      
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony