[英]Laravel 5 - How to use $this->app->when()
Reading about laravel bindings ,I understand $this->app->bind
, $this->app->singleton
and $this->app->instance
because they are almost the same.阅读有关 laravel绑定的信息,我了解
$this->app->bind
、 $this->app->singleton
和$this->app->instance
因为它们几乎相同。
But $this->app->when
is a little bit tricky for me.但是
$this->app->when
对我来说有点棘手。
In laravel example在 laravel 示例中
$this->app->when('App\Http\Controllers\UserController')
->needs('$variableName')
->give($value);
In my understanding it injects some primitive value and the App\Http\Controllers\UserController
is the alias of the object that will be binded.But where is the object?据我了解,它注入了一些原始值,而
App\Http\Controllers\UserController
是将要绑定的对象的别名。但是对象在哪里?
Can anyone explain?谁能解释一下? Thank you for your help.
谢谢您的帮助。
Contextual binding does not work on variable names, but on types.上下文绑定不适用于变量名,但适用于类型。 It is used to provide different implementations for interfaces to consuming classes or functions, depending on the context.
它用于根据上下文为使用类或函数的接口提供不同的实现。 In fact, you can actually read the method calls and it does exactly what you'd expect.
事实上,您实际上可以阅读方法调用,并且它完全符合您的预期。 To elaborate on this, I'll take the example of the documentation and adapt it slightly:
为了详细说明这一点,我将以文档为例并稍作修改:
$this->app->when(Worker::class)
->needs(Money::class)
->give(function () {
return new Dollar();
});
$this->app->when(Boss::class)
->needs(Money::class)
->give(function () {
return new Cheque();
});
In this example, Money
is an interface and Dollar
as well as Cheque
are implementations of the interface.在此示例中,
Money
是一个接口, Dollar
和Cheque
是该接口的实现。 The example literally means that if you typehint Money
on a Worker
class, it will resolve to an instance of Dollar
while it will resolve to Cheque
on a Boss
class.该示例的字面意思是,如果您在
Worker
类上输入Money
,它将解析为Dollar
的实例,而它将解析为Boss
类的Cheque
。 To illustrate, here the implementations and the results:为了说明,这里的实现和结果:
interface Money
{
public function getAmount();
}
class Dollar implements Money
{
public function getAmount()
{
return 1;
}
}
class Cheque implements Money
{
public function getAmount()
{
return 100000;
}
}
And now we typehint the Money
interface to see what we'll get:现在我们输入
Money
界面,看看我们会得到什么:
class Worker
{
public function __construct(Money $money)
{
echo $money->getAmount(); // prints '1'
}
}
class Boss
{
public function __construct(Money $money)
{
echo $money->getAmount(); // prints '100000'
}
}
It means that if a class of UserController
is instantiated and it needs a variable with the name $variableName
Larvel will automatically resolve this variable with the given value and you don't have to provide it.这意味着如果一个
UserController
类被实例化并且它需要一个名为$variableName
的变量,Larvel 将自动使用给定的值解析这个变量,您不必提供它。
For example:例如:
$value = "Sven"
$this->app->when('App\Http\Controllers\UserController')
->needs('$userName')
->give($value);
This would insert the value 'Sven' into the UserController whenever it needs the variable with the name $userName
这将在需要名称
$userName
的变量时将值“Sven”插入 UserController
In other words, if you had a function like public function __construct(Request $request)
Laravel knows what to insert because it knows that a Request
object is expected.换句话说,如果你有一个像
public function __construct(Request $request)
这样的函数,Laravel 知道要插入什么,因为它知道需要一个Request
对象。 When you use a function like public function __construct($name)
Laravel has no clue what to insert here, essentially you tell Laravel how to resolve this variable with the bindings.当您使用诸如
public function __construct($name)
之类的函数时,Laravel 不知道在此处插入什么,本质上是您告诉 Laravel 如何使用绑定解析此变量。
This is an example of primitive binding , for Contextual binding see the answer of @Namoshek这是原始绑定的示例,对于上下文绑定,请参阅@Namoshek 的答案
In case anyone finds this thread, trying to achieve contextual binding on an app()->make() or similar situation:如果有人发现这个线程,试图在 app()->make() 或类似情况下实现上下文绑定:
use Closure;
use Illuminate\Container\Container;
class FooBar {
public function doSomething(): void
{
//...do your thing
$this->getFooObject();
}
private function getFooObject(): FooAbstract
{
$class = FooAbstract::class;
$buildStack = static::class;
app()->beforeResolving(
$class,
Closure::bind(
function () use ($buildStack) {
$this->buildStack[] = $buildStack;
},
app(),
Container::class,
)
);
return app($class);
}
}
In the above example laravel's app container is bind as $this
to this closure.在上面的例子中,laravel 的 app 容器作为
$this
绑定到这个闭包。 Since the buildStack
property, that's used to identify the object that "needs" the object that is being created, is protected, we have access to it, and we can add the classname to the stack.由于用于标识“需要”正在创建的对象的对象的
buildStack
属性受到保护,因此我们可以访问它,并且可以将类名添加到堆栈中。
for example: if $buildStack = Bar::class
;例如:如果
$buildStack = Bar::class
; you can do the following您可以执行以下操作
app()->when(FooBar::class)->needs(FooAbstract::class)->give(FooImplementation::class);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.