Dependency Injection and Service Providers.
Compose the application explicitly in providers and consume services through constructor injection.
Registering services
A provider implements ServiceProviderInterface. Its register(ContainerBuilderInterface $builder) only declares bindings, aliases, and tags; it does not perform request or database work.
<?php
use App\Services\ArticleRepository;
use App\Services\ArticleRepositoryInterface;
use Lemonade\Framework\Container\ContainerBuilderInterface;
use Lemonade\Framework\Core\ServiceProviderInterface;
final class AppServiceProvider implements ServiceProviderInterface
{
public function register(ContainerBuilderInterface $builder): void
{
$builder->scoped(ArticleRepository::class, ArticleRepository::class);
$builder->alias(ArticleRepositoryInterface::class, ArticleRepository::class);
}
}Add the provider to app/Config/Providers.yaml. Always map an interface to a concrete, explicitly registered service.
Service lifetimes
singleton() shares an instance in the root runtime, scoped() shares one in a Request, Command, or Job scope, and transient() creates a fresh instance for every resolution. Post-registration side effects belong in BootableServiceProviderInterface::boot().