hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

PHP-DI #126

Open hysryt opened 5 years ago

hysryt commented 5 years ago

http://php-di.org/ DIコンテナライブラリ オートワイヤリングが特徴 PSR-11に準拠している。

hysryt commented 5 years ago

PHPのサポート

PHP-DIバージョン サポートするPHP
PHP-DI 5.0 PHP 5.4 以降
PHP-DI 5.3 PHP 5.5 以降
PHP-DI 6 PHP 7 以降

PHP-DI は常に最新のバージョンのみサポートされる。 つまり PHP-DI 5.3 にセキュリティバグがあったとしても PHP 5.5 用のパッチが当てられることはない。

PHP 自体は 2019/09/22 時点ですでに 7.0 までのサポートを終了している。 ただし、いまだに 5 を使用しているところも多い。

hysryt commented 5 years ago

インストール

Composer でインストール

composer require php-di/php-di
hysryt commented 5 years ago

オートワイヤリング

class Test {
  function __construct() {
    echo 'hello, world';
  }
}

$container = new DI\Container();
$container->get('Test');  // hello, world

初回get時に自動的にインスタンス化される。


class A {
  function __construct() {
    echo 'I`m A.';
  }
}

class B {
  function __construct(A $a) {
    echo 'I`m B.';
  }
}

$container = new DI\Container();
$container->get('B');  // I`m A.I`m B.

オートワイヤリング機能によって、コンストラクタによる依存性注入が自動的に行われる。 タイプヒンティングで指定したクラスが自動的に紐づけられるため、依存関係の明示的な設定が必要ない。

タイピヒンティングがインターフェース名の場合はオートワイヤリングが使用できないため、明示的な設定の記述が必要になる。

hysryt commented 5 years ago

ベストプラクティス

http://php-di.org/doc/best-practices.html PHP-DIが推奨する使用方法。

コントローラーを記述する場合

コントローラーにはプロパティに対してアノテーションで依存性を注入する。

プロパティインジェクションは一般的にあまり好まれない傾向にある。

ただし、コントローラーは以下の特徴を持つため、プロパティインジェクションに向いている

サービスを記述する場合

サービスにはコンストラクタでオートワイヤリングを活用して依存性を注入する。

ライブラリを使用する場合

匿名関数でライブラリの設定をし、インスタンスを返す

hysryt commented 5 years ago

PHPで依存性注入の定義を行う場合

<?php

include './vendor/autoload.php';

interface TestInterface {
  public function say();
}

class Test implements TestInterface {
  public function say() {
    echo 'hello!!!';
  }
}

$builder = new \DI\ContainerBuilder();

$builder->addDefinitions([
  TestInterface::class => DI\create(Test::class)
]);

$container = $builder->build();

$test = $container->get('TestInterface');
$test->say();  // hello!!!

ContainerBuilder インスタンスを作成し、addDefinitions() で依存性注入の定義を行う。 この例ではキーとして TestInterface を渡した場合、Test インスタンスを返すよう定義している。 この設定はオートワイヤリングにも適用される。

class A {
  function __construct(TestInterface $test) {
    $test->say();
  }
}

$container->get('A');  // hello!!!

リテラル値を設定

$builder->addDefinitions([
  'database.host' => 'localhost',
]);
$container = $builder->build();

echo $container->get('database.host');  // localhost

インスタンス化時に処理を挟む

$builder->addDefinitions([
  'TestInterface::class' => function(\Psr\Container\ContainerInterface $container) {
    echo 'インスタンスを作成します';
    return new Test();
  }
]);

セッターメソッドインジェクション

class A {
  function setTest(TestInterface $test) {
    $this->test = $test;
  }

  function say() {
    $this->test->say();
  }
}

$builder->addDefinitions([
  A::class => DI\create()->method('setTest', DI\get('Test'))
]);
$container = $builder->build();
$container->get('A')->say();

method() を使用する

プロパティインジェクション

class A {
  private $test;

  function say() {
    $this->test->say();
  }
}

$builder->addDefinitions([
  A::class => DI\create()->property('test', DI\get('Test'))
]);
$container = $builder->build();
$container->get('A')->say();

property() を使用する。