サービス定義

コンフィギュレーションは、カスタムサービスの定義を配置する場所です。これは、セクションservices で行います。

例えば、これはdatabase という名前のサービスを作成する方法で、これはクラスPDO のインスタンスになります。

services:
	database: PDO('sqlite::memory:')

サービスの名前付けは,サービスを参照できるようにするために行います.もしサービスが参照されないのであれば、名前を付ける必要はありません。そこで、名前の代わりに箇条書きを使っているだけです。

services:
	- PDO('sqlite::memory:')  #  anonymous service

1行のエントリーを複数行に分割して、setupなどのキーを追加できるようにすることも可能です。create: キーのエイリアスは、factory: です。

services:
	database:
		create: PDO('sqlite::memory:')
		setup: ...

次に、DIコンテナからサービスを取り出すには、名前を指定してgetService() というメソッドを使うか、種類を指定してgetByType() というメソッドを使うとよいでしょう。

$database = $container->getService('database');
$database = $container->getByType(PDO::class);

サービスの作成

多くの場合、サービスの作成は単にクラスのインスタンスを作成することで行います。

services:
	database: PDO('mysql:host=127.0.0.1;dbname=test', root, secret)

この場合、DIコンテナ内にファクトリーメソッドが生成されます。

public function createServiceDatabase(): PDO
{
	return new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret');
}

また、引数の受け渡しにキーarguments を使うこともできます。

services:
	database:
		create: PDO
		arguments: ['mysql:host=127.0.0.1;dbname=test', root, secret]

静的メソッドは、サービスを作成することもできます。

services:
	database: My\Database::create(root, secret)

PHP のコードに対応します。

public function createServiceDatabase(): PDO
{
	return My\Database::create('root', 'secret');
}

静的メソッドMy\Database::create() は、DI コンテナが知る必要のある戻り値が定義されていることが前提です。もしそれがない場合は、その型を設定に書き込みます。

services:
	database:
		create: My\Database::create(root, secret)
		type: PDO

Nette DIは、非常に強力な表現機能を備えており、ほとんど何でも書くことができます。例えば、他のサービスを参照して、そのメソッドを呼び出すことができます。簡単のために、-> の代わりに:: を使用します。

services:
	routerFactory: App\Router\Factory
	router: @routerFactory::create()

PHPのコードに対応します。

public function createServiceRouterFactory(): App\Router\Factory
{
	return new App\Router\Factory;
}

public function createServiceRouter(): Router
{
	return $this->getService('routerFactory')->create();
}

PHPのようにメソッドコールを連鎖させることができます。

services:
	foo: FooFactory::build()::get()

PHPのコードに対応しています。

public function createServiceFoo()
{
	return FooFactory::build()->get();
}

引数

名前付きパラメータは引数の受け渡しに使うこともできます。

services:
	database: PDO(
		'mysql:host=127.0.0.1;dbname=test'  # positional
		username: root                      # named
		password: secret                    # named
	)

引数を複数行に分ける場合、カンマの使用は任意である。

もちろん、他のサービスや パラメータを引数として使用することもできます。

services:
	- Foo(@anotherService, %appDir%)

PHPのコードに対応します。

public function createService01(): Foo
{
	return new Foo($this->getService('anotherService'), '...');
}

第一引数が自動生成で、第二引数を指定したい場合は、第一引数を省略して_ character, for example Foo(_, %appDir%). あるいは、第二引数のみを名前付きパラメータとして渡すのがよいでしょう。例えば、Foo(path: %appDir%).

Nette DI と NEON フォーマットは、ほとんど何でも書くことができる非常に強力な表現力を持っています。そのため、引数には新しく作成したオブジェクトを指定したり、静的メソッドや他のサービスのメソッドを呼び出したり、特殊な記法を使ってグローバルな関数を呼び出すこともできます。

services:
	analyser: My\Analyser(
		FilesystemIterator(%appDir%)         # create object
		DateTime::createFromFormat('Y-m-d')  # call static method
		@anotherService                      # passing another service
		@http.request::getRemoteAddress()    # calling another service method
		::getenv(NetteMode)                  # call a global function
	)

PHPのコードに対応します。

public function createServiceAnalyser(): My\Analyser
{
	return new My\Analyser(
		new FilesystemIterator('...'),
		DateTime::createFromFormat('Y-m-d'),
		$this->getService('anotherService'),
		$this->getService('http.request')->getRemoteAddress(),
		getenv('NetteMode')
	);
}

特殊機能

引数で特殊関数を使用し、値のキャストやネゲートを行うこともできます。

  • not(%arg%) 負論理
  • bool(%arg%) 無損失な bool へのキャスト
  • int(%arg%) int へのロスレスキャスト
  • float(%arg%) float へのロスレスキャスト
  • string(%arg%) ロスレス キャストから文字列
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)

ロスレス書き換えは、通常の PHP の書き換え ((int) など) とは異なり、数値以外の値では例外がスローされます。

引数として、複数のサービスを渡すことができます。特定の型 (クラスやインターフェイス) のすべてのサービスの配列は、関数typed() で作成されます。この関数では,自動配線を無効にしているサービスは省略されます.また,複数のタイプをカンマで区切って指定することもできます.

services:
	- BarsDependent( typed(Bar) )

また,autowiringを使用して,自動的にサービスの配列を渡すこともできます.

あるタグを持つすべてのサービスの配列を関数tagged() で作成します.タグはカンマで区切って複数指定することができます。

services:
	- LoggersDependent( tagged(logger) )

参照先サービス

個々のサービスの参照には、@ and name, so for example @database を使用します。

services:
	- create: Foo(@database)
	  setup:
			- setCacheStorage(@cache.storage)

PHPのコードに対応します。

public function createService01(): Foo
{
	$service = new Foo($this->getService('database'));
	$service->setCacheStorage($this->getService('cache.storage'));
	return $service;
}

匿名サービスでもコールバックを使って参照することができます。ただし、自動配線の関係で通常は必要ありません。

services:
	- create: Foo(@Nette\Database\Connection)  # or @\PDO
	  setup:
			- setCacheStorage(@cache.storage)

セットアップ

セットアップでは、サービスを作成する際に呼び出されるメソッドをリストアップします。

services:
	database:
		create: PDO(%dsn%, %user%, %password%)
		setup:
			- setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)

PHPのコードに対応します。

public function createServiceDatabase(): PDO
{
	$service = new PDO('...', '...', '...');
	$service->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	return $service;
}

プロパティを設定することも可能です。配列への要素の追加もサポートされており、NEON の構文と衝突しないように引用符で囲んで記述する必要があります。

services:
	foo:
		create: Foo
		setup:
			- $value = 123
			- '$onClick[]' = [@bar, clickHandler]

PHP のコードに対応します。

public function createServiceFoo(): Foo
{
	$service = new Foo;
	$service->value = 123;
	$service->onClick[] = [$this->getService('bar'), 'clickHandler'];
	return $service;
}

ただし、静的メソッドや他のサービスのメソッドもセットアップで呼び出すことができます。それらには、実際のサービスを@self として渡します。

services:
	foo:
		create: Foo
		setup:
			- My\Helpers::initializeFoo(@self)
			- @anotherService::setFoo(@self)

PHPのコードに対応する。

public function createServiceFoo(): Foo
{
	$service = new Foo;
	My\Helpers::initializeFoo($service);
	$this->getService('anotherService')->setFoo($service);
	return $service;
}

オートワイヤリング

autowiredキーは、あるサービスを自動配線から除外したり、その動作に影響を与えたりするために使用されます。詳細については、「自動配線」の章を参照してください。

services:
	foo:
		create: Foo
		autowired: false     # foo is removed from autowiring

タグ

個々のサービスには、タグという形でユーザー情報を付加することができます。

services:
	foo:
		create: Foo
		tags:
			- cached

タグは値を持つこともできます。

services:
	foo:
		create: Foo
		tags:
			logger: monolog.logger.event

特定のタグを持つサービスの配列は,関数tagged() を使って引数として渡すことができます.カンマで区切って複数のタグを指定することもできます.

services:
	- LoggersDependent( tagged(logger) )

サービス名は,DIコンテナからfindByTag() というメソッドで取得することができる.

$names = $container->findByTag('logger');
// $names is an array containing the service name and tag value
// i.e. ['foo' => 'monolog.logger.event', ...]

インジェクトモード

inject: true フラグは、injectアノテーションとinject*()メソッドによるパブリック変数経由の依存関係の受け渡しを有効にするために使用されます。

services:
	articles:
		create: App\Model\Articles
		inject: true

デフォルトでは、inject はプレゼンターに対してのみ有効です。

サービスの変更

DIコンテナには、ビルトインまたは拡張機能によって追加されたサービスが多数存在します。これらのサービスの定義は、コンフィギュレーションで変更することができます。例えば、サービスapplication.application 、デフォルトではオブジェクトNette\Application\Application 、クラスを変更することができます。

services:
	application.application:
		create: MyApplication
		alteration: true

alteration フラグは情報提供であり、既存のサービスを変更するだけであることを示します。

また、セットアップを追加することもできます。

services:
	application.application:
		create: MyApplication
		alteration: true
		setup:
			- '$onStartup[]' = [@resource, init]

サービスを書き換える際、元の引数や設定項目、タグを削除したい場合があります。そのために、reset 。

services:
	application.application:
		create: MyApplication
		alteration: true
		reset:
			- arguments
			- setup
			- tags

拡張で追加されたサービスもコンテナから削除することができます.

services:
	cache.journal: false
version: 3.x