【问题标题】:Extending Laravel core logging扩展 Laravel 核心日志记录
【发布时间】:2013-12-29 11:23:24
【问题描述】:

我又遇到了更多 Laravel 问题,因为我在理解事物时遇到了问题。

我再次尝试创建一个包来进行我自己的日志记录。在做了一些额外的阅读和阅读核心代码并尝试了其他方法之后,我得出的结论是,我需要做的就是扩展 laravel 日志记录的核心功能,以便它使用 a 记录到不同的路径自定义格式化程序。

我已经创建了我的包。这是我的服务提供者类:

use Illuminate\Log\LogServiceProvider;

class VmlogServiceProvider extends LogServiceProvider {


    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot()
    {
        App::bind('log', function()
        {
            return new Vm\Vmlog\Vmlog;
        });     
        parent::boot();

    }

}

?>

这是 VmLog 类

<?php namespace Vm\Vmlog;

use App;
use Illuminate\Support\ServiceProvider;
use Log;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;

class Vmlog extends \Illuminate\Log\Writer {


    protected $path;
    protected $formatter;
    protected $stream;
    protected $rotatingStream;

    public function __construct() {

        $output = APP_HOST."|%datetime%|%level%|%level_name%|".__METHOD__."|%message%|%context%".PHP_EOL;
        $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
        $this->formatter = new LineFormatter($output, $dateFormat);

        parent::__construct();
    }

    /**
     * Register a file log handler.
     *
     * @param  string  $path
     * @param  string  $level
     * @return void
     */
    public function useFiles($path, $level = 'debug')
    {
        $level = $this->parseLevel($level);

        $this->stream = new StreamHandler($this->path, $level);
        $this->stream->setFormatter($this->formatter);

        $this->monolog->pushHandler($this->stream);
    }

    /**
     * Register a daily file log handler.
     *
     * @param  string  $path
     * @param  int     $days
     * @param  string  $level
     * @return void
     */
    public function useDailyFiles($path, $days = 0, $level = 'debug')
    {
        $level = $this->parseLevel($level);
        $this->rotatingStream = new RotatingFileHandler($this->path, $days, $level);
        $this->rotatingStream->setFormatter($this->formatter);

        $this->monolog->pushHandler($this->rotatingStream);
    }

}

?>

我已经在 app.php 中注释掉了 LogServiceProvider,并在我的 VmlogServiceProvider 中添加了它。

然而,当我尝试运行时,我收到以下错误。

调用未定义的方法 Illuminate\Support\Facades\Log::useDailyFiles()

我不明白为什么会这样。根据文档(我认为),我已经删除了核心 LogServiceProvider,我已经在其中添加了我自己的并正确绑定了它。我在这里做错了什么?

【问题讨论】:

  • 这是 Laravel 4.0 还是 4.1?
  • Laravel 4.0,但我认为我们需要切换,因为我们仍在开发基础项目。

标签: php laravel laravel-4


【解决方案1】:

为什么要在服务提供者中使用Boot方法?

替换 Laravel 的日志

您可能打算在该服务提供者中使用register 方法而不是boot 方法?

看起来您的实现将覆盖默认记录器,而不是创建额外的日志。这是你的意图吗?在这种情况下,请注意您已经使用boot 方法注册了一个“日志”实例,但随后register 方法正在重新完成这项工作。 (也许将其替换为默认值?我不确定会导致什么行为)。

附加日志

如果你想添加额外的日志,你可以这样做,而无需扩展 Laravel 的服务提供者。

在一个新文件和您自己的命名空间中,创建一个LogServiceProvider

<?php namespace Fideloper\Log;

use Illuminate\Support\ServiceProvider;

class LogServiceProvider extends ServiceProvider {

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $logger = new Writer(new \Monolog\Logger('my-custom-log'), $this->app['events']);

        $logFile = 'my-custom-log.txt';

        $logger->useDailyFiles(storage_path().'/logs/'.$logFile);

        $this->app->instance('fideloper.log', $logger);

        $this->app->bind('Fideloper\Log\Writer', function($app)
        {
            return $app->make('fideloper.log');
        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return array('fideloper.log');
    }

}

然后创建一个新的日志写入器(类似于您所做的):

<?php namespace Fideloper\Log;

use Illuminate\Log\Writer as BaseWriter;

class Writer extends BaseWriter {}

请注意,我没有向我的扩展编写器类添加任何额外功能,但我可以。

此设置的一个缺点是我没有创建或覆盖Log 外观来使用我的新记录器。任何对 Log::whatever() 的调用仍将转到 Laravel 的默认值。我创建了一个新的 Fideloper\Log\Writer 对象,因为 Laravel 能够自动提供类依赖项,所以它可以工作。

$log = App::make('fideloper.log');

// Or get auto-created by laravel by making it a dependency
//   in a controller, for example:
<?php

use Fideloper\Log\Writer

class SomeController extends BaseController {

    public function __construct(Writer $log)
    {
        $this->log = $log;

        //Later
        $this->log->error('SOME CUSTOM ERROR');
    }

}

【讨论】:

  • 我想创建一个替换记录器,而不是一个额外的记录器。我最终做对了,但你的答案非常接近。为了完整起见,我会添加我的。
【解决方案2】:

我已经整理好了,所以为了完整起见,我会提供答案。

我们基本上模仿了 LogServiceProvider 类,但是我们没有调用 Laravel Writer 类,而是调用了自己的 Vmlog 类,它只是扩展了 writer 类。这样,原始日志记录的所有功能都保持不变,我们只需覆盖我们需要的功能。还需要注释掉Laravel Log服务提供者的注册,将自己的一个放到app.php文件中。

这里是 ServiceProvider 类。

<?php namespace vm\Vmlog;

use Monolog\Logger;
use Illuminate\Log\LogServiceProvider;
use Illuminate\Support\ServiceProvider;

class VmlogServiceProvider extends LogServiceProvider {

    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot()
    {
        $this->package('vm/vmlog');
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $logger = new Vmlog(new Logger('log'), $this->app['events']);

        $this->app->instance('log', $logger);

        if (isset($this->app['log.setup']))
        {
            call_user_func($this->app['log.setup'], $logger);
        }
    }
}

?>

这是扩展 Writer 类的 Vmlog 类。

<?php namespace vm\Vmlog;

use Illuminate\Support\ServiceProvider;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
use Illuminate\Events\Dispatcher;
use Monolog\Logger as MonologLogger;


class Vmlog extends \Illuminate\Log\Writer {


    protected $path;
    protected $dateFormat;
    protected $output;

    public function __construct(MonologLogger $monolog, Dispatcher $dispatcher = null) 
    {
        // Do stuff
        $this->dateFormat = 'Y-m-d\TH:i:s';
        $this->output = "|%datetime%|%level%|%level_name%|%message%|%context%".PHP_EOL;

        parent::__construct($monolog, $dispatcher);
    }

    /**
     * Register a file log handler.
     *
     * @param  string  $path
     * @param  string  $level
     * @return void
     */
    public function useFiles($path, $level = 'debug')
    {
        $level = $this->parseLevel($level);
        $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
        $formatter = new LineFormatter(APP_HOST.$this->output, $this->dateFormat);
        $stream = new StreamHandler($this->path, $level);
        $stream->setFormatter($formatter);

        $this->monolog->pushHandler($stream);
    }

    /**
     * Register a daily file log handler.
     *
     * @param  string  $path
     * @param  int     $days
     * @param  string  $level
     * @return void
     */
    public function useDailyFiles($path, $days = 0, $level = 'debug')
    {
        $level = $this->parseLevel($level);
        $this->path = VM_LOGPATH.APP_VLCODE."/".APP_VLCODE."_".APP_INSTANCE.".log";
        $formatter = new LineFormatter(APP_HOST.$this->output, $this->dateFormat);
        $stream = new RotatingFileHandler($this->path, $days, $level);
        $stream->setFormatter($formatter);

        $this->monolog->pushHandler($stream);
    }

}

?>

我仍然需要这样做,以便在包的配置文件中配置日志路径,但这对于现在和这个答案来说都是可行的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-03
    • 2021-10-04
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多