Skip to main content

Dependency Injection Container

Both the plugin and theme include a custom DI container with auto-wiring capabilities.

Plugin Container

Located at wp-ecommerce-core/includes/Container.php.

Registering Services

// Singleton — same instance every time
$container->singleton(ProductService::class, function ($c) {
return new ProductService(
$c->make(ProductRepository::class)
);
});

// Factory — new instance every time
$container->bind(Cart::class, function ($c) {
return new Cart($c->make(CartStorage::class));
});

Resolving Services

// Explicit resolution
$productService = $container->make(ProductService::class);

// Auto-wiring — resolves constructor dependencies automatically
$service = $container->make(OrderService::class);
// If OrderService requires ProductService in its constructor,
// the container will resolve it automatically

Accessing the Container

// From anywhere in the plugin
$container = \WPECommerce\Core\Bootstrap::getInstance()->getContainer();
$service = $container->make(ProductService::class);

Theme Container

Located at flavor-starter/inc/core/Container.php. Same API as the plugin container.

Accessing via Helper

// flavor_app() returns the Bootstrap singleton
$bootstrap = flavor_app();

// Access theme services
$moduleManager = flavor_app()->getModuleManager();

Best Practices

  1. Register in Bootstrap — All services should be registered during the bootstrap phase
  2. Prefer constructor injection — Let the container resolve dependencies
  3. Use interfaces — Register interfaces, not concrete classes
  4. Singletons for services — Use singleton() for stateless services
  5. Factories for stateful objects — Use bind() for objects that hold state
// Good — interface binding
$container->singleton(
ProductRepositoryInterface::class,
ProductRepository::class
);

// Good — constructor injection
class OrderService
{
public function __construct(
private ProductRepositoryInterface $products,
private PaymentGateway $payments
) {}
}