DI コンテナの設定

Nette DI コンテナの設定オプションの概要です。

設定ファイル

Nette DI コンテナは設定ファイルで簡単に制御できます。設定ファイルはふつう NEON 形式で書きます。この形式に対応したエディタを使うことをおすすめします。

 decorator: 	Decorator
di: DI コンテナ
extensions: 追加の DI 拡張のインストール
includes: ファイルの読み込み
parameters: パラメータ
search: サービスの自動登録
services: サービス

% を含む文字列を書くには、%% のように二重にしてエスケープする必要があります。

パラメータ

設定では、サービスの定義の中で使えるパラメータを定義できます。おかげで設定が分かりやすくなり、変わり得る値をひとつの場所にまとめられます。

parameters:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: secret

dsn パラメータは、設定のどこからでも %dsn% という書き方で参照します。パラメータは '%wwwDir%/images' のように文字列の中でも使えます。

パラメータは文字列や数値だけでなく、配列を含むこともできます。

parameters:
	mailer:
		host: smtp.example.com
		secure: ssl
		user: franta@gmail.com
	languages: [cs, en, de]

特定のキーは %mailer.user% のように参照します。

コード(クラスなど)がパラメータの値を必要とするなら、その値をクラスに渡してください。たとえばコンストラクタで渡します。クラスがパラメータの値を問い合わせられるグローバルな設定オブジェクトはありません。それは依存性注入の原則に反するからです。

サービス

別の章をご覧ください。

Decorator

ある型の複数のサービスを一度に変更するにはどうすればよいでしょうか。たとえば、ある基底クラスを継承するすべてのプレゼンターで特定のメソッドを呼ぶには? そのための decorator です。

decorator:
	# このクラスやインターフェースのインスタンスであるすべてのサービスに対して
	App\Presentation\BasePresenter:
		setup:
			- setProjectId(10)       # このメソッドを呼びます
			- $absoluteUrls = true   # そして変数を設定します

decorator はタグの設定や inject モードの有効化にも使えます。

decorator:
	InjectableInterface:
		tags: [mytag: 1]
		inject: true

DI

DI コンテナの技術的な設定です。

di:
	# DIC を Tracy バーに表示しますか?
	debugger: ...        # (bool) 既定は自動検出(Tracy があれば有効)

	# 決してオートワイヤリングしないパラメータの型
	excluded: ...        # (string[])

	# サービスの遅延生成を有効にしますか?
	lazy: ...            # (bool) 既定は false

	# DI コンテナが継承するクラス
	parentClass: ...     # (string) 既定は Nette\DI\Container

遅延サービス

lazy: true を設定すると、サービスの遅延生成が有効になります。つまりサービスは DI コンテナに要求された時点では実際には作られず、最初に使われるときにはじめて作られます。そのリクエストで本当に必要なサービスだけが作られるので、アプリケーションの起動が速くなり、メモリの使用量も減らせます。

個々のサービスについて、遅延生成は調整できます

遅延オブジェクトはユーザー定義のクラスにしか使えず、PHP の内部クラスには使えません。PHP 8.4 以上が必要です。

メタデータの書き出し

DI コンテナのクラスには多くのメタデータも含まれます。メタデータの書き出しを減らせば、その大きさを抑えられます。

di:
	export:
		# パラメータを書き出しますか?
		parameters: false   # (bool) 既定は true

		# タグを書き出しますか、そしてどれを?
		tags:               # (string[]|bool) 既定はすべて
			- event.subscriber

		# オートワイヤリング用のデータを書き出しますか、そしてどれを?
		types:              # (string[]|bool) 既定はすべて
			- Nette\Database\Connection
			- Symfony\Component\Console\Application

$container->getParameters() を使わないなら、パラメータの書き出しを無効にできます。さらに、$container->findByTag(...) でサービスを取得するのに実際に使うタグだけを書き出せます。このメソッドをまったく呼ばないなら、false を使ってタグの書き出しを完全に無効にできます。

オートワイヤリングのメタデータも、$container->getByType() で実際に要求するクラスだけを並べれば大きく減らせます。このメソッドを呼ばないなら(あるいは Nette\Application\Application を得るために bootstrapファイルでしか呼ばないなら)、false を使って型の書き出しを完全に無効にできます。

Extensions

追加の DI 拡張の登録です。たとえば DI 拡張 Dibi\Bridges\Nette\DibiExtension3dibi という名前で追加するにはこうします。

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension3

そして dibi セクションで設定します。

dibi:
	host: localhost

パラメータ付きのクラスを拡張として追加することもできます。

extensions:
	application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, [%appDir%], %tempDir%/cache)

ファイルの読み込み

追加の設定ファイルは includes セクションで読み込めます。

includes:
	- parameters.php
	- services.neon
	- presenters.neon

parameters.php という名前は誤りではありません。設定は、それを配列として返す PHP ファイルで書くこともできます。

<?php
return [
	'database' => [
		'main' => [
			'dsn' => 'sqlite::memory:',
		],
	],
];

複数の設定ファイルに同じキーの項目が現れた場合、それらは上書きされるか、配列の場合は統合されます。あとで読み込まれたファイルのほうが、前のものより優先度が高くなります。includes セクションを持つファイルは、そこで読み込まれるファイルより優先度が高くなります。

DI コンテナへのサービスの自動登録は、開発を大きく楽にします。Nette はプレゼンターを自動的にコンテナへ追加しますが、ほかのクラスも簡単に追加できます。

クラスをどのディレクトリ(とサブディレクトリ)で探すべきかを指定するだけです。

search:
	-	in: %appDir%/Forms
	-	in: %appDir%/Model

探索の規則がひとつだけなら、リストを省いてそのキーを search の直下に書けます。

search:
	in: %appDir%

とはいえ、ふつうはすべてのクラスとインターフェースを追加したいわけではないので、絞り込めます。

search:
	-	in: %appDir%/Forms

		# ファイル名による絞り込み (string|string[])
		files:
			- *Factory.php

		# クラス名による絞り込み (string|string[])
		classes:
			- *Factory

あるいは、並べたクラスの少なくともひとつを継承または実装するクラスを選べます。

search:
	-	in: %appDir%
		extends:
			- App\*Form
		implements:
			- App\*FormInterface

クラス名のマスクや祖先を使って除外の規則を定めることもできます。クラスが除外の規則に当てはまれば、DI コンテナには追加されません。

search:
	-	in: %appDir%
		exclude:
			files: ...
			classes: ...
			extends: ...
			implements: ...

自動登録されるすべてのサービスにタグを割り当てられます。

search:
	-	in: %appDir%
		tags: ...

クラスのほかに、探索は create() または get() メソッドをひとつだけ持つインターフェースも生成されるファクトリやアクセサとして登録します。同じ型のサービスがすでにコンテナに登録されているクラスは飛ばされるので、重複はできません。

統合

複数の設定ファイルに同じキーの要素が現れた場合、それらは上書きされるか、配列の場合は統合されます。あとで読み込まれたファイルのほうが、前のものより優先度が高くなります。

config1.neon config2.neon 結果
items:
	- 1
	- 2
items:
	- 3
items:
	- 1
	- 2
	- 3

配列については、キー名のあとに感嘆符を付けると統合を防げます。

config1.neon config2.neon 結果
items:
	- 1
	- 2
items!:
	- 3
items:
	- 3
バージョン: 3.x