LoginSignup
4
5

More than 5 years have passed since last update.

Yii2 かんたんコンテナ

Last updated at Posted at 2014-12-12

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と組み合わせたり、実装にあわせて自由に開発する事が出来ます
マニュアルやソースコードを読んで触ってみましょう!

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5