1

私はlaravel 4コンテナを研究して、laravelの内部についての知識を深め、より良いコードを書くスキルを向上させてきました。

しかし、私は 3 つの類似したコードを理解できていません。この質問をきれいに保つために、最小のスニペットを使用します。

同様の質問は、以下のリンクにあります。正解を答えてくださっている方もいらっしゃいますが、「使い方はわかっているけど、中身はわからない」だけでは満足できません。ですから、誰かがこれらすべてについて説明できることを本当に願っています。

質問 1 質問 2

<?php namespace Illuminate\Container; use Closure, ArrayAccess, ReflectionParameter;

class BindingResolutionException extends \Exception {}

class Container implements ArrayAccess {

    /**
     * Wrap a Closure such that it is shared.
     *
     * @param  Closure  $closure
     * @return Closure
     */
    public function share(Closure $closure)
    {
        return function($container) use ($closure)
        {
            // We'll simply declare a static variable within the Closures and if
            // it has not been set we'll execute the given Closure to resolve
            // the value and return it back to the consumers of the method.
            static $object;

            if (is_null($object))
            {
                $object = $closure($container);
            }

            return $object;
        };
    } 

}

share メソッドは、その関数の $container 変数が実際には Illuminate\Container のインスタンスであることをどのように認識しますか? その関数のスコープ内で定義されていません。次のユースケースの例でも定義されていません(とにかく役に立たないでしょう)

class AuthServiceProvider extends ServiceProvider{

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app['auth'] = $this->app->share(function($app)
        {
            // Once the authentication service has actually been requested by the developer
            // we will set a variable in the application indicating such. This helps us
            // know that we need to set any queued cookies in the after event later.
            $app['auth.loaded'] = true;

            return new AuthManager($app);
        });
    }

}

別の実装が期待されるので、ここに来ます

class MyContainer{

    public function share(Closure $closure)
    {
        $container = $this;

        return function() use ($closure, $container)
        {
            static $object;

            if(is_null($object))
            {
                $object = $closure($container);
            }

            return $object;
        };
    }

}

$closure = function($container)
{
    var_dump($container);
};

$container = new MyContainer();
call_user_func($container->share($closure));
//dumps an instance of MyContainer -> which is the wanted behaviour

$container = new Illuminate\Container\Container();
call_user_func($container->share($closure));
//Throws a warning AND a notice
//Warning: Missing argument 1 for Illuminate\Container\Container::Illuminate\Container\{closure}() in /Users/thomas/Sites/Troll/vendor/illuminate/container/Illuminate/Container/Container.php on line 128
//NOTICE: Notice: Undefined variable: container in /Users/thomas/Sites/Troll/vendor/illuminate/container/Illuminate/Container/Container.php on line 137
//and even worse the output of the var_dump is NULL

存在しないパラメーターをクロージャー引数として渡すという同じ実装を持つextendメソッドとbindメソッドを理解するのに同じ問題がありますが、それがコンテナインスタンス自体にどのように解決されるかを把握できませんか?

4

1 に答える 1

1

の戻り値Container::share()は、1 つの引数 (コンテナー自体) を取る関数です。外部から呼び出すには、次のようにする必要があります。

$closure = function ($container) {
    var_dump($container);
};

$container = new Illuminate\Container\Container();
call_user_func($container->share($closure), $container);

この理由は、サービス定義の仕組みによるものです。の使用目的はshare、サービス定義をラップすることです。

このような:

$container = new Illuminate\Container\Container();
$container['foo'] = $container->share(function ($container) { return new Foo(); });

サービスにアクセスすると、次のようになります。

var_dump($container['foo']);

値が呼び出し可能かどうかをチェックし、そうであれば関数として呼び出しを試みます。をオフにしておくと、毎回share新しいインスタンスが取得されます。Fooshareインスタンスを記憶し、毎回同じものを返します。

繰り返しになり$containerますが、返される関数の引数shareはそこにあります。これは、サービスの作成がそのように機能するためです。サービス定義 (コンテナーに「設定」する「ファクトリー」関数) は、コンテナーを受け取り、それが作成するサービスのインスタンスを返す単なる関数です。

定義が引数offsetGet()を取ることを期待しているので、それが返されます。$containershare

于 2013-08-12T15:14:20.690 に答える