私はlaravel 4コンテナを研究して、laravelの内部についての知識を深め、より良いコードを書くスキルを向上させてきました。
しかし、私は 3 つの類似したコードを理解できていません。この質問をきれいに保つために、最小のスニペットを使用します。
同様の質問は、以下のリンクにあります。正解を答えてくださっている方もいらっしゃいますが、「使い方はわかっているけど、中身はわからない」だけでは満足できません。ですから、誰かがこれらすべてについて説明できることを本当に願っています。
<?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メソッドを理解するのに同じ問題がありますが、それがコンテナインスタンス自体にどのように解決されるかを把握できませんか?