首頁 後端開發 php教程 PHP主|使用PSR-3登錄以提高可重用性

PHP主|使用PSR-3登錄以提高可重用性

Feb 24, 2025 am 10:42 AM

PHP Master | Logging with PSR-3 to Improve Reusability

核心要點

  • PSR-3,一個通用的日誌對象接口,允許開發者編寫可重用的代碼,而無需依賴任何特定的日誌實現,從而提高了PHP中不同日誌庫之間的兼容性。
  • PSR-3接口提供了八種方法來處理不同嚴重級別的消息,以及一個通用的log()方法,可以接收任意嚴重級別。其設計目的是為了解決日誌實現不兼容的問題。
  • 儘管PSR-3有很多好處,但有些日誌庫並不原生支持它。然而,開發者可以通過利用適配器模式和擴展Psr/Log庫中提供的AbstractLogger類來創建符合PSR-3的適配器。
  • 許多主要的PHP項目,包括Monolog、Symfony和Mustache.php,都已經添加了對PSR-3的支持。由於它降低了代碼重用的障礙,預計會有更多庫和框架正確使用日誌記錄,為開發者提供有用的信息。

在PHP開發中,日誌記錄是最常見的任務之一。我們使用日誌來跟踪錯誤消息、記錄重要事件和調試代碼問題。在任何PHP項目中,代碼中都可能充滿了對日誌庫的調用,這些庫為我們處理這些操作。不幸的是,在代碼中散佈著對日誌庫的調用,這使得代碼依賴於該庫的可用性,這明顯違反了依賴倒置原則。即使我們使用依賴注入讓我們的對象訪問日誌庫,日誌庫之間的差異也意味著在它們之間切換可能很困難且費時,需要對整個代碼庫進行重大重構。為了提高日誌庫之間的兼容性,PHP-FIG小組最近發布了PSR-3,這是一個通用的日誌對象接口。在本文中,我將討論PSR-3定義的日誌接口如何允許我們編寫不依賴於任何特定日誌實現的可重用代碼。

PSR-3快速入門

在我們了解PSR-3如何使我們的代碼更可重用之前,有必要了解PSR-3是什麼。如果您已經熟悉PSR-3,可以跳過本節。規範的核心是日誌對象的接口。此接口公開了八種方法來處理不同嚴重級別的消息,以及一個通用的log()方法,可以接受任意嚴重級別。 PSR-3支持的八個嚴重級別基於RFC 5424,如下所述:

  • emergency – 系統無法使用
  • alert – 需要立即採取行動
  • critical – 嚴重狀況
  • error – 不需要立即關注但應監控的錯誤
  • warning – 不尋常或不希望發生的事件,但並非錯誤
  • notice – 正常但重要的事件
  • info – 有趣的事件
  • debug – 用於調試的詳細信息

每個日誌方法都接受一個消息,該消息必須是字符串或具有__toString()方法的對象。附加參數接受一個數組,可以提供日誌消息的上下文信息。可以在PSR-3規範中找到這些方法和參數的完整說明。

獲取PSR-3文件

獲取使用PSR-3所需的文件很容易——您可以在Psr/Log GitHub存儲庫中找到它們。您也可以使用Composer從Packagist獲取這些文件。下面是一個用於檢索Psr/Log文件的示例composer.json文件:

{
    "require": {
        "psr/log": "dev-master"
    }
}
登入後複製
登入後複製
登入後複製

日誌記錄如何限制代碼重用

PHP有很多不同的日誌庫,每個庫都有自己收集和記錄數據的方法。雖然它們之間有一些共同點,但每個庫都有自己獨特的一套日誌方法。這意味著在日誌之間切換可能具有挑戰性,通常需要更改任何使用日誌記錄的地方的代碼。這與代碼重用和麵向對象設計的SOLID原則背道而馳。我們面臨的局面是:要么聲明對特定日誌庫的依賴,要么完全避免日誌記錄。為了更清楚地說明這個問題,需要一個具體的例子。假設我們正在創建一個簡單的Mailer對象來處理髮送電子郵件。我們希望Mailer在每次發送電子郵件時記錄一條消息,並且我們決定使用優秀的Monolog庫來處理我們的日誌記錄需求。

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 发送电子邮件的代码...

        // 记录消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}
登入後複製
登入後複製
登入後複製

我們可以使用以下代碼使用此類:

<?php
// 创建一个Monolog对象
$logger = new Monolog\Logger("Mail");
$logger->pushHandler(new Monolog\Handler\StreamHandler("mail.log"));

// 创建邮件发送器并发送电子邮件
$mailer = new Email\Mailer($logger);
$mailer->sendEmail("email@example.com");
登入後複製
登入後複製

運行此代碼將在mail.log文件中創建一個新條目,記錄已發送電子郵件。此時,我們可能會認為我們已經編寫了一個可重用的Mailer對象。我們使用依賴注入使日誌記錄器可用於Mailer,因此我們可以交換不同的日誌記錄器配置,而無需觸及我們的Mailer代碼。看起來我們已經成功遵循了SOLID原則並避免了創建任何硬依賴。但是,假設我們想在使用Analog處理日誌記錄交互的不同項目中重用Mailer類。現在我們遇到了問題,因為Analog沒有addInfo()方法。要使用Analog記錄信息級別消息,我們調用Analog::log($message, Analog::INFO)。我們可以修改Mailer類以使用Analog的方法,如下所示。

<?php namespace Email;

class Mailer
{
    public function sendEmail($emailAddress)
    {
        // 发送电子邮件的代码...

        // 记录消息
        Analog::log("Email sent to $emailAddress", Analog::INFO);
    }
}
登入後複製
登入後複製

我們可以使用以下代碼使用更新後的Mailer類:

{
    "require": {
        "psr/log": "dev-master"
    }
}
登入後複製
登入後複製
登入後複製

雖然這會起作用,但這遠非理想。我們遇到了Mailer對特定日誌記錄實現的依賴,這要求在引入新的日誌記錄器時更改類。這使得類不太可重用,並迫使我們必須在依賴於特定日誌記錄器的可用性或完全放棄類中的日誌記錄之間做出選擇。

使用PSR-3避免日誌記錄器依賴

正如Alejandro Gervasio在他關於該主題的優秀文章中解釋的那樣,依賴倒置原則告訴我們,我們應該依賴抽象而不是具體實現。在日誌記錄的情況下,我們目前的問題一直是缺乏一個可以依賴的合適的抽象。這就是PSR-3發揮作用的地方。 PSR-3旨在通過為日誌記錄器提供一個通用接口(恰當地命名為LoggerInterface)來克服日誌記錄實現不兼容的問題。通過提供一個不綁定到任何特定實現的接口,PSR-3使我們無需依賴特定的日誌記錄器——我們可以改為對LoggerInterface進行類型提示以獲取符合PSR-3的日誌記錄器。我已經更新了下面的Mailer類來演示這一點:

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 发送电子邮件的代码...

        // 记录消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}
登入後複製
登入後複製
登入後複製

構造函數已修改為接受LoggerInterface的實現者,並且sendEmail()方法現在調用PSR-3中指定的info()方法。 Monolog已經符合PSR-3,並且Analog提供了一個實現LoggerInterface的包裝器對象,因此我們現在可以使用這兩個日誌記錄器而無需修改Mailer類。以下是如何使用Monolog調用該類的:

<?php
// 创建一个Monolog对象
$logger = new Monolog\Logger("Mail");
$logger->pushHandler(new Monolog\Handler\StreamHandler("mail.log"));

// 创建邮件发送器并发送电子邮件
$mailer = new Email\Mailer($logger);
$mailer->sendEmail("email@example.com");
登入後複製
登入後複製

以及使用Analog:

<?php namespace Email;

class Mailer
{
    public function sendEmail($emailAddress)
    {
        // 发送电子邮件的代码...

        // 记录消息
        Analog::log("Email sent to $emailAddress", Analog::INFO);
    }
}
登入後複製
登入後複製

現在,我們能夠使用我們的Mailer對象與任何庫一起使用,而無需編輯Mailer類或更改我們使用它的方式。

為不支持PSR-3的日誌記錄器使用適配器模式

到目前為止,我們已經通過請求LoggerInterface的實現者成功地將Mailer對象與任何特定的日誌記錄實現解耦。但是,那些尚未添加對PSR-3支持的日誌記錄器呢?例如,流行的KLogger庫已經有一段時間沒有更新了,目前與PSR-3不兼容。幸運的是,我們可以通過利用適配器模式輕鬆地將KLogger公開的方法映射到LoggerInterface中定義的方法。 Psr/Log存儲庫中的支持文件使我們能夠通過提供一個我們可以擴展的AbstractLogger類來輕鬆創建適配器類。抽像類只是將LoggerInterface中定義的八個特定於級別的日誌方法轉發到一個通用的log()方法。通過擴展AbstractLogger類並定義我們自己的log()方法,我們可以輕鬆地為不原生支持PSR-3的日誌記錄器創建符合PSR-3的適配器。我將在下面通過為KLogger創建一個簡單的適配器來演示這一點:

{
    "require": {
        "psr/log": "dev-master"
    }
}
登入後複製
登入後複製
登入後複製

log()方法只是將LoggerInterface方法映射到各自的KLogger方法,而KLogger處理實際的日誌記錄活動。通過這種方式包裝KLogger類,我們能夠在不破壞LoggerInterface契約的情況下使用它。我們現在可以使用KLogger適配器與Mailer類一起使用:

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 发送电子邮件的代码...

        // 记录消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}
登入後複製
登入後複製
登入後複製

使用適配器類,我們能夠在不修改Mailer類的情況下使用KLogger,並且仍然遵守LoggerInterface。 KLogger不接受調試級別消息的第二個參數,因此即使使用適配器,它也不完全符合PSR-3。擴展KLogger以使其完全與PSR-3兼容將是一項微不足道的任務,但這超出了本文的範圍。但是,可以肯定地說,使用我們的適配器類使我們非常接近完全符合PSR-3,並允許我們使用LoggerInterface與KLogger類一起使用。

結論

在本文中,我們已經了解瞭如何使用PSR-3來幫助我們編寫與日誌記錄器無關的代碼,這些代碼不依賴於特定的日誌記錄實現。許多主要的PHP項目已經添加了對PSR-3的支持,包括Monolog、Symfony和Mustache.php,以及Drupal等其他知名項目正在討論如何最好地集成它。由於PSR-3降低了代碼重用的障礙,我們應該看到更多庫和框架正確使用日誌記錄,為開發者提供有用的信息。 PSR-3會影響您在應用程序中使用日誌記錄的方式嗎?請在下面的評論部分告訴我們。

(圖片來自Fotolia)

(PSR-3日誌記錄的常見問題解答部分,由於篇幅限制,此處省略。 可以根據需要添加。)

以上是PHP主|使用PSR-3登錄以提高可重用性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

會話如何劫持工作,如何在PHP中減輕它? 會話如何劫持工作,如何在PHP中減輕它? Apr 06, 2025 am 12:02 AM

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

PHP 8.1中的枚舉(枚舉)是什麼? PHP 8.1中的枚舉(枚舉)是什麼? Apr 03, 2025 am 12:05 AM

PHP8.1中的枚舉功能通過定義命名常量增強了代碼的清晰度和類型安全性。 1)枚舉可以是整數、字符串或對象,提高了代碼可讀性和類型安全性。 2)枚舉基於類,支持面向對象特性,如遍歷和反射。 3)枚舉可用於比較和賦值,確保類型安全。 4)枚舉支持添加方法,實現複雜邏輯。 5)嚴格類型檢查和錯誤處理可避免常見錯誤。 6)枚舉減少魔法值,提升可維護性,但需注意性能優化。

描述紮實的原則及其如何應用於PHP的開發。 描述紮實的原則及其如何應用於PHP的開發。 Apr 03, 2025 am 12:04 AM

SOLID原則在PHP開發中的應用包括:1.單一職責原則(SRP):每個類只負責一個功能。 2.開閉原則(OCP):通過擴展而非修改實現變化。 3.里氏替換原則(LSP):子類可替換基類而不影響程序正確性。 4.接口隔離原則(ISP):使用細粒度接口避免依賴不使用的方法。 5.依賴倒置原則(DIP):高低層次模塊都依賴於抽象,通過依賴注入實現。

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是REST API設計原理? 什麼是REST API設計原理? Apr 04, 2025 am 12:01 AM

RESTAPI設計原則包括資源定義、URI設計、HTTP方法使用、狀態碼使用、版本控制和HATEOAS。 1.資源應使用名詞表示並保持層次結構。 2.HTTP方法應符合其語義,如GET用於獲取資源。 3.狀態碼應正確使用,如404表示資源不存在。 4.版本控制可通過URI或頭部實現。 5.HATEOAS通過響應中的鏈接引導客戶端操作。

您如何在PHP中有效處理異常(嘗試,捕捉,最後,投擲)? 您如何在PHP中有效處理異常(嘗試,捕捉,最後,投擲)? Apr 05, 2025 am 12:03 AM

在PHP中,異常處理通過try,catch,finally,和throw關鍵字實現。 1)try塊包圍可能拋出異常的代碼;2)catch塊處理異常;3)finally塊確保代碼始終執行;4)throw用於手動拋出異常。這些機制幫助提升代碼的健壯性和可維護性。

PHP中的匿名類是什麼?您何時可以使用它們? PHP中的匿名類是什麼?您何時可以使用它們? Apr 04, 2025 am 12:02 AM

匿名類在PHP中的主要作用是創建一次性使用的對象。 1.匿名類允許在代碼中直接定義沒有名字的類,適用於臨時需求。 2.它們可以繼承類或實現接口,增加靈活性。 3.使用時需注意性能和代碼可讀性,避免重複定義相同的匿名類。

See all articles