国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Home Backend Development PHP Tutorial PHP Master | Logging with PSR-3 to Improve Reusability

PHP Master | Logging with PSR-3 to Improve Reusability

Feb 24, 2025 am 10:42 AM

PHP Master | Logging with PSR-3 to Improve Reusability

Core points

  • PSR-3, a common log object interface, allows developers to write reusable code without relying on any specific log implementation, thereby improving compatibility between different log libraries in PHP.
  • The
  • PSR-3 interface provides eight methods to handle messages of different severity levels, and a common log() method that can receive any severity levels. Its design is to solve the problem of log implementation incompatibility.
  • Although PSR-3 has many benefits, some log libraries do not support it natively. However, developers can create PSR-3 compliant adapters by leveraging the adapter mode and extending the AbstractLogger class provided in the Psr/Log library.
  • Many major PHP projects, including Monolog, Symfony, and Mustache.php, have added support for PSR-3. As it reduces the barriers to code reuse, more libraries and frameworks are expected to use logging correctly, providing useful information for developers.

In PHP development, logging is one of the most common tasks. We use logs to track error messages, log important events, and debug code issues. In any PHP project, the code may be filled with calls to log libraries that handle these operations for us. Unfortunately, calls to log libraries are scattered throughout the code, which makes the code depend on the availability of the library, which is clearly contrary to the principle of dependency inversion. Even if we use dependency injection to let our objects access the log library, the difference between log libraries means switching between them can be difficult and time-consuming, requiring a major refactoring of the entire code library. To improve compatibility between log libraries, the PHP-FIG team recently released PSR-3, a common log object interface. In this article, I will discuss how the PSR-3 defined log interface allows us to write reusable code that does not depend on any particular log implementation.

PSR-3 Quick Start

Before we understand how PSR-3 makes our code more reusable, it is necessary to understand what PSR-3 is. If you are already familiar with PSR-3, you can skip this section. The core of the specification is the interface to log objects. This interface discloses eight ways to handle messages of different severity levels, and a common log() method that can accept any severity levels. The eight severity levels supported by PSR-3 are based on RFC 5424, as described below:

  • emergency – The system cannot be used
  • alert – Action is required
  • critical – Serious situation
  • error – Errors that do not need immediate attention but should be monitored
  • warning – An unusual or undesirable event, but not an error
  • notice – Normal but important events
  • info – Interesting Events
  • debug – Details for debugging

Each log method accepts a message that must be a string or an object with a __toString() method. Additional parameters accept an array that can provide context information for log messages. A complete description of these methods and parameters can be found in the PSR-3 specification.

Get PSR-3 file

Getting the files you need to use PSR-3 is easy - you can find them in the Psr/Log GitHub repository. You can also use Composer to get these files from Packagist. Here is an example of a composer.json file for retrieving Psr/Log files:

{
    "require": {
        "psr/log": "dev-master"
    }
}

How to limit code reuse of logging

PHP has many different log libraries, each with its own way of collecting and recording data. While they have some commonalities, each library has its own unique set of logging methods. This means switching between logs can be challenging, and often requires changing the code where you use logging. This runs contrary to the SOLID principle of code reuse and object-oriented design. The situation we face is that either declare dependencies on specific log libraries or avoid logging altogether. To illustrate this issue more clearly, a specific example is needed. Suppose we are creating a simple Mailer object to handle sending emails. We want Mailer to log a message every time we send an email, and we decided to use the excellent Monolog library to handle our logging needs.

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 發(fā)送電子郵件的代碼...

        // 記錄消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}

We can use this class with the following code:

<?php
// 創(chuàng)建一個Monolog對象
$logger = new Monolog\Logger("Mail");
$logger->pushHandler(new Monolog\Handler\StreamHandler("mail.log"));

// 創(chuàng)建郵件發(fā)送器并發(fā)送電子郵件
$mailer = new Email\Mailer($logger);
$mailer->sendEmail("email@example.com");

Running this code will create a new entry in the mail.log file, recording the email sent. At this point, we might think that we have written a reusable Mailer object. We use dependency injection to make the logger available for Mailer, so we can swap different logger configurations without touching our Mailer code. It looks like we have successfully followed the SOLID principle and avoided creating any hard dependencies. But suppose we want to reuse the Mailer class in different projects using Analog to handle logging interactions. Now we have a problem because Analog does not have a addInfo() method. To record information-level messages using Analog, we call Analog::log($message, Analog::INFO). We can modify the Mailer class to use the Analog method as shown below.

<?php namespace Email;

class Mailer
{
    public function sendEmail($emailAddress)
    {
        // 發(fā)送電子郵件的代碼...

        // 記錄消息
        Analog::log("Email sent to $emailAddress", Analog::INFO);
    }
}

We can use the updated Mailer class with the following code:

{
    "require": {
        "psr/log": "dev-master"
    }
}

While this will work, it is far from ideal. We encountered Mailer's dependency on a specific logging implementation, which requires changing the class when introducing a new logger. This makes the class less reusable and forces us to choose between relying on the availability of a particular logger or abandoning logging in the class altogether.

Use PSR-3 to avoid logger dependencies

As Alejandro Gervasio explains in his excellent article on the topic, the principle of dependency inversion tells us that we should rely on abstraction rather than concrete implementations. In the case of logging, our current problem has been the lack of a suitable abstraction that can be relied on. This is where PSR-3 comes into play. PSR-3 is designed to overcome the incompatibility of logging implementation by providing a common interface for the logger (properly named LoggerInterface). By providing an interface that is not bound to any specific implementation, PSR-3 allows us to avoid relying on a specific logger - we can instead type prompt for LoggerInterface to get a PSR-3-compliant logger. I've updated the following Mailer class to demonstrate this:

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 發(fā)送電子郵件的代碼...

        // 記錄消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}
The

constructor has been modified to accept the LoggerInterface implementer, and the sendEmail() method now calls the info() method specified in PSR-3. Monolog is already PSR-3 compliant, and Analog provides a wrapper object that implements LoggerInterface, so we can now use these two loggers without modifying the Mailer class. Here is how to call this class using Monolog:

<?php
// 創(chuàng)建一個Monolog對象
$logger = new Monolog\Logger("Mail");
$logger->pushHandler(new Monolog\Handler\StreamHandler("mail.log"));

// 創(chuàng)建郵件發(fā)送器并發(fā)送電子郵件
$mailer = new Email\Mailer($logger);
$mailer->sendEmail("email@example.com");

and use Analog:

<?php namespace Email;

class Mailer
{
    public function sendEmail($emailAddress)
    {
        // 發(fā)送電子郵件的代碼...

        // 記錄消息
        Analog::log("Email sent to $emailAddress", Analog::INFO);
    }
}

Now we are able to use our Mailer object with any library without editing the Mailer class or changing the way we use it.

Use adapter mode for loggers that do not support PSR-3

So far, we have successfully decoupled the Mailer object from any specific logging implementation through the implementer requesting LoggerInterface. But what about those loggers that have not yet been added for PSR-3 support? For example, the popular KLogger library has not been updated for a while and is currently incompatible with PSR-3. Fortunately, we can easily map the methods exposed by KLogger to those defined in LoggerInterface by leveraging the adapter pattern. Supported files in the Psr/Log repository enable us to easily create adapter classes by providing a AbstractLogger class that we can extend. An abstract class simply forwards eight level-specific log methods defined in LoggerInterface to a common log() method. By extending the AbstractLogger class and defining our own log() method, we can easily create PSR-3-compliant adapters for loggers that do not natively support PSR-3. I'll demonstrate this below by creating a simple adapter for KLogger:

{
    "require": {
        "psr/log": "dev-master"
    }
}
The

log() method simply maps the LoggerInterface method to the respective KLogger method, and the KLogger handles the actual logging activity. By wrapping the KLogger class this way, we are able to use it without breaking the LoggerInterface contract. We can now use the KLogger adapter with the Mailer class:

<?php namespace Email;

class Mailer
{
    private $logger;

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

    public function sendEmail($emailAddress)
    {
        // 發(fā)送電子郵件的代碼...

        // 記錄消息
        $this->logger->addInfo("Email sent to $emailAddress");
    }
}

With the adapter class, we are able to use KLogger without modifying the Mailer class and still adhere to LoggerInterface. KLogger does not accept the second parameter of debug level messages, so it does not fully comply with PSR-3 even with an adapter. Extending KLogger to make it fully compatible with PSR-3 would be a trivial task, but that's beyond the scope of this article. However, it is safe to say that using our adapter class makes us very close to being fully PSR-3 compliant and allows us to use LoggerInterface with the KLogger class.

Conclusion

In this article, we have learned how to use PSR-3 to help us write logger-free code that does not depend on a specific logging implementation. Many major PHP projects have added support for PSR-3, including Monolog, Symfony, and Mustache.php, as well as other well-known projects like Drupal are discussing how to best integrate it. Since PSR-3 reduces the barriers to code reuse, we should see more libraries and frameworks correctly use logging to provide useful information for developers. Will PSR-3 affect how you use logging in your application? Please let us know in the comments section below.

(Picture from Fotolia)

(The FAQ part of PSR-3 logging is omitted here due to space limitations. It can be added as needed.)

The above is the detailed content of PHP Master | Logging with PSR-3 to Improve Reusability. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

What are some best practices for versioning a PHP-based API? What are some best practices for versioning a PHP-based API? Jun 14, 2025 am 12:27 AM

ToversionaPHP-basedAPIeffectively,useURL-basedversioningforclarityandeaseofrouting,separateversionedcodetoavoidconflicts,deprecateoldversionswithclearcommunication,andconsidercustomheadersonlywhennecessary.StartbyplacingtheversionintheURL(e.g.,/api/v

How do I implement authentication and authorization in PHP? How do I implement authentication and authorization in PHP? Jun 20, 2025 am 01:03 AM

TosecurelyhandleauthenticationandauthorizationinPHP,followthesesteps:1.Alwayshashpasswordswithpassword_hash()andverifyusingpassword_verify(),usepreparedstatementstopreventSQLinjection,andstoreuserdatain$_SESSIONafterlogin.2.Implementrole-basedaccessc

What are weak references (WeakMap) in PHP, and when might they be useful? What are weak references (WeakMap) in PHP, and when might they be useful? Jun 14, 2025 am 12:25 AM

PHPdoesnothaveabuilt-inWeakMapbutoffersWeakReferenceforsimilarfunctionality.1.WeakReferenceallowsholdingreferenceswithoutpreventinggarbagecollection.2.Itisusefulforcaching,eventlisteners,andmetadatawithoutaffectingobjectlifecycles.3.YoucansimulateaWe

What are the differences between procedural and object-oriented programming paradigms in PHP? What are the differences between procedural and object-oriented programming paradigms in PHP? Jun 14, 2025 am 12:25 AM

Proceduralandobject-orientedprogramming(OOP)inPHPdiffersignificantlyinstructure,reusability,anddatahandling.1.Proceduralprogrammingusesfunctionsorganizedsequentially,suitableforsmallscripts.2.OOPorganizescodeintoclassesandobjects,modelingreal-worlden

How can you handle file uploads securely in PHP? How can you handle file uploads securely in PHP? Jun 19, 2025 am 01:05 AM

To safely handle file uploads in PHP, the core is to verify file types, rename files, and restrict permissions. 1. Use finfo_file() to check the real MIME type, and only specific types such as image/jpeg are allowed; 2. Use uniqid() to generate random file names and store them in non-Web root directory; 3. Limit file size through php.ini and HTML forms, and set directory permissions to 0755; 4. Use ClamAV to scan malware to enhance security. These steps effectively prevent security vulnerabilities and ensure that the file upload process is safe and reliable.

How can you interact with NoSQL databases (e.g., MongoDB, Redis) from PHP? How can you interact with NoSQL databases (e.g., MongoDB, Redis) from PHP? Jun 19, 2025 am 01:07 AM

Yes, PHP can interact with NoSQL databases like MongoDB and Redis through specific extensions or libraries. First, use the MongoDBPHP driver (installed through PECL or Composer) to create client instances and operate databases and collections, supporting insertion, query, aggregation and other operations; second, use the Predis library or phpredis extension to connect to Redis, perform key-value settings and acquisitions, and recommend phpredis for high-performance scenarios, while Predis is convenient for rapid deployment; both are suitable for production environments and are well-documented.

What are the differences between == (loose comparison) and === (strict comparison) in PHP? What are the differences between == (loose comparison) and === (strict comparison) in PHP? Jun 19, 2025 am 01:07 AM

In PHP, the main difference between == and == is the strictness of type checking. ==Type conversion will be performed before comparison, for example, 5=="5" returns true, and ===Request that the value and type are the same before true will be returned, for example, 5==="5" returns false. In usage scenarios, === is more secure and should be used first, and == is only used when type conversion is required.

How do I stay up-to-date with the latest PHP developments and best practices? How do I stay up-to-date with the latest PHP developments and best practices? Jun 23, 2025 am 12:56 AM

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

See all articles