得到一个xml型的对象:
$items=$resp->items;
读取对象的值,就用$items->item,或$items->item->price。
php提供了array方法将对象转换成数组,只需将转换数组的对象前面加上(array)即可。
例如,将$items->item(有很多item的对象)转换成数组:
$goods[]=(array)$item;
}
$goods即为一个php数组了。
转换前:
(
[cid] => 50003793
[modified] => 2013-04-18 17:16:25
[nick] => qq307819623
[price] => 200.00
[title] => Nokia N97全新行货
)
SimpleXMLElement Object
(
[cid] => 50024921
[modified] => 2013-04-18 16:58:06
[nick] => qq307819623
[pic_url] => http://www./i2/19325021969376698/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 888888.00
[title] => 刘俊仲
)
SimpleXMLElement Object
(
[cid] => 1512
[modified] => 2013-04-18 16:56:46
[nick] => qq307819623
[pic_url] => http://www./i2/19325023881567971/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 323232.00
[title] => 二手你好
)
SimpleXMLElement Object
(
[cid] => 50012166
[modified] => 2013-04-18 15:10:07
[nick] => qq307819623
[pic_url] => http://www./i2/19325034513112454/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 32.00
[title] => 放大率拉德斯基分拉沙德疯了似的看法拉斯法
)
转换后:
(
[0] => Array
(
[cid] => 50003793
[modified] => 2013-04-18 17:16:25
[nick] => qq307819623
[price] => 200.00
[title] => Nokia N97全新行货
)
[1] => Array
(
[cid] => 50024921
[modified] => 2013-04-18 16:58:06
[nick] => qq307819623
[pic_url] => http://www./i2/19325021969376698/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 888888.00
[title] => 刘俊仲
)
[2] => Array
(
[cid] => 1512
[modified] => 2013-04-18 16:56:46
[nick] => qq307819623
[pic_url] => http://www./i2/19325023881567971/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 323232.00
[title] => 二手你好
)
[3] => Array
(
[cid] => 50012166
[modified] => 2013-04-18 15:10:07
[nick] => qq307819623
[pic_url] => http://www./i2/19325034513112454/T1hc87XB8hXXXXXXXX_!!0-item_pic.jpg
[price] => 32.00
[title] => 放大率拉德斯基分拉沙德疯了似的看法拉斯法
)
)
本节内容:
phpQuery占用内存过多的问题
phpQuery是一个用php实现的类似jQuery的开源项目,可以在服务器端以jQuery的语法形式解析网页元素。
相对于正则或其它方式匹配网页方式,phpQuery使用起来要方便的多。
在使用phpQuery采集网页时,遇到一个问题:在处理大量网页之后,phpQuery占用的内存数量非常惊人(很快就超过了1G),
例如:
while (true) {
phpQuery::newDocumentFile($htmlFile);
// 处理网页元素...
echo memory_get_usage() . "\n";
}
注意:以上代码会用光你机器的内存。
问题分析:
phpQuery在每处理一个网页就会产生一个DOMDocumentWrapper 对象,而每个DOMDocumentWrapper 对象会被保存在静态成员$documents中(phpQuery::createDocumentWrapper中),这个变量是一个数组,每解析一个网页数组元素就增加一个。
phpQuery::$documents[$wrapper->id] = $wrapper;
解决方法:
每次解析完一个网页,把phpQuery::$documents置空即可。
例如:
while (true) {
phpQuery::newDocumentFile($htmlFile);
// 处理网页元素...
phpQuery::$documents = array();
echo memory_get_usage() . "\n";
}
如此,内存占用便稳定下来了。
本节内容:
PHP 静态变量 缓存
来看一段代码:
帮助用户重置密码,requestResetPassword是接收用户重置密码的请求并且做了相应的检查。
为了提高复用性,将重置密码的操作单独分配到一个新的resetPassword的函数,更改完密码的后再调用sendEmail向用户发送一封通知邮件。
例子:
<?php
/**
* 用户请求重置密码的接收器
*/
function requestResetPassword() {
//检查用户是否存在
if( !checkUserExists( $_GET['userid'] ) ) {
exit('抱歉,用户不存在,请确认用户帐号。');
}
resetPassword( $_GET['userid'] );
//最后向用户发送一封邮件
sendEmail( $_GET['userid'], '重置密码成功', '新的密码是xxxx' );
exit('新密码已经发送到你的邮箱。');
}
/**
* 帮助用户重置密码
*/ www.
function resetPassword( $userid ) {
//检查用户是否存在
if( !checkUserExists( $userid ) ) {
return false;
}
//进行重置用户密码的操作
//略...
return true;
}
/**
* 向用户发送一封邮件
*/
function sendEmail( $userid, $title, $content ) {
//检查用户是否存在
if( !checkUserExists( $userid ) ) {
return false;
}
//发送邮件操作
//略...
return true;
}
/**
* 检查某个用户是否存在
*/
function checkUserExists( $userid ) {
$user = getUserInfo( $userid );
return !empty( $user );
}
/**
* 获取某个用户的数据
*/ www.
function getUserInfo( $userid ) {
//假设我有一个query的函数,它用来查询数据库并返回数据
$user = query( "SELECT * FROM `user` WHERE `uid`=" . intval( $userid ) );
return is_array( $user ) ? $user : array() ;
}
存在的问题:
这三个函数都同时使用checkUserExists这个函数来检查用户不存在,数据库查询了三次,这样带来了一些额外的开销。
如果要去掉三者之间任意一个checkUserExists,看上去是可能的。
但是,如果之后有某些功能要调用resetPassword或者sendEmail,用户不存在时,系统可能会发生错误。
还有一个解决方法是,将resetPassword的逻辑写到requestResetPassword里,再过一点,把sendEmail的逻辑也写进去。这样函数调用减少,数据库查询也变成一次了,性能得到了提高。但是重置密码和发送邮件的功能将不能得到复用,并且违背了单一责任的原则,代码复杂度也提高了。
不过,因为函数分离和复用性都很好,如果实际性能受到影响,可能考虑用缓存的方法减少数据库查询,修改了下共用的checkUserExists函数:
<?php
/**
* 检查某个用户是否存在
*/
function checkUserExists( $userid ) {
//增加一个缓存,用以记录检查用户的结果
static $cache = array();
//检查当前用户是否已经检查过一次
if( isset()( $cache[ $userid ] ) ) {
return $cache[ $userid ];
}
$user = getUserInfo( $userid );
//把结果记录到缓存中
$cache[ $userid ] = !empty( $user );
return $cache[ $userid ];
}
也可以用同样的方法改动getUserInfo函数。
小结:
当代码的复用性提高时,想提高性能是很简单的,性能的瓶颈也很容易被发现和修改。
可能为了复用而将遍历封装到一个函数中,并且多次使用它。
这些开销对项目根本没有预想中那样有太大的影响,或说是微乎其微的。
因此,更愿意将时间花在如何提高代码的复用性和维护性方面,而不是纠结于浪费多这一点性能。
实际性能如果真的达不到要求,也可以权衡增加硬件配置。