Skip to main content

Service Definition Loader

Overview

The Service Definition Loader is a powerful feature in DomainFlow Core that automates the process of binding services into your application. By loading service definitions from configuration files, it allows you to register services using a consistent structure—supporting PHP, JSON, and YAML formats. This mechanism simplifies managing dependencies, centralizes configuration, and enables advanced features like factory methods and service tagging.


Key Concepts

  • Supported File Formats: Service definitions can be provided in PHP (returning an array), JSON, or YAML (via the Symfony YAML component). This flexibility lets you choose the format that best fits your project.

  • Definition Structure: Each service definition typically includes:

    • concrete: The fully qualified class name or alias to be bound.
    • factory: A callable for instantiating the service (takes precedence over a concrete definition).
    • shared: A boolean indicating whether the service should be a singleton.
    • tags: Optional grouping information for later retrieval or processing.
  • Error Handling: The loader validates the configuration file and the structure of each definition. It raises descriptive exceptions if the file cannot be read or if the format is invalid.

  • Custom File Reading: You can inject a custom file reader for testing or to modify file access behavior, ensuring flexibility when dealing with different file systems or formats.


Method Descriptions

setFileReader($fileReader)

Signature

public function setFileReader(FileReader $fileReader): void

Purpose Allows you to specify a custom file reader. This is particularly useful for testing or when you need to override the default file reading behavior.

ParameterTypeRequired?Description
$fileReaderFileReaderYesAn instance of a file reader to use.

Usage Example

$customReader = new CustomFileReader();
$app->setFileReader($customReader);

loadServiceDefinitions($file)

Signature

public function loadServiceDefinitions(string $file): void

Purpose Loads service definitions from the specified file. The method reads the file, parses its content based on its extension (PHP, JSON, or YAML), and binds each service into the container.

ParameterTypeRequired?Description
$filestringYesPath to the configuration file containing service definitions.

Usage Example

$app->loadServiceDefinitions(__DIR__ . '/config/services.php');
  • Internal Flow:
  1. Checks if the file exists and is readable.
  2. Uses a file reader to get the content.
  3. Parses the file according to its extension.
  4. Iterates over each service definition and processes it (binding the service, setting shared flags, and tagging if specified).

Internal Methods (for Reference)

While not directly invoked by users, these methods handle the heavy lifting:

  • parseDefinitionsFile($file): Parses the configuration file based on its extension. Returns the service definitions as an array.

  • processServiceDefinition($abstract, $definition): Processes each individual service definition by binding it to the application container. It takes into account factory functions, shared flags, and tags.


Comparative Descriptions

  • Concrete vs. Factory Definitions: When both a concrete and a factory key are provided in a service definition, the loader will prioritize the factory callable. This allows for dynamic service instantiation based on custom logic.

  • Shared Services: Setting the shared flag to true ensures that the service is instantiated only once and the same instance is returned on subsequent requests, promoting efficient resource usage.

  • Tags: Adding tags to a service definition provides a way to group services, which can be useful for batch processing or retrieving services by category.


Practical Examples

Imagine you have a configuration file (e.g., services.php) with the following structure:

<?php
return [
'Mailer' => [
'concrete' => '\\App\\Mailer\\SmtpMailer',
'shared' => true,
'tags' => ['communication', 'email'],
],
'ReportGenerator' => [
'factory' => function ($container) {
return new \\App\\Reports\\Generator($container->get('Mailer'));
},
'shared' => false,
],
];

You would load these definitions into your application like this:

$app->loadServiceDefinitions(__DIR__ . '/config/services.php');

// Later, you can resolve the services:
$mailer = $app->get('Mailer');
$reportGenerator = $app->get('ReportGenerator');

Extensibility

  • Custom File Reader: Override the default file reader to support alternative storage systems or custom file access strategies.

  • Supporting Additional Formats: While the loader currently supports PHP, JSON, and YAML, you could extend it to handle other configuration formats by enhancing the parsing logic.

  • Dynamic Definition Updates: Consider integrating the loader with a caching mechanism to minimize file reads on every boot, or enabling runtime updates to service definitions for more dynamic environments.

This Service Definition Loader makes it easy to centralize and automate service registration, leading to a more modular and maintainable application architecture.