Help us understand the problem. What is going on with this article?

Yii2 かんたんコンテナ

More than 5 years have passed since last update.

Yii2は便利なものや、強力なdebugツール等至れり尽くせりなフレームワークですが、
コンテナもシンプルで強力なものの一つです
振る舞いを変更したりサービスロケータにしてみたり
簡単に幅広く利用する事が出来ます

Yii.php
class Yii extends \yii\BaseYii
{
}

spl_autoload_register(['Yii', 'autoload'], true, true);
Yii::$classMap = include(__DIR__ . '/classes.php');
Yii::$container = new yii\di\Container;

と実装されていますので、どこでも簡単に利用できます
ではいくつか利用方法を紹介しましょう!

basic

// 単体で利用
$container = new yii\di\Container;
// フレームワーク
\Yii::$container;

さっそくコンテナを利用してみます
まずは普通のクラスを作って、インスタンスを作ってみましょう

service/Acme.php
namespace app\service;

/**
 * Class Acme
 * @package app\service
 */
class Acme
{

} 

上記のシンプルなクラスのインスタンスを取得する場合は

$container->get('app\service\Acme');

となります
di/Container.phpでbuildメソッドを利用してインスタンスを生成しています

引数利用

コンストラクタに引数を利用するクラスです

class Acme
{
    protected $acme;

    public function __construct($message = "")
    {
        $this->acme = $message;
    }
}

Reflectionを使ってコンストラクタの引数を調べて、
必要に応じて引数を利用してインスタンスを生成するので、
引数が必要なもの下記の様にしてみましょう

$container->get('app\service\Acme', ["yii2"]);

このあたりは他のコンテナライブラリやフレームワーク等と同じです

コンテナが返すものはインスタンスじゃなくてもOKです
文字列にすることもできます

$container->set('hi', function () {
        return 'yii';
    }
);
$container->get('hi');

プロパティにも

では下記の場合はどうでしょうか?
プロパティのみです

class Acme
{

    public $acme;
}

この場合は、

$container->set('hello', function () {
        return 'yii2';
    }
);

$container->get('app\service\Acme', [], [
        'acme' => $container->get('hello'),
    ]
);

上記の様にプロパティに対して代入することもできます

di/Container.php
$object = $reflection->newInstanceArgs($dependencies);
foreach ($config as $name => $value) {
    $object->$name = $value;
}

di/Containerで、
newInstanceArgsでインスタンスを作成してプロパティに挿入する様に実装されています
シンプル!

$container->get('app\service\Acme', [], [
        'acme' => function() {},
    ]
);

クロージャなどでも同様です

setter

private, protectedのプロパティに対しては、
セッターを利用する事が出来ます

class Acme extends Object
{

    public $acme;

    protected $private;

    public function setPrivate($private)
    {
        $this->private = $private;
    }
}

yii\base\Objectを継承すると、マジックメソッドの__setを利用して
protectedにも対応する事が出来ます

そしてさらに、
インスタンス生成時に利用できる様に、コンテナにまとめて登録する事も出来ます

$container->set('app\service\Acme', [
        'acme' => 'yii'
    ]
);
$container->get('app\service\Acme');

コンテナに登録するときに、classを利用するとそのインスタンスを返す様になります

$container->set('acme.class', [
        'class' => 'app\service\Acme',
        'acme' => 'yii'
    ]
);
$container->get('acme.class');

すごい楽チンで多彩!それでいてシンプル故に早い!
下記の様な場合は、コンストラクタで記述されているクラスも自動で解決してくれます

class Acme
{
    public $acme;

    /** @var \stdClass  */
    protected $class;

    /**
     * @param \stdClass $class
     */
    public function __construct(\stdClass $class)
    {
        $this->class = $class;
    }
}

di

interfaceも使ってしまいましょう

namespace app\service;

interface AcmeInterface
{

} 

こんな感じで実装してみます

class Acme implements AcmeInterface
{
    public $acme;
}

class Nyaa implements AcmeInterface
{
    public $acme;
}

簡単に実装を入れ替える事が出来ます

$container->set('app\service\AcmeInterface', 'app\service\Acme');
$container->get('app\service\AcmeInterface');

$container->set('app\service\AcmeInterface', 'app\service\Nyaa');
$container->get('app\service\AcmeInterface');

もちろんsingletonもあります
componentsと組み合わせたり、実装にあわせて自由に開発する事が出来ます
マニュアルやソースコードを読んで触ってみましょう!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした