Laravel 集成的 Monolog 库对日志进行配置和记录实例

 更新时间:2016年11月25日 15:32  点击:1594
本文章为各位介绍一篇关于Laravel 集成的 Monolog 库对日志进行配置和记录的实例,具体的如下希望对各位吸帮助。

对于大型系统而言,日志是不可或缺的模块,Laravel自然也对日志提供了完善的支持。目前Laravel集成了强大的Monolog库进行日志记录。下面我们就来大致看一下Laravel中如何对日志进行配置以及日志的简单使用。

1、日志处理器配置

首先我们来看日志处理器的配置。Laravel目前支持四种日志处理器:

single —— 将日志记录到单个文件中。该日志处理器对应Monolog的StreamHandler。
daily —— 以日期为单位将日志进行归档,每天创建一个新的日志文件记录日志。该日志处理器 对应Monolog的RotatingFileHandler。
syslog —— 将日志记录到syslog中。该日志处理器 对应Monolog的SyslogHandler。
errorlog —— 将日志记录到PHP的error_log中。该日志处理器 对应Monolog的ErrorLogHandler。

项目实际日志处理器通过config/app.php中的log配置项决定,默认配置值为single。这里我们使用默认值,不做修改:

'log' => 'single',

当然如果这四种方式满足不了你的需求,还可以使用configureMonologUsing方法完全控制Monolog的日志处理器:

$app->configureMonologUsing(function($monolog) {
    $monolog->pushHandler(...);
});

注:必须将上述这段代码置于bootstrap/app.php文件返回$app之前处才能生效。
2、使用Log记录日志
配置完成后,就可以在代码中使用Log门面来记录日志,Log门面背后实际上是Illuminate\Log\Writer,而在Writer的构造函数中注入了Monolog\Logger。生成的日志文件存放在storage/logs目录下。

目前,Log门面支持八种日志级别(使用RFC 5424标准):

Log::emergency($error);     //紧急状况,比如系统挂掉
Log::alert($error);     //需要立即采取行动的问题,比如整站宕掉,数据库异常等,这种状况应该通过短信提醒
Log::critical($error);     //严重问题,比如:应用组件无效,意料之外的异常
Log::error($error);     //运行时错误,不需要立即处理但需要被记录和监控
Log::warning($error);    //警告但不是错误,比如使用了被废弃的API
Log::notice($error);     //普通但值得注意的事件
Log::info($error);     //感兴趣的事件,比如登录、退出
Log::debug($error);     //详细的调试信息

下面我们就来分别演示下这几种日志级别的日志记录,我们将在TestController的log方法中进行测试:

public function log(){
    Log::emergency("系统挂掉了");
    Log::alert("数据库访问异常");
    Log::critical("系统出现未知错误");
    Log::error("指定变量不存在");
    Log::warning("该方法已经被废弃");
    Log::notice("用户在异地登录");
    Log::info("用户xxx登录成功");
    Log::debug("调试信息");
}
在浏览器中访问http://laravel.app:8000/test/log,对应在storage/logs/laravel.log记录的日志信息如下:

[2015-11-09 14:24:05] local.EMERGENCY: 系统挂掉了
[2015-11-09 14:24:05] local.ALERT: 数据库访问异常
[2015-11-09 14:24:05] local.CRITICAL: 系统出现未知错误
[2015-11-09 14:24:05] local.ERROR: 指定变量不存在
[2015-11-09 14:24:05] local.WARNING: 该方法已经被废弃
[2015-11-09 14:24:05] local.NOTICE: 用户在异地登录
[2015-11-09 14:24:05] local.INFO: 用户xxx登录成功
[2015-11-09 14:24:05] local.DEBUG: 调试信息

可见对应的日志记录包含了日志记录时间、日志级别和日志消息等信息。当然我们也可以在记录日志时传递上下文信息:

Log::info("用户xxx登录成功",['user_id'=>1]);
对应的日志记录为:

[2015-11-09 14:25:47] local.INFO: 用户xxx登录成功 {"user_id":1}

如果要访问底层Monolog的实例可以使用如下方法:

$monolog = Log::getMonolog();
dd($monolog);

我们可以在浏览器页面中查看当前Monolog对象实例的属性信息:

Laravel Monolog 对象实例

我们可以从中看出当前使用的日志处理器,日志记录的位置,日志记录的格式等信息。

下文我们来看一篇关于Laravel 5.1中定义事件、事件监听器以及触发事件例子,希望能够帮助到各位新手朋友的哦。

这里我们基于之前基于模型+缓存对文章增删改查这篇文件对文章保存后缓存的处理做进一步优化。我们将文章保存(新建/修改)视为一个事件,将保存文章内容到缓存放到监听器中实现:

1、注册事件-监听器

首先我们需要在EventServiceProvider中注册事件与监听器之间的映射关系:

 代码如下 复制代码

protected $listen = [
    'App\Events\PostSaved'=>[
        'App\Listeners\SaveDataToCache'
    ]
];

然后我们在项目根目录运行如下Artisan命令:

php artisan event:generate

该命令会在app/Events目录下生成PostSaved.php,在app/Listeners目录下生成SaveDataToCache.php。

2、定义事件类

接下来我们编辑事件类PostSaved如下:

 代码如下 复制代码

<?php

namespace App\Events;

use App\Events\Event;
use App\Models\Post;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class PostSaved extends Event
{
    use SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return [];
    }
}

我们在构造函数中注入一个Post实例传递给PostSaved。

3、定义监听器类

然后我们来定义监听器类SaveDataToCache,监听器类中使用handle方法接收事件实例并执行响应该事件的业务逻辑,这里就是将就接收到的Post实例保存到缓存中:

 代码如下 复制代码

<?php

namespace App\Listeners;

use App\Events\PostSaved;
use Cache;
use Log;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SaveDataToCache
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param PostSaved $event
     * @return void
     */
    public function handle(PostSaved $event)
    {
        $post = $event->post;
        $key = 'post_'.$post->id;
        Cache::put($key,$post,60*24*7);
        Log::info('保存文章到缓存成功!',['id'=>$post->id,'title'=>$post->title]);
    }
}

业务逻辑很简单:从注入的PostSaved中获取文章实例并将其保存到缓存,并将该操作记录到日志。

4、触发事件

最后我们来测试文章保存事件及其监听器。

要触发文章保存事件,可以使用Event门面提供的fire方法,在PostController中修改store方法如下:

 代码如下 复制代码

public function store(Request $request)
{
    $title = $request->input('title');
    $content = $request->input('content');

    $post = new Post;
    $post->title = $title;
    $post->content = $content;
    $post->save();

    Event::fire(new PostSaved($post));

    return redirect()->route('post.show',['post'=>$post]);
}

然后修改update方法如下:

 代码如下 复制代码

public function update(Request $request, $id)
{
    $post = Post::find($id);
    if(!$post)
        exit('指定文章不存在!');

    $title = $request->input('title');
    $content = $request->input('content');

    $post->title = $title;
    $post->content = $content;
    $post->save();

    Event::fire(new PostSaved($post));

    return redirect()->route('post.show',['post'=>$post]);
}

在浏览器中访问http://laravel.app:8000/post/create,填写标题和文章内容:

Laravel测试文章保存事件

点击提交页面跳转到文章详情页,此时去查看日志storage/logs/laravel.log,可以看到对应日志记录:

[2015-11-10 23:14:12] local.INFO: 保存文章到缓存成功! {"id":13,"title":"Test Event Add"}
说明已触发文章保存事件,监听器监听到事件后将其保存到缓存中并记录日志。

Laravel 5.1有自己的文件系统了我们可以直接使用Laravel 5.1文件系统来对文件的操作了,下面来看一篇对文件操作,移动,存储及删除的例子。

Laravel 基于 Flysystem 提供了强大的文件系统对文件进行存储和删除,该文件系统和缓存一样,支持多种驱动,这些驱动包括本地驱动、FTP、Amazon S3以及 Rackspace,在这些驱动之上提供了统一的API方便随时切换驱动而不需要修改任何业务逻辑代码。

既然API方法一致,那么这里作为示例,我们使用本地驱动来演示如何使用文件系统API对文件进行存储和删除。

1、配置

文件系统配置位于config/filesystems.php,默认配置如下:

 代码如下 复制代码

return [

    'default' => 'local',
    'cloud' => 's3',
    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        'ftp' => [
            'driver' => 'ftp',
            'host' => 'ftp.example.com',
            'username' => 'your-username',
            'password' => 'your-password',
        ],

        's3' => [
            'driver' => 's3',
            'key' => 'your-key',
            'secret' => 'your-secret',
            'region' => 'your-region',
            'bucket' => 'your-bucket',
        ],

        'rackspace' => [
            'driver' => 'rackspace',
            'username' => 'your-username',
            'key' => 'your-key',
            'container' => 'your-container',
            'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/',
            'region' => 'IAD',
            'url_type' => 'publicURL',
        ],

    ],

];

从配置文件可以看出,Laravel默认的文件系统驱动是local,也就是本地驱动,默认的云存储是Amazon S3。我们可以修改这些默认配置。

所有支持的驱动及驱动详细配置定义在disks配置项中,在local驱动中使用root配置指定文件系统的根路径,即storage/app,这意味着如果使用local驱动,所有文件都会存放在该目录下。如果使用ftp驱动需要指定FTP主机、用户名和登录密码,此外还有一些额外配置,比如端口号、超时时间、加密方式等。同理使用s3或者rackspace也要填写相应的配置项。

由于我们使用local驱动,所以这里我们保持该配置文件不变即可。

2、基本使用

下面我们使用文件系统演示如何上传文件、获取文件、以及删除文件,我们将使用Storage门面提供的方法进行操作。

上传文件/获取文件

这里我们基于 HTTP 请求实例教程#上传文件这篇教程并对其上传方法postFileupload进行修改:

 代码如下 复制代码

public function postFileupload(Request $request){
    //判断请求中是否包含name=file的上传文件
    if(!$request->hasFile('file')){
        exit('上传文件为空!');
    }
    $file = $request->file('file');
    //判断文件上传过程中是否出错
    if(!$file->isValid()){
        exit('文件上传出错!');
    }
    $newFileName = md5(time().rand(0,10000)).'.'.$file->getClientOriginalExtension();
    $savePath = 'test/'.$newFileName;
    $bytes = Storage::put(
        $savePath,
        file_get_contents($file->getRealPath())
    );
    if(!Storage::exists($savePath)){
        exit('保存文件失败!');
    }
    header("Content-Type: ".Storage::mimeType($savePath));
    echo Storage::get($savePath);
}

在上传处理逻辑中我们先保存文件到指定位置,然后判断保存后的文件是否存在,如果不存在则表明上传失败,否则显示上传文件内容。

比如我们测试上传图片,访问http://laravel.app:8000/request/fileupload,点击“选择文件”上传一张图片

本文章为各位介绍一篇关于PHP设计模式之Repository资源库模式学习笔记了,希望这篇文章可以为各位带来帮助,具体如下。

1、模式定义

Repository 是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository 是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

Repository 模式是架构模式,在设计架构时,才有参考价值。应用 Repository 模式所带来的好处,远高于实现这个模式所增加的代码。只要项目分层,都应当使用这个模式。

2、UML类图

Respository-Design-Pattern-Uml

3、示例代码

Post.php

<?php

namespace DesignPatterns\More\Repository;

/**
 * Post 类
 * @package DesignPatterns\Repository
 */
class Post
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $title;

    /**
     * @var string
     */
    private $text;

    /**
     * @var string
     */
    private $author;

    /**
     * @var \DateTime
     */
    private $created;

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param string $author
     */
    public function setAuthor($author)
    {
        $this->author = $author;
    }

    /**
     * @return string
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * @param \DateTime $created
     */
    public function setCreated($created)
    {
        $this->created = $created;
    }

    /**
     * @return \DateTime
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * @param string $text
     */
    public function setText($text)
    {
        $this->text = $text;
    }

    /**
     * @return string
     */
    public function getText()
    {
        return $this->text;
    }

    /**
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }
}
PostRepository.php

<?php

namespace DesignPatterns\More\Repository;

use DesignPatterns\More\Repository\Storage;

/**
 * Post 对应的 Repository
 * 该类介于数据实体层(Post) 和访问对象层(Storage)之间
 *
 * Repository 封装了持久化对象到数据存储器以及在展示层显示面向对象的视图操作
 *
 * Repository 还实现了领域层和数据映射层的分离和单向依赖
 *
 * PostRepository 类
 * @package DesignPatterns\Repository
 */
class PostRepository
{
    private $persistence;

    public function __construct(Storage $persistence)
    {
        $this->persistence = $persistence;
    }

    /**
     * 通过指定id返回Post对象
     *
     * @param int $id
     * @return Post|null
     */
    public function getById($id)
    {
        $arrayData = $this->persistence->retrieve($id);
        if (is_null($arrayData)) {
            return null;
        }

        $post = new Post();
        $post->setId($arrayData['id']);
        $post->setAuthor($arrayData['author']);
        $post->setCreated($arrayData['created']);
        $post->setText($arrayData['text']);
        $post->setTitle($arrayData['title']);

        return $post;
    }

    /**
     * 保存指定对象并返回
     *
     * @param Post $post
     * @return Post
     */
    public function save(Post $post)
    {
        $id = $this->persistence->persist(array(
            'author' => $post->getAuthor(),
            'created' => $post->getCreated(),
            'text' => $post->getText(),
            'title' => $post->getTitle()
        ));

        $post->setId($id);
        return $post;
    }

    /**
     * 删除指定的 Post 对象
     *
     * @param Post $post
     * @return bool
     */
    public function delete(Post $post)
    {
        return $this->persistence->delete($post->getId());
    }
}
Storage.php

<?php

namespace DesignPatterns\More\Repository;

/**
 * Storage接口
 *
 * 该接口定义了访问数据存储器的方法
 * 具体的实现可以是多样化的,比如内存、关系型数据库、NoSQL数据库等等
 *
 * @package DesignPatterns\Repository
 */
interface Storage
{
    /**
     * 持久化数据方法
     * 返回新创建的对象ID
     *
     * @param array() $data
     * @return int
     */
    public function persist($data);

    /**
     * 通过指定id返回数据
     * 如果为空返回null
     *
     * @param int $id
     * @return array|null
     */
    public function retrieve($id);

    /**
     * 通过指定id删除数据
     * 如果数据不存在返回false,否则如果删除成功返回true
     *
     * @param int $id
     * @return bool
     */
    public function delete($id);
}

MemoryStorage.php

<?php

namespace DesignPatterns\More\Repository;

use DesignPatterns\More\Repository\Storage;

/**
 * MemoryStorage类
 * @package DesignPatterns\Repository
 */
class MemoryStorage implements Storage
{

    private $data;
    private $lastId;

    public function __construct()
    {
        $this->data = array();
        $this->lastId = 0;
    }

    /**
     * {@inheritdoc}
     */
    public function persist($data)
    {
        $this->data[++$this->lastId] = $data;
        return $this->lastId;
    }

    /**
     * {@inheritdoc}
     */
    public function retrieve($id)
    {
        return isset($this->data[$id]) ? $this->data[$id] : null;
    }

    /**
     * {@inheritdoc}
     */
    public function delete($id)
    {
        if (!isset($this->data[$id])) {
            return false;
        }

        $this->data[$id] = null;
        unset($this->data[$id]);

        return true;
    }
}

[!--infotagslink--]

相关文章

  • Laravel4安装配置的方法

    如果我们需要安培Laravel4的话最php最低要求要在php5.3.7版本并且我们需要把mcrypt与openss这两个扩展开启才可以,具体步骤我们参考下文。 前面我们介绍我了 com...2016-11-25
  • Laravel 调试工具 laravel-debugbar 打印日志消息

    laravel-debugbar 调试工具的教程小编整理了几篇不错的教程,今天我们来看一篇Laravel 调试工具 laravel-debugbar 打印日志消息例子,希望文章对各位有帮助。 其实不...2016-11-25
  • Laravel 5.1中定义事件、事件监听器以及触发事件例子

    下文我们来看一篇关于Laravel 5.1中定义事件、事件监听器以及触发事件例子,希望能够帮助到各位新手朋友的哦。 这里我们基于之前基于模型+缓存对文章增删改查这篇...2016-11-25
  • Powershell 查询 Windows 日志的方法

    这篇文章主要介绍了Powershell 查询 Windows 日志的方法,需要的朋友可以参考下...2020-06-30
  • 对MySQL日志操作的一些基本命令总结

    MySQL日志主要包含:错误日志、查询日志、慢查询日志、事务日志、二进制日志;日志是mysql数据库的重要组成部分。日志文件中记录着mysql数据库运行期间发生的变化;也就是说用来记录mysql数据库的客户端连接状况、SQL语句...2015-11-24
  • C#实现线程安全的简易日志记录方法

    这篇文章主要介绍了C#实现线程安全的简易日志记录方法,比较实用的功能,需要的朋友可以参考下...2020-06-25
  • 搭建php Laravel框架教程详解

    Laravel框架我们用到的不多了,但如果使用需要搭配了,下面我们来看一篇关于搭建php Laravel框架教程详解,具体的操作细节如下所示,希望对各位有帮助。 一、安装 Compos...2016-11-25
  • c# 用Dictionary实现日志数据批量插入

    这篇文章主要介绍了c# 用Dictionary实现日志数据批量插入的步骤,帮助大家更好的理解和使用c#中的Dictionary类,感兴趣的朋友可以了解下...2021-02-01
  • C#3.0使用EventLog类写Windows事件日志的方法

    这篇文章主要介绍了C#3.0使用EventLog类写Windows事件日志的方法,以简单实例形式分析了C#写windows事件日志的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • Java SSM框架如何添加写日志功能

    这篇文章主要介绍了Java SSM框架如何添加写日志功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-25
  • c#快速写本地日志方法

    下面小编就为大家分享一篇c#快速写本地日志方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-06-25
  • sql server日志处理不当造成的隐患详解

    这篇文章主要给大家介绍了关于sql server日志处理不当造成的隐患的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用sql server具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-07-11
  • Nginx访问日志及错误日志参数说明

    这篇文章主要介绍了Nginx访问日志及错误日志参数说明,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-14
  • springboot启动时没有日志的原因分析

    这篇文章主要介绍了springboot启动时没有日志的原因分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-27
  • C#写日志类实例

    这篇文章主要介绍了C#写日志类,实现将日志信息写入文本文件的功能,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • 如何用Laravel包含你自己的帮助函数

    你可能想创建一个在应用的任何地方都可以访问的函数,这个篇文章将带你解决此问题,感兴趣的同学,可以参考下。...2021-05-27
  • Nginx自定义访问日志的配置方式

    Nginx日志主要分为两种:访问日志和错误日志。访问日志主要记录客户端访问Nginx的每一个请求,格式可以自定义。下面这篇文章主要给大家介绍了Nginx自定义访问日志的配置方式,需要的朋友可以参考学习,下面来一起看看吧。...2017-07-06
  • 使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)

    最近接了个项目需要开发一个app项目,由于是第一次接触这种app开发,经过一番思考,决定使用Vue3+Vant前端组件的模式进行开发,下面把问题分析及实现代码分享给大家,需要的朋友参考下吧...2021-06-10
  • Laravel Nginx配置步骤详解

    Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁...2016-11-25
  • php性能分析之php-fpm慢执行日志slow log用法浅析

    这篇文章主要介绍了php性能分析之php-fpm慢执行日志slow log用法,结合实例形式分析了php慢执行日志的功能与相关使用技巧,需要的朋友可以参考下...2016-10-20