Laravel如何在静态方法中使用$ this上下文?

时间:2018-10-02 14:16:19

标签: php laravel oop laravel-5 static-methods

Laravel如何在“ routes”目录中console.php文件内使用 $ this-> comment()方法,而 Artisan :: command()是静态方法?

enter image description here

<?php

use Illuminate\Foundation\Inspiring;

Artisan::command('inspire', function() {
    $this->comment(Inspiring::(quote));
})->describe('Display an inspiring quote');

2 个答案:

答案 0 :(得分:11)

$this不在静态方法本身内部使用,而是在传递给该方法的闭包中使用。 From the Laravel manual

  

闭包绑定到基础命令实例,因此您可以完全访问通常可以在完整命令类上访问的所有帮助方法。

因此,$this在此上下文中是Command实例。这是使用PHP的bindTo方法实现的,该方法允许您指定任何给定闭包的范围。


这种方法并非Artisan命令专有。通常,我们将此功能称为Facades

  

外观为应用程序的service container中可用的类提供了“静态”接口。 Laravel附带了许多外墙,可以访问Laravel的几乎所有功能。 Laravel外观作为服务容器中基础类的“静态代理”,提供了简洁,表达性强的语法的优点,同时保持了比传统静态方法更高的可测试性和灵活性。

还有很多其他外观,它们都可以静态访问位于服务容器中的实例。一些更常见的外观和方法是:

  • Cache::get('key')Cache::set('key', 'value')
  • Request::input('some_field')Request::only('some_field')
  • Log::info('be aware of this...')
  • ...

答案 1 :(得分:2)

Laravel非常自由地使用magic methods。当您执行类似Artisan::command()的操作时,没有实际的public static function command()定义。因此,php而是查看是否定义了__callStatic()方法,作为未定义方法的统称。因此,在Artisan门面中的某处,您可能会发现一些具有以下效果的东西:

public static function __callStatic($name, array $args = [])
{
    $newObj = new static();
    if (method_exists($newObj, $name)) {
        return $newObj->$name(...$args);
    }
}

这里的另一个棘手的事情是,您返回的对象很可能没有像上面的示例中那样被新实例化。其中大多数遵循Singleton Pattern,这意味着您不仅要静态地调用非静态方法,而且每次都针对目标对象的 same 实例调用它。

$newObj = new static();

看起来会更像

self::$preexistingObject = self::$preexistingObject ?: new static();
$newObj = self::$preexistingObject;

大多数这种魔术发生在服务提供商“启动”时。在配置文件中的某个地方,Laravel被告知要与该“ Artisan” Facade关联的根类。它会创建该类的新实例,并在该会话期间将其保留并重用。

最后,为了更直接地回答您的问题并详细说明Iainn的答案,这是我第一次发现时就大为震惊,但是原生Php实际上支持更改匿名函数中实际上指向哪个对象$this。您只需调用$closure->bindTo($newObject),就好像Closure是它本身,而object和bindTo()是一个方法一样。 (据我所知,实际上,Php可能并没有太大的区别。)

您也可以用它来做一些很酷的事情。您可以将您的类设置为接收闭包,将其重新绑定到其自己的作用域而不是调用者的作用域,将其保留在静态关联数组中,并在以后通过访问它。 Magic __call()方法。结果基本上是method-overloading;将自定义算法注入帮助程序类以供以后在declarative上下文中使用的机会。

Laravel提供了可以做到这一点的工具。 Macros,这是您可以随心所欲插入的特质。它已经融入了一些已知的扩展候选工具集,例如CollectionsEloquent\BuilderResponses