Nette Documentation Preview

syntax
サービス定義
******

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

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

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

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

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

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

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

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

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


サービスの作成 .[#toc-creating-a-service]
==================================

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


引数 .[#toc-arguments]
====================

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

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

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

もちろん、[他のサービスや |#Referencing Services] [パラメータを |configuration#parameters]引数として使用することもできます。

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

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

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

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

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

```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のコードに対応します。

```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')
	);
}
```


特殊機能 .[#toc-special-functions]
------------------------------

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

-`not(%arg%)` 負論理
-`bool(%arg%)` 無損失な bool へのキャスト
-`int(%arg%)` int へのロスレスキャスト
-`float(%arg%)` float へのロスレスキャスト
-`string(%arg%)` ロスレス キャストから文字列

```neon
services:
	- Foo(
		id: int(::getenv('ProjectId'))
		productionMode: not(%debugMode%)
	)
```

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

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

```neon
services:
	- BarsDependent( typed(Bar) )
```

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

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

```neon
services:
	- LoggersDependent( tagged(logger) )
```


参照先サービス .[#toc-referencing-services]
====================================

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

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

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

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

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

```neon
services:
	-	create: Foo(@Nette\Database\Connection)
		setup:
			- setCacheStorage(@cache.storage)
```


セットアップ .[#toc-setup]
====================

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

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

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

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

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


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

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

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

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


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

PHPのコードに対応する。

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


オートワイヤリング .[#toc-autowiring]
============================

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

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


タグ .[#toc-tags]
===============

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

```neon
services:
	foo:
		create: Foo
		tags:
			- cached
```

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

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

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

```neon
services:
	- LoggersDependent( tagged(logger) )
```

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

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


インジェクトモード .[#toc-inject-mode]
=============================

`inject: true` フラグは、[inject |best-practices:en:inject-method-attribute#Inject Attributes]アノテーションと[inject*() |best-practices:en:inject-method-attribute#inject Methods]メソッドによるパブリック変数経由の依存関係の受け渡しを有効にするために使用されます。

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

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


サービスの変更 .[#toc-modification-of-services]
========================================

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

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

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

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

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

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

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

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

```neon
services:
	cache.journal: false
```

サービス定義

コンフィギュレーションは、カスタムサービスの定義を配置する場所です。これは、セクション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)
		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