简体   繁体   English

Laravel 5 - 如何使用 $this->app->when()

[英]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是一个接口, DollarCheque是该接口的实现。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM