扩展Laravel岩心测井


Extending Laravel core logging

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

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

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

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,我在它的位置添加了自己的LogServiceProvider并根据文档正确绑定了它(我认为)。我在这里做错了什么?

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

替换Laravel的日志

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

看起来您的实现将覆盖默认记录器,而不是创建额外的日志。这是你的意图吗?在这种情况下,请注意,您已经使用了boot方法来注册"log"的实例,但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 facade来使用我的新记录器。对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');
    }
}

我已经设法将其全部排序,因此为了完整性起见,将提供答案。

我们基本上模仿LogServiceProvider类,但不是调用LaravelWriter类,而是调用自己的Vmlog类,这只是扩展了Writer类。这样,原始日志记录的所有功能都保持不变,我们只需覆盖我们需要的功能。您还需要注释掉Laravel日志服务提供商的注册,并将自己的注册放在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);
        }
    }
}
?>

下面是Vmlog类,它扩展了Writer类。

<?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);
    }
}
?>

我仍然需要在包的配置文件中配置日志路径,但现在和这个答案都可以。