自定义日志记录-CakePHP(1.3)


Customize logging - CakePHP (1.3)

我想扩展cakefp日志记录功能。使用

$this->log($msg, $level)

您可以将带有$level$msg记录到tmp/logs/$level.log中。

我想如何使用日志是:

  1. 不同级别的单独功能,例如$this->debug($msg)用于$this->log($msg, 'debug')$this->error($msg)用于$this->log($msg, 'error')等,用于日志记录
  2. 自动将类的名称放在消息前面,例如,如果$this的类型为"MyClass",则$this->debug($msg)将导致"MyClass:$msg"

我知道我可以通过扩展AppModel、AppController等来扩展功能,但由于我在应用程序中到处都需要这些功能,我宁愿扩展cakepp的Object,但没有找到稳定的机制(不想在cake/polder中更改它)。我想为这个功能实现一个新的类,但我不确定如何在cakepp中实现它。

你能给我一些提示吗?我可以在哪里/如何巧妙地实现这些扩展?

全局便利方法

好吧,你们真的不能在PHP中进行猴子补丁(至少5.2),这对那些在你们离开后必须维护代码的开发人员来说可能是一件好事。:)

CakePHP是一个具有严格约定的MVC框架,它只允许您独立地扩展所需的部分(如AppModelAppController等),并在核心中保持面向对象的基础不变(因此很难添加"可以在任何地方使用"的代码以防潜在的误用),从而使您很难打破MVC范式。

至于添加超越所有MVC分离的功能,app/config/bootstrap.php就是它的用武之地。当你把代码放在这里时,很明显它不是框架的一部分(这是非常正确的),但允许你在CakePHP加载之前添加这些基本内容。这里的一些选项可能是:

  1. 创建一个函数(例如,一些自定义函数,如error(),以您喜欢的方式调用CakeLog::write()。)
  2. 加载一个类(例如,加载您自己的日志记录类,名为..Log,这样您就可以在某些地方调用Log::error()
  3. 请参见以下内容:

记录器API

Cake确实允许对记录器之类的东西进行许多定制,但不幸的是,在这种情况下,向我们展示的API已经在核心中定义了。登录CakePHP的API如下,您可以在任何您喜欢的地方使用任何一种方法(好吧,前者仅在类中):

$this->log($msg, $level) // any class extending `Object` inherits this
// or
CakeLog::write($level, $message); // this is actually what is called by the above

您试图消除的任意$level参数实际上是一个非常强大的功能:

$this->log('Cannot connect to SMTP server', 'email'); // logs to app/logs/email.log
// vs
$this->email('Cannot connect to SMTP server'); // ambiguous - does this send emails?

我们刚刚创建了一个全新的日志类型,而没有编写额外的代码行,我们的代码的意图非常清楚

自定义记录器

核心开发人员有先见之明,添加了一个条件,允许我们完全替换记录器类(如果我们希望的话):

function log($msg, $type = LOG_ERROR) {
    if (!class_exists('CakeLog')) { // winning
        require LIBS . 'cake_log.php';
    }
    // ...

正如你所看到的,核心CakeLog类只有在不存在这样的类的情况下才会被实例化,这让你有机会插入你自己创建的东西(或者一个经过一些调整的精确副本——尽管你想在升级时手动与核心同步更改):

// app/config/bootstrap.php
App::import('Lib', 'CakeLog'); // copy cake/libs/cake_log.php to app/lib/cake_log.php

以上内容将使您能够完全控制应用程序中CakeLog类的实现,因此您可以执行一些操作,例如将调用类名动态添加到日志消息中。然而,更直接的方法(以及其他类型的日志记录,例如对数据库的日志记录)是创建一个自定义日志流:

CakeLog::config('file', array(
    'engine' => 'FileLog', // copy cake/libs/log/file_log.php to app/libs/log/file_log.php
));

TL;DR-尽管您可以在CakePHP启动之前加载自己的代码,或者在提供的每个MVC层中单独使用,但您不应该篡改核心提供的对象层次结构。这使得添加全局继承的类方法变得困难。

我的建议是:使用给你的API,集中精力添加更多的功能,而不是语法上的微妙。:)

除了deizel所说的(顺便说一句,deizel写得很好),你不必使用Cake的记录器。欢迎您使用任何您想要的日志记录系统。选择一个你喜欢的现有日志框架可能是最安全的选择。bootstrap.php是进行任何require调用或初始化的好地方。

否则,如果你想在Cake中做一些事情,我建议你创建一个包含三个日志接口的插件:组件、行为和助手。这样,日志记录功能将在您的模型、视图和控制器中可用。至于如何编码,我喜欢将cake类作为真实日志类的瘦代理,并在代理中使用神奇的方法__call()来解析日志请求和环境,然后将这些信息转发给记录器以统一处理。

您可以编写类似$this->MyLogger->oops("stubbed my toe")的内容,并可能有一个oops.log文件,其中包含您的消息和您希望包含的任何附加信息(呼叫控制器/视图/型号、时间和日期等)。