可以用composer的autoload来,导入自己写的类库。

 

composer dump-autoload -o  ----------------> 改成 composer update 也可以。

怎么使用co'mposer呢?

1.composer.json

2. index.php

3. 执行 php index.php

---------------------------------------------------------------------------------

Logging is one of the most ubiquitous tasks encountered in PHP. We use logs to track error messages, record important events, and debug problems with our code. In any PHP project, the code is likely to be full of calls to a logging library which handles these actions for us.

Unfortunately, having calls to a logging library scattered throughout our code makes the code dependent on the availability of that library, a clear violation of the Dependency Inversion Principle. Even if we use dependency injection to give our objects access to the logging library, the differences between logging libraries means that it can be difficult and time consuming to switch between them, requiring a major refactoring of our entire codebase.

 
Ads by Hooly
 

To promote compatibility between logging libraries, the PHP-FIG group recently released PSR-3, a common interface for logger objects. In this article, I’ll discuss how the logger interface defined by PSR-3 allows us to write reusable code that isn’t dependent on any particular logging implementation.

First, a Quick Primer

 

Before we look at how PSR-3 can make 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 heart of the specification is an interface for logger objects. This interface exposes eight methods for handling messages of different severity, and a generic log() method which can accept an arbitrary severity level.

The eight severity levels supported by PSR-3 are based on RFC 5424, and are described below:

  • Emergency – the system is unusable
  • Alert – immediate action is required
  • Critical – critical conditions
  • Error – errors that do not require immediate attention but should be monitored
  • Warning – unusual or undesirable occurrences that are not errors
  • Notice – normal but significant events
  • Info – interesting events
  • Debug – detailed information for debugging purposes

Each of the logging methods accepts a message, which must be a string or an object with a __toString() method. An additional argument accepts an array, which may be given to provide contextual information for the log message.

A full explanation of these methods and parameters can be found in the PSR-3 specification.

Getting PSR-3 Files

Getting the files you need to work with PSR-3 is easy – you can find them in the Psr/Log GitHub repository. You can also use Composer to get the files from Packagist. Below is a sample composer.json file to retrieve the Psr/Log files:

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

How Logging Can Limit Code Reuse

There are many different logging libraries for PHP, each with its own approach to collecting and recording data. While there are some common ideas among them, each library has its own unique set of logging methods. This means that switching between loggers can be challenging, often requiring code changes wherever logging is used. This works against the idea of code reuse and the SOLID principles of object-oriented design. We’re left with a situation that requires us to either declare a dependency on a specific logging library, or avoid logging entirely.

To illustrate this problem more clearly, a concrete example is needed. Let’s say we’re creating a simple Mailer object to handle sending emails. We want the Mailer to log a message whenever an email is sent, and we decide to use the excellent Monologlibrary to handle our logging needs.

<?php
namespace Email; class Mailer
{
private $logger; public function __construct($logger)
{
$this->logger = $logger;
} public function sendEmail($emailAddress)
{
// code to send an email... // log a message
$this->logger->addInfo("Email sent to $emailAddress");
}
}

We can use this class with the following code:

<?php
// create a Monolog object
$logger = new MonologLogger("Mail");
$logger->pushHandler(new MonologHandlerStreamHandler("mail.log")); // create the mailer and send an email
$mailer = new EmailMailer($logger);
$mailer->sendEmail("email@example.com");

Running this code will result in a new entry in the mail.log file, recording that the email was sent.

At this point, we might be tempted to say that we’ve written a reusable Mailer object. We’re making the logger available to the Mailer with dependency injection so we can swap out different logger configurations without having to touch our Mailer code. It appears that we’ve successfully followed the SOLID principles and avoided creating any hard dependencies.

But suppose we want to reuse our Mailer class in a different project which uses Analog to handle logging interactions. Now we run into a problem, because Analog doesn’t have an addInfo() method. To log an info level message with Analog, we call Analog::log($message, Analog::INFO).

We could modify our Mailer class to use Analog’s methods, as seen below.

<?php
namespace Email; class Mailer
{
public function sendEmail($emailAddress)
{
// code to send an email... // log a message
Analog::log("Email sent to $emailAddress", Analog::INFO);
}
}

We can consume the updated Mailer class using the following code:

<?php
// set up Analog
Analog::handler(AnalogHandlerFile::init("mail.log")); // create the mailer and send an email
$mailer = new EmailMailer();
$mailer->sendEmail("email@example.com");

While this will work, it is far from ideal. We’ve run into Mailer’s dependency on a specific logging implementation, which requires the class to change whenever a new logger is introduced. This makes the class less reusable and forces us to choose between being dependent on the availability of a specific logger or abandoning logging from within our class entirely.

Using PSR-3 to Avoid the Logger Dependency

As Alejandro Gervasio explained in his excellent article on the subject, the Dependency Inversion Principle tells us that we should depend upon abstractions rather than concretions. In the case of logging, our problem so far has been a lack of a decent abstraction on which to depend.

This is where PSR-3 comes in. PSR-3 is designed to overcome the problem of incompatible logging implementations by providing a universal interface for loggers, aptly named LoggerInterface. By providing an interface which is not bound to any particular implementation, PSR-3 frees us from having to rely on a specific logger – we can instead type-hint against LoggerInterface to acquire a PSR-3 compliant logger. I have updated the Mailer class below to demonstrate this:

<?php
namespace Email; class Mailer
{
private $logger; public function __construct(PsrLogLoggerInterface $logger)
{
$this->logger = $logger;
} public function sendEmail($emailAddress)
{
// code to send an email... // log a message
$this->logger->info("Email sent to $emailAddress");
}
}

The constructor has been modified to accept an implementor of LoggerInterface, and the sendEmail() method now calls the info() method specified in PSR-3.

Monolog is already PSR-3 compliant, and Analog supplies a wrapper object that implements LoggerInterface, so we can now use both loggers without modifying our Mailer class.

Here’s how you would call the class with Monolog:

<?php
// create a Monolog object
$logger = new MonologLogger("Mail");
$logger->pushHandler(new MonologHandlerStreamHandler("mail.log")); // create the mailer and send an email
$mailer = new EmailMailer($logger);
$mailer->sendEmail("email@example.com");

And with Analog:

<?php
// create a PSR-3 compatible Analog wrapper
$logger = new AnalogLogger();
$logger->handler(AnalogHandlerFile::init("mail.log")); // create the mailer and send an email
$mailer = new EmailMailer($logger);
$mailer->sendEmail("email@example.com");

Now we’re able to use our Mailer object with either library without having to edit the Mailer class or change the way we consume it.

Using the Adapter Pattern for Loggers that Don’t Support PSR-3

So far we’ve successfully decoupled the Mailer object from any particular logging implementation by asking for an implementor of LoggerInterface. But what about loggers that have yet to add support for PSR-3? For example, the popular KLoggerlibrary has not been updated for some time and is currently not compatible with PSR-3.

Luckily, it’s simple for us to map the methods exposed by KLogger to those defined by LoggerInterface by harnessing the power of the Adapter Pattern. The supporting files in the Psr/Log repository make it easy to create adapter classes by providing us with an AbstractLogger class that we can extend. The abstract class simply forwards the eight level-specific logging methods defined in LoggerInterface to a generic log() method. By extending the AbstractLoggerclass 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:

<?php
namespace Logger; class KloggerAdapter extends PsrLogAbstractLogger implements PsrLogLoggerInterface
{
private $logger; public function __construct($logger)
{
$this->logger = $logger;
} public function log($level, $message, array $context = array())
{
// PSR-3 states that $message should be a string
$message = (string)$message; // map $level to the relevant KLogger method
switch ($level) {
case PsrLogLogLevel::EMERGENCY:
$this->logger->logEmerg($message, $context);
break;
case PsrLogLogLevel::ALERT:
$this->logger->logAlert($message, $context);
break;
case PsrLogLogLevel::CRITICAL:
$this->logger->logCrit($message, $context);
break;
case PsrLogLogLevel::ERROR:
$this->logger->logError($message, $context);
break;
case PsrLogLogLevel::WARNING:
$this->logger->logWarn($message, $context);
break;
case PsrLogLogLevel::NOTICE:
$this->logger->logNotice($message, $context);
break;
case PsrLogLogLevel::INFO:
$this->logger->logInfo($message, $context);
break;
case PsrLogLogLevel::DEBUG:
// KLogger logDebug() method does not accept a second
// argument
$this->logger->logDebug($message);
break;
default:
// PSR-3 states that we must throw a
// PsrLogInvalidArgumentException if we don't
// recognize the level
throw new PsrLogInvalidArgumentException(
"Unknown severity level"
);
}
}
}

The log() method simply maps the LoggerInterface methods to the respective KLogger methods, and KLogger handles the actual logging activity. By wrapping the KLogger class in this way, we’re able to use it without breaking the LoggerInterface contract.

We can now use the KLogger adapter to work with the Mailer class:

<?php
// create a new KLogger object which will log to the "logs" directory
$klogger = KLogger::instance("logs"); // inject KLoggger to a PSR-3 compatible KloggerAdapter
$logger = new LoggerKloggerAdapter($klogger); // send an email
$mailer = new EmailMailer($logger);
$mailer->sendEmail("email@example.com");

Using the adapter class, we’re able to use KLogger without modifying the Mailer class and still adhering to LoggerInterface.

KLogger doesn’t accept a second argument for debug level messages, so it’s not technically PSR-3 compliant even with an adapter. Extending KLogger to make it fully compatible with PSR-3 would be a trivial task, but one which falls outside the scope of this article. However, it is safe to say that using our adapter class gets us very close to full PSR-3 compliance and allows us to use LoggerInterface with the KLogger class.

Conclusion

In this article we’ve seen how using PSR-3 can help us to write logger-agnostic code which does not depend on a particular logging implementation. Many major PHP projects have already added support for PSR-3, including Monolog, Symfony, and Mustache.php, and other big names such as Drupal are discussing how to best integrate it. As PSR-3 makes logging less of a barrier to code reuse, we should see more libraries and frameworks making proper use of logging to provide useful information to developers.

Will PSR-3 affect how you use logging in your applications? Let us know in the comments section below.

Logging with PSR-3 to Improve Reusability的更多相关文章

  1. [php]laravel框架容器管理的一些要点

    本文面向php语言的laravel框架的用户,介绍一些laravel框架里面容器管理方面的使用要点.文章很长,但是内容应该很有用,希望有需要的朋友能看到.php经验有限,不到位的地方,欢迎帮忙指正. ...

  2. laravel5.1启动详解

    laravel的启动过程 如果没有使用过类似Yii之类的框架,直接去看laravel,会有点一脸迷糊的感觉,起码我是这样的.laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有 ...

  3. Java Interview Reference Guide--reference

    Part 1 http://techmytalk.com/2014/01/24/java-interview-reference-guide-part-1/ Posted on January 24, ...

  4. laravel 服务容器

    服务容器,也叫IOC容器,其实包含了依赖注入(DI)和控制反转(IOC)两部分,是laravel的真正核心.其他的各种功能模块比如 Route(路由).Eloquent ORM(数据库 ORM 组件) ...

  5. laravel启动过程简单解析

    :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px ...

  6. laravel框架容器管理

    来自http://www.cnblogs.com/chy1000/p/7072936.html 本文面向php语言的laravel框架的用户,介绍一些laravel框架里面容器管理方面的使用要点.文章 ...

  7. laravel的启动过程---摘自网络博客个人学习之用

    如果没有使用过类似Yii之类的框架,直接去看laravel,会有点一脸迷糊的感觉,起码我是这样的.laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有助于得心应手的使用框架,希 ...

  8. laravel的启动过程解析

    laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有助于得心应手的使用框架,希望能对大家有点帮助. 统一入口 laravel框架使用了统一入口,入口文件:/public/ind ...

  9. laravel框架容器管理的一些要点(转)

    本文面向php语言的laravel框架的用户,介绍一些laravel框架里面容器管理方面的使用要点.文章很长,但是内容应该很有用,希望有需要的朋友能看到.php经验有限,不到位的地方,欢迎帮忙指正. ...

随机推荐

  1. Revit二次开发示例:AutoStamp

    该示例中,在Revit启动时添加打印事件,在打印时向模型添加水印,打印完成后删除该水印.   #region Namespaces using System; using System.Collect ...

  2. hihocoder#1046 K个串 可持久化线段树 + 堆

    首先考虑二分,然后发现不可行.... 注意到\(k\)十分小,尝试从这里突破 首先用扫描线来处理出以每个节点为右端点的区间的权值和,用可持久化线段树存下来 在所有的右端点相同的区间中,挑一个权值最大的 ...

  3. python学习两月总结_汇总大牛们的思想_值得收藏

    下面是我汇总的我学习两个月python(version:3.3.2)的所有笔记 你可以访问:http://www.python.org获取更多信息 你也可以访问:http://www.cnblogs. ...

  4. SQL 脚本中的全角逗号引起【ORA-01756: 引号内的字符串没有正确结束】

    今天运行壹個小程序,功能是读取指定目录下的 SQL 脚本,并加载到内存中批量执行,之前的程序运行良好.但是今天相关开发人员更新了其中壹個 SQL 脚本,于是程序运行的时候就出错了,错误提示信息如下:批 ...

  5. rac 10g 10.2.0.1升级到10.2.0.5具体解释

        RAC 10.2.0.1 升级到 10.2.0.5 一. 准备: Patch 包:p8202632_10205_LINUX.zip   节点数:3个节点       RAC1    RAC2  ...

  6. 在EntityFramework6中管理DbContext的正确方式——4DbContextScope:一个简单的,正确的并且灵活的管理DbContext实例的方式(外文翻译)

    (译者注:使用EF开发应用程序的一个难点就在于对其DbContext的生命周期管理,你的管理策略是否能很好的支持上层服务 使用独立事务,使用嵌套事务,并行执行,异步执行等需求? Mehdi El Gu ...

  7. 与Win8之磁盘活动时间100%斗争心得

    Windows8因人而异地会在使用过程中磁盘活动时间无缘无故提升到100%并且可能出现持续性抽风现象,具体表现为0%瞬间飙升至100%后又回落,或者一直保持在100%导致使用过程卡顿,认真阅读本文有助 ...

  8. WebView具体介绍

    PART_0    侃在前面的话 WebView是Android提供给我们用来载入网页的控件.功能非常强大.我们经常使用的手机淘宝.手机京东的Androidclient里面大量使用到了WebView. ...

  9. Major GC 是清理老年代。 Full GC 是清理整个堆空间—包括年轻代和老年代。

    Major GC 是清理老年代. Full GC 是清理整个堆空间—包括年轻代和老年代.

  10. 让一个view 或者控件不支持拖拽

    让一个view 或者控件不支持拖拽: dragView.userInteractionEnabled = NO;