Laravel如何在“ routes”目录中console.php文件内使用 $ this-> comment()方法,而 Artisan :: command()是静态方法?
<?php
use Illuminate\Foundation\Inspiring;
Artisan::command('inspire', function() {
$this->comment(Inspiring::(quote));
})->describe('Display an inspiring quote');
答案 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,这是您可以随心所欲插入的特质。它已经融入了一些已知的扩展候选工具集,例如Collections,Eloquent\Builder和Responses。