【问题标题】:How use Laravel Contextual Binding for Logger channels?如何为 Logger 通道使用 Laravel 上下文绑定?
【发布时间】:2021-06-26 13:38:59
【问题描述】:

在 Laravel 文档中,我看到了示例:

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

$this->app->when([VideoController::class, UploadController::class])
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('s3');
          });

https://laravel.com/docs/8.x/container#contextual-binding

我想在存储磁盘中使用不同的日志通道。

https://laravel.com/docs/8.x/logging#writing-to-specific-channels

我试试:

    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
$this->app->when(PhotoController::class)
          ->needs('log')
          ->give(function () {
              return \Log::channel('telegram');
          });

$this->app->when([VideoController::class, UploadController::class])
          ->needs('log')
          ->give(function () {
              return \Log::channel('slack');
          });

但我得到错误:

NOTICE: PHP message: PHP Fatal error:  Uncaught Error: Maximum function nesting level of '256' reached, aborting! in /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:792
 Stack trace:
 #0 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(646): Illuminate\Foundation\Application->resolve('Illuminate\\Log\\...')
 #1 /var/www/html/app/Providers/AppServiceProvider.php(106): Illuminate\Container\Container->get('Illuminate\\Log\\...')
 #2 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(805): App\Providers\AppServiceProvider->App\Providers\{closure}(Object(Illuminate\Foundation\Application), Array)
 #3 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(691): Illuminate\Container\Container->build(Object(Closure))
 #4 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(796): Illuminate\Container\Container->resolve('log', Array, true)
 #5 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(646):  in /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Application.php on line 792

我也试过了:

->needs(LoggerInterface::class)

同样的错误。

我没有在文档中看到如何正确执行此操作的示例。没什么。

【问题讨论】:

  • 我相信这是因为你不能注入一个接口,而是它必须是一个实现,例如存储你得到一个具有特定存储类型的具体实例,而日志它是一个接口系统无法解析。
  • return \Log::channel ('slack');这一行出现了递归循环,因为它调用容器来解析日志的日志。需要一些解决方法。
  • 也许先试试binding你的界面?

标签: php laravel dependency-injection contextual-binding


【解决方案1】:

旁注:您可以绑定到一个接口,这是一种常见的用法,Laravel 称它们为“合同”,请参阅https://laravel.com/docs/8.x/container#binding-interfaces-to-implementations。所以这不是这里的问题。

关于这个问题:我不太清楚我在做什么不同,但它对我来说是按预期工作的:

use Illuminate\Support\Facades\Log;
$this->app->when(SomeController::class)->needs('log')->give(function() {
    return Log::channel('mychannel');
});

但是,'log' 字符串我不太喜欢这里。我相信它指的是记录器的所谓“外观”的名称,这给它所指的内容带来了更多的认知过载。恕我直言,最好在这里使用完整的类名,更明确:

use Illuminate\Log\Logger;
use Illuminate\Support\Facades\Log;
$this->app->when(SomeController::class)->needs(Logger::class)->give(function() {
    return Log::channel('mychannel');
});

然后您可以在任何控制器中使用以下 sn-p:

public function __construct(Logger $logger) {
    $this->logger = $logger;
}

事实上,您有两个选择来定义何时/需要/给予:

  • Illuminate\Log\Logger::class
  • Psr\Log\LoggerInterface::class(上面的 Logger 实现了这个)

两者都有效,但在这两种情况下,您都需要在(要注入的)构造函数中使用与所写完全相同的类。您不能在控制器构造函数中绑定 LoggerInterface 和 typehint Logger 并期望它能够工作,它显然不能以这种方式识别继承。

要知道的另一件好事是,显然这只适用于构造函数。控制器方法也有依赖注入,但是结合上下文绑定不起作用。但是,它适用于此处定义的默认“简单”绑定https://laravel.com/docs/7.x/container#binding

public function showUser(Illuminate\Log\Logger $log) {
    // This typehint does not take contextual binding into account. You will receive
    // the default binding for this class.
    $log->info('...');
}

请参阅https://github.com/laravel/framework/issues/6177(tl;dr:问题已解决,未来将不支持控制器方法的上下文绑定)。

希望这些信息对您有所帮助。

【讨论】:

  • 如果使用Illuminate\Log\Logger::class,它可以工作,但如果使用Psr\Log\LoggerInterface::class,则不工作。很奇怪。
  • 如果你在 typehint 中使用同一个类,那么我不知道为什么它不起作用
猜你喜欢
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多