DI: Services Configuration
Dependency injection (DI) container is easily configured using NEON files.
The configuration is usually written in NEON format. Have fun trying out the syntax at https://ne-on.org.
services:
database: Nette\Database\Connection(%dsn%, %user%, %password%)
# or multi-lines
database:
factory: Nette\Database\Connection(%dsn%, %user%, %password%)
# or more multi-lines :-)
database:
class: Nette\Database\Connection
arguments: [%dsn%, %user%, %password%]
Generates:
function createServiceDatabase()
{
return new Nette\Database\Connection(
$this->parameters['dsn'],
$this->parameters['user'],
$this->parameters['password']
);
}
Service definition:
services:
database:
class: Nette\Database\Connection
factory: DbFactory::createConnection
DbFactory::createConnection
:
class DbFactory
{
static function createConnection()
{
...
}
}
Generates:
function createServiceDatabase()
{
return DbFactory::createConnection($this);
}
Setup
services:
database:
factory: Nette\Database\Connection(%dsn%, %user%, %password%)
setup:
- setCacheStorage(@cacheStorage)
Generates:
function createServiceDatabase()
{
$service = new Nette\Database\Connection(...);
$service->setCacheStorage($this->cacheStorage);
return $service;
}
Autowiring feature adds dependencies automatically, so they don't even have to be mentioned:
setup:
- setCacheStorage
In case the cacheStorage
service does not exist, it is possible to use a result of a call as a parameter:
setup:
- setCacheStorage( Factory::createStorage() )
# or a method of other service:
- setCacheStorage( @factory::createStorage() )
Alternatively a newly created class instance:
setup:
- setCacheStorage( Nette\Caching\Storages\FileStorage(%tempDir%) )
# generates: $service->setCacheStorage(new Nette\Caching\Storages\FileStorage(...));
You can also set a value of a property:
substitutions
setup:
- $substitutions( [db: test] )
# generates: $service->substitutions = array('db' => 'test');
Full example:
parameters:
database:
driver: mysql
host: localhost
dbname: test
user: jim
password: beam
substitutions:
db: test
services:
database:
factory: Nette\Database\Connection(
'%database.driver%:host=%database.host%;dbname=%database.dbname%',
%database.user%, %database.password%, null,
Nette\Database\Reflection\DiscoveredReflection()
)
setup:
- setCacheStorage
- $substitutions( %database.substitutions% )
Anonymous services
Time after time there are services that are in fact not referenced anywhere else in config files. Naming these services in this case is not necessary. To define an anonymous service, use the following syntax:
services:
- Simple\Service
-
factory: Complex\Service
setup:
- setLang(%lang%)
To refer to such anonymous service you will need to use the fully qualified class name instead.
services:
router: @App\RouterFactory::createRouter
Keep in mind that from a nature of anonymous services, it is not possible to register more than one of the same type, because it would lead to an ambiguity.
Service definitions inheritance
services:
dev_database < database
setup:
- Diagnostics\ConnectionPanel::initialize
Auto-wiring
Auto-wiring feature can automatically pass dependencies into constructor and methods of the service. It uses typehinting and
@return
annotations. There can be only one service matching the type in the container, otherwise an exception is
thrown.
To define more than one service of the same type we need to exclude them from auto-wiring:
services:
cacheStorage:
factory: Nette\Caching\Storages\FileStorage(%tempDir%)
tempCacheStorage:
factory: Nette\Caching\Storages\DevNullStorage
autowired: no
When modifying the Nette Framework's core services we need to make sure the container is aware of the classes we want to use.
That means using fully qualified class names in @return
annotations or set the FQ class name with
class
entry.
Multiple configuration files
Use includes
section to add more configuration files.
includes:
- parameters.php
- services.neon
- presenters.neon
Configuration merging process assigns the highest priority to the file containing includes
section and the lowest
priority to the first included file. To prevent merging of a certain array use exclamation mark right after the name of
the array:
argument!: [1, 2, 3]