久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

PHP - 在多個類中實現日志記錄機制

PHP - Implement logging mechanism to file in several classes(PHP - 在多個類中實現日志記錄機制)
本文介紹了PHP - 在多個類中實現日志記錄機制的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我想在 PHP 中實現日志記錄機制:

I would like to implement logging mechanism to file in PHP:

  1. 日志文件路徑將在配置文件 config.php 中
  2. 在幾個類中,我想將一些事件記錄到日志文件中

例如:

    Class A {

        public function f_A {
            log_to_file($message);
        }

    }

    Class B {

        public function f_B {
            log_to_file($message);
        }

    }

我將非常感謝您提供任何提示.我想實現一些簡單而優雅的解決方案.

I will be very grateful for any tips. I would like to implement some easy and elegant solution.

我正在考慮(謝謝你的回答),我想我會這樣做(也許,有一些錯誤,我是從頭開始寫的):

I was thinking about it (thank you for your answers) and I think I will do it this way (maybe, there are some errors, I was writing it from scratch):

interface Logger {
    public function log_message($message);
}

class LoggerFile implements Logger {
    private $log_file;

public function __construct($log_file) {
    $this->log_file = $log_file;
}
public function log_message($message) {
        if (is_string($message)) {
            file_put_contents($this->log_file, date("Y-m-d H:i:s")." ".$message."
", FILE_APPEND);
        }
    }
}

//maybe in the future logging into database

class LoggerDb implements Logger {
    private $db;

    public function __construct($db) {
        //some code
    }
public function log_message($message) {
        //some code
    }
}

Class A {
    private $logger;

public function __construct(Logger $l) {
        $this->logger = $l;
    }


public function f_A {
    $this->logger->log_message($message);
}
}

Class B {
    private $logger;

public function __construct(Logger $l) {
        $this->logger = $l;
    }


public function f_B {
    $this->logger->log_message($message);
}
}

//usage:

//in config.php:

define("CONFIG_LOG_FILE", "log/app_log.log");

//in the index.php or some other files

$logger = new LoggerFile(CONFIG_LOG_FILE);

$instance_a = new A($logger);
$instance_b = new B($logger);

推薦答案

記錄器在哪里使用?

一般來說,在代碼中使用記錄器有兩個主要用例:

Where are loggers used?

In general there are two major use-cases for use of loggers within your code:

  • 侵入式日志記錄:

  • invasive logging:

大多數人使用這種方法是因為它最容易理解.

For the most part people use this approach because it is the easiest to understand.

實際上,如果日志記錄是域邏輯本身的一部分,您應該只使用侵入式日志記錄.例如 - 在處理支付或敏感信息管理的課程中.

In reality you should only use invasive logging if logging is part of the domain logic itself. For example - in classes that deal with payments or management of sensitive information.

非侵入式日志記錄:

使用此方法而不是更改您希望記錄的類,您可以將現有實例包裝在一個容器中,這樣您就可以跟蹤實例與應用程序其余部分之間的每次交換.

With this method instead of altering the class that you wish to log, you wrap an existing instance in a container that lets you track every exchange between instance and rest of application.

您還可以臨時啟用此類日志記錄,同時在開發環境之外調試某些特定問題或對用戶行為進行一些研究時.由于記錄實例的類從未改變,與侵入式記錄相比,破壞項目行為的風險要低得多.

You also gain the ability to enable such logging temporarily, while debugging some specific problem outside of the development environment or when you are conducting some research of user behaviour. Since the class of the logged instance is never altered, the risk of disrupting the project's behaviour is a lot lower when compared to invasive logging.

為此,您可以使用兩種主要方法.您可以注入一個實現 Logger 接口的實例,也可以為類提供一個工廠,而工廠只會在必要時初始化日志系統.

To do this you have two main approaches available. You can either inject an instance that implements the Logger interface, or provide the class with a factory that in turn will initialize the logging system only when necessary.

注意:
由于似乎直接注入對您來說并不是什么隱藏的秘密,我將省略那部分...只是我會敦促您避免使用常量在已定義它們的文件之外.

現在.. 工廠和延遲加載的實現.

Now .. the implementation with factory and lazy loading.

您首先要定義您將使用的 API(在完美的世界中,您從單元測試開始).

You start by defining the API that you will use (in perfect world you start with unit-tests).

class Foobar 
{
    private $loggerFactory;

    public function __construct(Creator $loggerFactory, ....)
    {
        $this->loggerFactory = $loggerFactory;
        ....
    }
    .... 

    public function someLoggedMethod()
    {
        $logger = $this->loggerFactory->provide('simple');
        $logger->log( ... logged data .. );
        ....
    }
    ....
}

這個工廠將有兩個額外的好處:

This factory will have two additional benefits:

  • 可以保證只創建一個實例,不需要全局狀態
  • 在編寫單元測試時提供一個接縫

注意:
實際上,當以這種方式編寫時,類 Foobar 僅依賴于實現 Creator 接口的實例.通常你會注入一個構建器(如果你需要類型的實例,可能需要一些設置)或一個工廠(如果你想用相同的界面創建不同的實例).

下一步將是工廠的實施:

class LazyLoggerFactory implements Creator
{

    private $loggers = [];
    private $providers = [];

    public function addProvider($name, callable $provider)
    {
        $this->providers[$name] = $provider;
        return $this;
    }

    public function provide($name)
    {
        if (array_key_exists($name, $this->loggers) === false)
        {
            $this->loggers[$name] = call_user_func($this->providers[$name]);
        }
        return $this->loggers[$name];
    }

}

當您調用 $factory->provide('thing'); 時,工廠會查找實例是否已創建.如果搜索失敗,它會創建一個新實例.

When you call $factory->provide('thing');, the factory looks up if the instance has already been created. If the search fails it creates a new instance.

注意:我實際上并不完全確定這是否可以稱為工廠",因為實例化確實封裝在匿名函數中.

Note: I am actually not entirely sure that this can be called "factory" since the instantiation is really encapsulated in the anonymous functions.

最后一步實際上是與供應商聯系:

$config = include '/path/to/config/loggers.php';

$loggerFactory = new LazyLoggerFactory;
$loggerFactory->addProvider('simple', function() use ($config){
    $instance = new SimpleFileLogger($config['log_file']);
    return $instance;
});

/* 
$loggerFactory->addProvider('fake', function(){
    $instance = new NullLogger;
    return $instance;
});
*/

$test = new Foobar( $loggerFactory );

當然要完全理解這種方法,您必須知道閉包在 PHP 中的工作原理,但無論如何您都必須學習它們.

Of course to fully understand this approach you will have to know how closures work in PHP, but you will have to learn them anyway.

這種方法的核心思想是,不是注入記錄器,而是將現有實例放入容器中,該容器充當所述實例和應用程序之間的隔膜.這種膜可以執行不同的任務,其中之一就是記錄.

The core idea of this approach is that instead of injecting the logger, you put an existing instance in a container which acts as membrane between said instance and application. This membrane can then perform different tasks, one of those is logging.

class LogBrane
{
    protected $target = null;
    protected $logger = null;

    public function __construct( $target, Logger $logger )
    {
        $this->target = $target;
        $this->logger = $logger;
    }

    public function __call( $method, $arguments )
    {
        if ( method_exists( $this->target, $method ) === false )
        {
            // sometime you will want to log call of nonexistent method
        }

        try
        {
            $response = call_user_func_array( [$this->target, $method], 
                                              $arguments );

            // write log, if you want
            $this->logger->log(....);
        }
        catch (Exception $e)
        {
            // write log about exception 
            $this->logger->log(....);

            // and re-throw to not disrupt the behavior
            throw $e;
        }
    }
}

這個類也可以和上面描述的惰性工廠一起使用.

This class can also be used together with the above described lazy factory.

要使用此結構,您只需執行以下操作:

To use this structure, you simply do the following:

$instance = new Foobar;

$instance = new LogBrane( $instance, $logger );
$instance->someMethod();

此時包裝實例的容器成為原始容器的全功能替代品.應用程序的其余部分可以像處理一個簡單的對象一樣處理它(傳遞、調用方法).并且包裝的實例本身并不知道它正在被記錄.

At this point the container which wraps the instance becomes a fully functional replacement of the original. The rest of your application can handle it as if it is a simple object (pass around, call methods upon). And the wrapped instance itself is not aware that it is being logged.

如果您決定在某個時候刪除日志記錄,則無需重寫應用程序的其余部分即可完成.

And if at some point you decide to remove the logging then it can be done without rewriting the rest of your application.

這篇關于PHP - 在多個類中實現日志記錄機制的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Joining 2 tables in SELECT(MYSQL/PHP)(在 SELECT(MYSQL/PHP) 中加入 2 個表)
How to make lt;option selected=quot;selectedquot;gt; set by MySQL and PHP?(如何使lt;option selected=“selectedgt;由 MySQL 和 PHP 設置?)
Auto populate a select box using an array in PHP(使用 PHP 中的數組自動填充選擇框)
PHP SQL SELECT where like search item with multiple words(PHP SQL SELECT where like search item with multiple words)
json_encode produce JSON_ERROR_UTF8 from MSSQL-SELECT(json_encode 從 MSSQL-SELECT 產生 JSON_ERROR_UTF8)
MySQL ORDER BY rand(), name ASC(MySQL ORDER BY rand(),名稱 ASC)
主站蜘蛛池模板: 成人黄色av| 国产精品自拍视频网站 | 一级免费毛片 | 日韩一区二区三区在线观看 | 成人综合在线视频 | 国产日韩欧美在线 | 久久av网| 亚欧精品一区 | 欧美视频偷拍 | 欧美日韩在线观看一区二区三区 | 自拍偷拍亚洲一区 | 国产激情网| 亚洲免费视频网站 | 国产在线精品一区二区三区 | 久久精品成人 | 国产精品视频免费观看 | 久久国产精品免费一区二区三区 | 亚洲字幕在线观看 | 日韩视频一区二区在线 | 中文字幕97 | 99这里只有精品 | 美女视频黄色的 | 亚洲一区视频在线 | www.日本三级| 日韩有码一区 | 99精品一区二区三区 | 国产精品18久久久久久白浆动漫 | 午夜爽爽爽男女免费观看 | 黄色大片毛片 | 亚洲一区 中文字幕 | 欧美久久久久久 | 日本欧美国产在线 | 久久草在线视频 | 天堂成人av| 欧美日韩免费 | 一级黄a视频 | 欧美在线高清 | 狠狠色网 | 中文精品视频 | 妖精视频一区二区三区 | 日韩视频二区 |