Zend_Framework 变量输出、错误抛出与日志

使用 Zend_Debug::dump() 可以很方便的在开发项目时Debug,你可以很容易地增加或移除它。

你也可以考虑使用 Zend_Log 来调试,用于更长期的非短暂性的调试和监控。例如,你可以使用 DEBUG 记录级别和 Stream 记录器来输出 Zend_Debug::dump() 返回的信息。

Zend_Debug

Zend_Debug::dump($var, $label=null, $echo=true)
$var 参数指定了需要打印信息的表达式或变量。

$label 标签参数是用来加在 Zend_Debug::dump() 输出信息之前的一段文本,可以用来区分多个变量信息。

$echo用于控制Zend_Debug::dump() 是否输出。

原理:Zend_Debug::dump() 方法封装 PHP 函数var_dump()。如果输出流被检测为 web 输出,var_dump() 的输出结果使用 htmlspecialchars()转义,并封装(X)HTML的 pre 标签。

Zend_Log

Zend_Log 是一个通用日志组件. 它支持多个日志后端,格式化发送给日志的消息,过滤被纪录的消息.这些功能被划分为如下的对象:

Zend_Log

一个Log (Zend_Log的实例)是应用程序使用最多的对象.Log对象的数量不受限制.一个Log对象必须至少包含一个Writer对象,可以包含零个,一个或多个Filter.
1.创建Log

//方法一
$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('php://output');
$logger->addWriter($writer);
//方法二
$writer = new Zend_Log_Writer_Stream('php://output');
$logger = new Zend_Log($writer);

2.日志消息
要纪录消息,调用Log实例的log()方法,并向其传递消息和消息等级.

//方法一
$logger->log('Informational message', Zend_Log::INFO)
//方法二
$logger->log('Informational message', 6)
//方法三
$logger->info('Informational message');

log()方法的第一个参数是是一个字符串message,第二个参数是一个整数priority. priortiy必须是一个可以被Log实例识别的消息等级之一.
默认的消息等级

EMERG   = 0;  // Emergency: 系统不可用
ALERT   = 1;  // Alert: 报警
CRIT    = 2;  // Critical: 紧要
ERR     = 3;  // Error: 错误
WARN    = 4;  // Warning: 警告
NOTICE  = 5;  // Notice: 通知
INFO    = 6;  // Informational: 一般信息
DEBUG   = 7;  // Debug: 小时消息

你可以定义重要性低于DEBUG的属性. 当在日志消息中选择消息等级时,要知道消息等级的层次并选择合适的消息等级.
用户定义的消息等级可以在运行时通过Log对象的addPriority()方法添加:
$logger->addPriority('FOO', 8);
上面的代码片断创建了一个新的日志消息等级, FOO,它的值为 8, 这个新的消息等级可以被用于日志:

$logger->log('Foo message', 8);
$logger->foo('Foo Message');

3.销毁Log
$logger = null;
Writer会在Log对象被销毁前自动地被销毁,且php页面关闭前自动销毁Log。

Writers
一个Writer是继承自Zend_Log_Writer_Abstract类的一个对象.Writer的职责是向存储后端纪录日志数据,主要有两种方法。

1.写入到数据库
Zend_Log_Writer_Db使用Zend_Db写入日志信息到数据库表中. Zend_Log_Writer_Db的构造函数接受一个Zend_Db_Adapter 实例,一个表名,和一个数据库字段到事件数据项的映射:

$params = array ('host'     => '127.0.0.1', 'username' => 'malory', 
                'password' => '******', 'dbname'   => 'camelot');
$db = Zend_Db::factory('PDO_MYSQL', $params);

$columnMapping = array('lvl' => 'priority', 'msg' => 'message');
$writer = new Zend_Log_Writer_Db($db, 'log_table_name', $columnMapping);

$logger = new Zend_Log($writer);

$logger->info('Informational message');

上面的例子写入单个行到名称为log_table_name的数据库表中.数据库字段 lvs 接收优先级号,名为 msg 的字段接收日志消息.

2.写入到流(Streams)
Zend_Log_Writer_Stream 写入日志数据到 PHP 流中.

要把日志写入到输出缓冲区,使用URLphp:://output. 或者你可以直接发送日志数据到像STDERR 这样的流中(php://stderr).

$writer = new Zend_Log_Writer_Stream('php://output');
$logger = new Zend_Log($writer);

$logger->info('Informational message');

3.写入到文件,使用Filesystem URLs之一:

$writer = new Zend_Log_Writer_Stream('/path/to/logfile');
$logger = new Zend_Log($writer);

$logger->info('Informational message');

默认情况流以一个追加(“a”)的方式打开,要以不同的模式打开可以设置第二个参数.

Zend_Log_Writer_Stream还接受一个现有的流资源:

$stream = @fopen('/path/to/logfile', 'a', false);
if (! $stream) {
    throw new Exception('Failed to open stream');
}

$writer = new Zend_Log_Writer_Stream($stream);
$logger = new Zend_Log($writer);

$logger->info('Informational message');

你不能给现有的流资源指定模式.这样作将导致抛出一个Zend_Log_Exception异常.

4.关闭Writer
Zend_Log_Writer_Null 时不向任何地方写入. 用于在测试期间关闭日志.

$writer = new Zend_Log_Writer_Null;
$logger = new Zend_Log($writer);

// 无路可去
$logger->info('Informational message');

5.测试 Mock
Zend_Log_Writer_Mock是一个非常简单的Writer,它纪录所接收到的原始的数据到数组中.

$mock = new Zend_Log_Writer_Mock;
$logger = new Zend_Log($mock);

$logger->info('Informational message');

var_dump($mock->events[0]);

// Array
// (
//    [timestamp] => 2007-04-06T07:16:37-07:00
//    [message] => Informational message
//    [priority] => 6
//    [priorityName] => INFO
// )

清空有mock记录的日志,设置$mock->events = array()即可.

6.组合Writers
没有复合Writer对象,但是一个Log实例可以有任意个Writer.使用addWriter方法 添加Writer:

$writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile');
$writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile');

$logger = new Zend_Log();
$logger->addWriter($writer1);
$logger->addWriter($writer2);

// goes to both writers
$logger->info('Informational message');

Formatters
一个 Formatter (实现了 Zend_Log_Formatter_Interface接口) 在由Writer写入数据之前可以对日志数据进行格式化.每一个Writer只能有一个Formatter.

Formatter是一个负责取得一个描述日志事件的event数组并输出一个格式化的日志行的对象.

有些Writer不是面向行的并且不能使用Formatter.比如数据库Writer,它向数据库中直接插入一个事件项. 对于这样的Writer不支持Formatter,如果你对这样的Writer设置一个Formatter将抛出一个异常.

1.简单格式化
Zend_Log_Formatter_Simple 是默认的.当未指定任何formatter时使用. 默认的配置等同于下面的配置:

<?php
$format = '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);

使用Writer的setFormatter()方法在个别的Writer上设置Formatter:

<?php
$writer = new Zend_Log_Writer_Stream('php://output');
$formatter = new Zend_Log_Formatter_Simple('hello %message%' . PHP_EOL);
$writer->setFormatter($formatter);

$logger = new Zend_Log();
$logger->addWriter($writer);

$logger->info('there');

// outputs "hello there"

Zend_Log_Formatter_Simple的构造函数接受单个参数: 格式化字符串.该字符串包含有单个百分号包裹的键(例如,%message%).
格式化字符串可以包含来自于任何事件数据数组的键。
在 Zend_Log_Formatter_Simple 里使用 DEFAULT_FORMAT 常量,可以获取缺省键。

2.格式化到XML
Zend_Log_Formatter_Xml格式化日志数据到XML字符串中. 默认的它自动地纪录在事件数据数组中的所有项.

<?php
$writer = new Zend_Log_Writer_Stream('php://output');
$formatter = new Zend_Log_Formatter_Xml();
$writer->setFormatter($formatter);

$logger = new Zend_Log();
$logger->addWriter($writer);

$logger->info('informational message');

上面的代码输出下面的XML(为清晰添加了空格):

<logEntry>
  <timestamp>2007-04-06T07:24:37-07:00</timestamp>
  <message>informational message</message>
  <priority>6</priority>
  <priorityName>INFO</priorityName>
</logEntry>

可以定制根元素并指定一个到事件数据数组的XML元素映射. Zend_Log_Formatter_Xml的构造函数接受一个根元素名字的字符串作为第一个参数和一个元素映射的关联数组作为第二个参数:

<log>
  <msg>informational message</msg>
  <level>INFO</level>
</log>

25.1.6. 理解日志事件
当你调用log()方法或它们的快捷方式时,日志事件即被创建.这是一个简单的关联数组, 默认创建:timestamp, message, priority, and priorityName.

event数组的创建是完全透明的.但是对于添加上面默认设置中不存在的项, 对event数组的了解是必须的.

给每个将来的事件添加新项,用给定的键值调用setEventItem()方法:

$logger->setEventItem('pid', getmypid());

上面的例子设置了一个名为pid的新项并设置它为当前进程的PID.一旦一个新的项被设置, 在日志纪录中,它自动对其他所有writer和所有事件数据可用.一个项可以在任何时候再次调用setEventItem() 方法被覆盖.

用setEventItem()设置一个新的事件项将导致新项发送给Logger的所有Writer.但是 这不能保证writer实际地纪录了该项.这是由于writer并不知道该怎么做,除非formatter通告了一个新项.

过滤器
一个Filter对象用于阻止消息写入日志.

一个 Filter (实现 Zend_Log_Filter_Interface接口)阻塞数据被保存.一个Filter可以应用到个别的Writer, 或则在所有Writer之前应用到一个Log.这样Filter是串联起来的.

1.对所有Writer过滤

要在所有writer之前过滤消息,你可以使用addFilter()方法添加任意数量的Filter到Log对象:

$logger = new Zend_Log();

$writer = new Zend_Log_Writer_Stream('php://output');
$logger->addWriter($writer);

$filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);//阻止了CRIT以下的信息
$logger->addFilter($filter);

// blocked
$logger->info('Informational message');

// logged
$logger->emerg('Emergency message');

当你添加一个或多个Filter到Log对象后,消息在任何Writer接收之前必须通过所有的Filter.

25.4.2. 过滤一个Writer实例
要在一个特定的Writer上进行消息过滤,使用该Writer对象的addFilter()方法:

$logger = new Zend_Log();

$writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile');
$logger->addWriter($writer1);

$writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile');
$logger->addWriter($writer2);

// add a filter only to writer2
$filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);
$writer2->addFilter($filter);

// logged to writer1, blocked from writer2
$logger->info('Informational message');

// logged by both writers
$logger->emerg('Emergency message');

Zend_Exception

<?php

try {
    Zend_Loader::loadClass('nonexistantclass');
} catch (Zend_Exception $e) {
    echo "Caught exception: " . get_class($e) . "\n";
    echo "Message: " . $e->getMessage() . "\n";
    // 处理错误的代码
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值