モデル

アプリケーションが成長するにつれて、異なる場所、異なる Presenter で、データベースに対して同様の操作を実行する必要があることにすぐに気づくでしょう。たとえば、最新の公開記事を取得するなどです。記事に下書きかどうかを示すフラグを追加するなどしてアプリケーションを改善する場合、データベースから記事を取得するアプリケーション内のすべての場所を調べて、下書きでない記事のみを選択するように where 条件を追加する必要があります。

その時点で、データベースとの直接的なやり取りは不十分になり、公開された記事を返す新しい関数で支援する方が賢明です。そして、後で別の条件、たとえば将来の日付の記事を表示しないように追加する場合、コードを 1 か所だけ変更します。

関数を PostFacade クラスに配置し、getPublicArticles() と名付けます。

app/Model/ ディレクトリに、記事を処理するモデルクラス PostFacade を作成します。

<?php
namespace App\Model;

use Nette;

final class PostFacade
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	public function getPublicArticles()
	{
		return $this->database
			->table('posts')
			->where('created_at < ', new \DateTime)
			->order('created_at DESC');
	}
}

クラスでは、コンストラクタを使用してデータベース Explorer を渡してもらいます。DI コンテナ の力を活用します。

HomePresenter に切り替えて、Nette\Database\Explorer への依存関係を取り除き、新しいクラスへの新しい依存関係に置き換えるように変更します。

<?php
namespace App\Presentation\Home;

use App\Model\PostFacade;
use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private PostFacade $facade,
	) {
	}

	public function renderDefault(): void
	{
		$this->template->posts = $this->facade
			->getPublicArticles()
			->limit(5);
	}
}

use セクションには App\Model\PostFacade があるため、PHP コードの記述を PostFacade に短縮できます。コンストラクタでこのオブジェクトを要求し、$facade プロパティに書き込み、renderDefault メソッドで使用します。

残りの最後のステップは、DI コンテナにこのオブジェクトを作成する方法を教えることです。これは通常、config/services.neon ファイルの services セクションにインデントを追加し、クラスの完全な名前とコンストラクタのパラメータを指定することによって行われます。 これにより、いわゆる登録が行われ、オブジェクトは サービス と呼ばれます。autowiring という魔法のおかげで、DI がコンストラクタのパラメータを自動的に認識して渡すため、ほとんどの場合、パラメータを指定する必要はありません。したがって、クラス名だけを指定するだけで十分です。

...

services:
	- App\Model\PostFacade

ただし、この行を追加する必要さえありません。services.neon の冒頭にある search セクションで、-Facade または -Factory で終わるすべてのクラスは DI によって自動的に検索されるように定義されています。これは PostFacade の場合も同様です。

まとめ

PostFacade クラスはコンストラクタで Nette\Database\Explorer の受け渡しを要求し、このクラスは DI コンテナに登録されているため、コンテナはこのインスタンスを作成して渡します。DI はこのようにして PostFacade のインスタンスを作成し、それを要求した HomePresenter クラスのコンストラクタに渡します。まるでマトリョーシカのようです。:) 誰もが欲しいものを言うだけで、何がどこでどのように作成されるかについては気にしません。作成は DI コンテナが担当します。

ここでは、dependency injection設定 について詳しく読むことができます。