【问题标题】:Customize logging - CakePHP (1.3)自定义日志记录 - CakePHP (1.3)
【发布时间】:2012-01-10 14:59:23
【问题描述】:

我想扩展 cakephp 日志功能。 使用

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

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

我想如何使用日志记录是:

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

我知道我可以通过扩展 AppModel、AppController 等来扩展功能,但由于我在应用程序中的任何地方都需要该功能,我宁愿需要扩展 cakephp 的对象 - 但没有找到稳定的机制(不要'不想在 cake/ 文件夹中更改它)。 我想为该功能实现一个新类,但我不确定如何在 cakephp 中实现它。

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

【问题讨论】:

    标签: php cakephp cakephp-1.3


    【解决方案1】:

    全局便捷方法

    嗯,在 PHP(至少 5.2)中你不能真正做到monkey patching,这对于在你离开后必须维护你的代码的开发人员来说可能是一件好事。 :)

    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 参数实际上是quite a powerful feature

    $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?
    

    我们刚刚创建了一个全新的日志类型,没有编写额外的代码行,很清楚我们代码的意图是什么。

    自定义记录器

    核心开发人员对add a condition 有远见,如果我们愿意,我们可以完全替换记录器类:

    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 类的实现,因此您可以执行一些操作,例如将调用类名称动态添加到日志消息中。但是,更直接的方式(以及其他类型的日志记录 - 例如数据库)是create a custom log stream

    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,感谢您提供的广泛见解,我从中学到了很多。将类名与日志消息一起使用仅有助于跟踪错误消息。你是对的,功能更重要,但我只是好奇,想扩展我对 cakephp 的了解 :)
    • 没问题。添加调用类名是个好主意。我会为此创建一个自定义日志流,这应该不会太难:github.com/cakephp/cakephp/blob/…
    【解决方案2】:

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

    否则,如果您想在 Cake 中做事,我建议您创建一个具有三个日志接口的插件:组件、行为和助手。这样,您的模型、视图和控制器中就可以使用日志记录功能。至于如何编写代码,我喜欢让蛋糕类精简代理到您的真实日志记录类的想法,并在您的代理中使用魔术方法__call() 来解析日志记录请求和环境,然后将该信息转发给您的记录器以统一处理。

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

    【讨论】:

    • 是的,当然。当您提到使用现有的日志框架时,它提出了一个有效的观点。您可以“在蛋糕中做事”,但最终会得到一个行为/组件/视图“三重奏”,可以只有(并且应该)通过将其打包为插件来重用。如果您可以找到现有的库并将其推入app/vendors(或app/libs,如果you wrote it),请不要重新发明轮子。或者,您对使用 magic __call() method 的建议(非常正确)实现了 OP 对简单地调用 $thing->fillInTheBlank($stuff) 的渴望。
    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-29
    • 2019-11-15
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    相关资源
    最近更新 更多