Chapter 9: Services and Dependency Injection in Zend Framework 3
✅ Introduction
In Zend Framework 3, Services are reusable classes that provide functionality such as business logic, database access, or third-party integrations. The ServiceManager is a powerful Dependency Injection (DI) container that manages object creation and dependencies automatically.
✅ Key Concepts
- Service: A class that performs specific tasks (e.g., UserService for user operations).
- Dependency Injection: A design pattern where dependencies are passed into a class instead of being created inside it.
- ServiceManager: Zend Framework’s built-in container for managing services and their dependencies.
✅ Creating a Service Class
// module/Application/src/Service/UserService.php
namespace Application\Service;
class UserService {
public function getUserById($id) {
// Example: Fetch from database (mock for now)
return [
'id' => $id,
'name' => 'John Doe',
'role' => 'user'
];
}
}
✅ Registering the Service
Register your service in the module.config.php file:
return [
'service_manager' => [
'factories' => [
Application\Service\UserService::class => InvokableFactory::class,
],
],
];
✅ Using the Service in a Controller
// module/Application/src/Controller/UserController.php
namespace Application\Controller;
use Application\Service\UserService;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class UserController extends AbstractActionController {
private $userService;
public function __construct(UserService $userService) {
$this->userService = $userService;
}
public function profileAction() {
$id = $this->params()->fromRoute('id', 1);
$user = $this->userService->getUserById($id);
return new ViewModel(['user' => $user]);
}
}
✅ Injecting Service into Controller with Factory
// module/Application/src/Factory/UserControllerFactory.php
namespace Application\Factory;
use Application\Controller\UserController;
use Application\Service\UserService;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class UserControllerFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
$userService = $container->get(UserService::class);
return new UserController($userService);
}
}
✅ Update module.config.php
return [
'controllers' => [
'factories' => [
Application\Controller\UserController::class => Application\Factory\UserControllerFactory::class,
],
],
];
✅ Dependency Injection Benefits
- Removes tight coupling between classes.
- Makes unit testing easier (mock dependencies).
- Improves code reusability and maintainability.
✅ Best Practices
- Always inject dependencies via the constructor.
- Keep services focused on one responsibility (Single Responsibility Principle).
- Use factories for complex services that require multiple dependencies.
- Leverage the
ServiceManagerinstead of creating objects manually.
✅ Exercise
- Create a
PostServiceclass to fetch blog posts. - Register the service in
module.config.php. - Inject the service into a
PostControllerusing a factory. - Display a list of posts in a view template using the injected service.
