使用 PDOStatement->execute() 执行查询时出现错误:
Message: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
经过测试发现是因为在前一次 execute 里面执行了多条SQL语句(即通过分号分隔连续执行了多次的select/insert/update)。
看上去应该是 Pdo_Mysql 库本身存在的问题?没有找到比较好的解决方案。唯一比较笨的方法是:在执行了 multi-query 语句之后立即 closeConnection ,断开本次数据库连接。再下次查询之前先重新建立连接。这样 unbuffered queries 就被重置了。
使用 PHPExcel 来生成 excel 文档是比较消耗内存的,有时候可能会需要通过一个循环来把大数据切分成若干个小的 excel 文档保存来避免内存耗尽。
然而 PHPExcel 存在 circular references 的情况(貌似在最新的 1.6.5 版本中仍然没有去解决这个问题),如果在一次 http 请求过程中反复多次构建 PHPExcel 及 PHPExcel_Writer_Excel5 对象实例来完成多个 excel 文档生成操作的话,所有被构建的对象实例都无法在 http 请求结束之前及时释放,从而造成内存泄漏。
解决办法是在 PHPExcel_Worksheet 类中增加方法:
public function Destroy() {
foreach($this->_cellCollection as $index => $dummy) {
$this->_cellCollection[$index] = null;
}
}
并在 PHPExcel 类中增加方法:
public function Destroy() {
foreach($this->_workSheetCollection as $index => $dummy) {
$this->_workSheetCollection[$index]->Destroy();
$this->_workSheetCollection[$index] = null;
}
}
然后在需要资源回收的地方显式的调用 PHPExcel::Destroy() 来处理循环引用的问题。注意 __destruct() 方法是在对象被认为可以被释放的时候才会被调用,所以循环引用的处理不能放到 __destruct() 来进行。
据说PHP5不建议和Apache的 worker MPM 搭配使用,但之前就是拿 PHP 5.2.6 + Apache 2.2.4 worker MPM 来跑服务,效果貌似挺好。
后来重新编译了一次 PHP 之后 Apache 就报错了:Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP. Pre-configuration failed!
网上通常说的使用 --with-experimental-zts 参数以及 --enable-maintainer-zts 参数统统试了一遍,结果编 PHP 的时候就通不过了。只有改成使用 prefork MPM。
困扰了N久,最后才发现是因为重编 PHP 的时候加了 --with-openssl 把openssl 模块加进去了的缘故,去掉这个模块就又可以正常与 worker MPM 搭配了。
前些日子一篇N久之前的老文忽然成了被阅读的热点,检查之后才发现自己使用那段代码来做pr查询的页面已经不能正常得到URL的Page Rank值了,取而代之的是一大段“In your email, please send us the entire code displayed below”之类的Google terms_of_service错误提示信息。看来是原先的接口已经失效了。
但我装在Firefox工具栏的扩展插件SearchStatus仍然能够正常解析出每个受访页的PR值,找到 SearchStatus 的插件包解开来看源码,果然是使用了不一样的验证码生成算法,在原先的 checksum 生成之后,还需要再进行一次计算,两次演算之后得到的才是正确的ch参数。
于是拿现成的js代码改造一番之后,新的PHP版本的 Google PageRank 查询接口方法就出来了。经过本地测试之后,谁想传到服务器之后又出现了该死的 terms_of_service 错误提示。把checksum的计算过程一步步打出来,发现经过了几次右位移之后本地和服务器上的数字就不一样了。这才想到服务器是64位机,32位系统下位移之后应该被cut掉的bit在那里就活得好好的。加了个 trunkbitForce32bit 方法,对所有算术运算之后的数值进行高位屏蔽,算是搞定了64位系统下的多余位问题。结果拿到32位Linux环境下跑又不兼容了,原因是PHP在进行算术处理出现溢出时,会自动尝试将int转为float。当发生的是负数溢出时,这一操作在Windows下能正确保留精度,但在Linux下就有问题了。
下面这段代码:
$a = -4294967295;
echo dechex($a)."<br />\n";
if ( $a < 0 ) $a += 4294967296;
echo dechex($a)."<br />\n";
第一个echo在Windows下能够正确输出该负数低32位的补码,而在32位Linux机上输出的则是int类型所能表示的最大负数0x80000000了。只有通过取巧的方式给这个溢出的大负数加上一个超出整数范围的大整数来抵消掉溢出的部分,才能复原低32位应该有的样子。
使用这些非常规手段,终于炮制出这个更新版的兼容Linux32/Linux64/Windows的Google PR值查询接口的PHP脚本实现(含完整代码)。
参考:
php异或运算的不可靠性
PHP vs. BIGINT vs. float conversion caveat
http://www.teamworksusa.com/RDS275/HydroWorks275/keygen.php
在 Zend Framework 中, Db_Adapter 提供 quoteInto 方法用于查询变量嵌入的统一处理。但在该方法最终调用的底层方法 _quote 中,会用 is_numeric 先判断变量是否是数字,如果是的话就直接返回了,只有非数字型的内容才会被进行转义并加引号。
这样的处理带来的问题是,当你使用数据库自带的 MD5 函数对字符串(比如用户密码)进行 md5 加密时,如果恰好字符串是纯数字,又恰好是0打头的数字,比如“07902”,这时候 MD5(07902) 和 MD5('07902') 返回的结果是不一样的,从而造成潜在的数据错误。
一般我都习惯于给所有的变量都加上引号,不知道 zf 是基于什么考虑对数字型变量进行单独处理。。
CentOS 服务器上的 LANG=en_US.UTF-8 ,当php脚本里面使用了 fgetcsv 对某个 GBK 编码的 csv 文件进行解析之后, basename 函数就再也无法正常工作了,每次调用返回的文件名始终为空字符串,该问题甚至会在整个 apache 的 httpd 线程生命周期内存在。 windows 下似乎不会出现这种情况。
解决方法:在用 fgetcsv 处理文件之前先设置 setlocale(LC_ALL,'zh_CN.GBK'); 或者通过 iconv / mb_convert_encoding 等方式将整个 GBK 编码的文件先转化为 utf-8 编码。
理论上来说 fgetcsv 应该只是一个字符串解析的过程,即便输入字符串的编码格式出现问题,最多也就是解析返回的数组乱掉而已,怎么会影响到 basename 函数的正常运作并在线程周期内持续作怪?从 php 的源代码来看似乎也没什么特别的操作,依然困惑中。
本来拿 PHP Standalone OpenID Server 的代码改装出来的 Zeal OpenID Server 纯属好玩,最近发现对 OpenID 感兴趣的朋友日渐增多,发信留言询问相关的东西。所以干脆把整个汉化修改之后的 Zeal OpenID Server 整站源码打了个包,喜欢研究的朋友自己 down 一个下来瞧瞧吧。
如果使用过程中有什么问题,最好自己去搞定,俺不负责技术解答,嘿嘿 :)
gz 压缩包:
openid.zeali.net.tar.gz zip 压缩包:
openid.zeali.net.zip
Just Copy the whole folder to your server .
create a database ,
import tables information of file zeal_openid_server.sql
change config.php to fit your requirements.
default settings in config.php:
administrator user : admin
administrator pass : 123456
db host : localhost
db name : zeal_openid_server
db user : openuser
db pass : 123456
- Five common PHP design patterns
设计模式这东西就像孙子兵法,高度的概括性和广泛的适用性是它们的特点。但运用之后的结果究竟是快马一鞭抑或南辕北辙就不能一概而论了。
对于没有足够实战经验积累的人来说,读再多次可能也只是把几个经典名词烂熟于胸而已;拿来忽悠老板或者面试官固然很有份量,真要到理论付诸实践的时候往往就会大帽子乱扣,整出个四不像来。相反很多人只是根据项目的需求去设计各种各样最恰当的系统,但从来没想过这倒是该叫什么模式。运用之妙,存乎一心。就看你是在理解的基础上去总结,还是用条条框框来给自己下套了。 - JavaScript Code Improver
JavaScript代码格式化工具。 - 和谐社会需要恶搞
“什么才是和谐社会,那就是保护一切人的应有的权利!”
这几天一直没办法通过 del.icio.us 的 API 接口抓到当天的网摘信息,开始还以为自己没摘录过东西(最近确实懒了很多),后来觉得不对劲,猜测应该是 del.icio.us 修改了 API 接口,但一直忙着其他琐事也就没顾上去美味网站上查个究竟。
今天凑巧从 Jeremy Zawodny's blog 上看到了原因,原来 API 改成了 https,地址也从 http://del.icio.us/api/ 变到了 https://api.del.icio.us/v1/ 。这样一来想要通过 PHP 的 fsockopen 来访问 API 的话就必须实现 ssl 协议通讯,费事不少。好在可以用 curl 来作为替代的简单解决方案。Edward Eliot 提供的这个PhpDelicious类正是使用curl来处理了新的API接口。
在PHP中有些诸如 call_user_function() 或 usort() 的函数接受用户自定义的函数作为一个参数。Callback 函数不仅可以是一个简单的函数,它还可以是一个对象的方法,包括静态类的方法。
一个 PHP 函数用函数名字符串来传递。您可以传递任何内建的或者用户自定义的函数,除了 array(), echo(), empty(), eval(), exit(), isset(), list(), print() 和 unset()。
一个对象的方法以数组的形式来传递,数组的 0 下标指明对象名,下标 1 指明方法名。
对于没有实例化为对象的静态类,要传递其方法,将数组 0 下标指明的对象名换成该类的名称即可。
Callback 函数实例
<?php
// An example callback function
function my_callback_function() {
echo 'hello world!';
}
// An example callback method
class MyClass {
function myCallbackMethod() {
echo 'Hello World!';
}
}
// Type 1: Simple callback
call_user_func('my_callback_function');
// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod'));
// Type 3: Object method call
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));
?>
http://www.phpe.net/manual/language.pseudo-types.php
http://cn.php.net/manual/en/language.pseudo-types.php
- Digg PHP's Scalability and Performance
从硬件、数据库、语言解释三个方面来分析PHP支撑高负载应用的能力。通过合理利用 Apache 2 的 worker threads , FastCGI 以及 APC , MCache 等 PHP 加速扩展, 即便完全使用 OO 的原则来设计编写 PHP 代码(一般来说对于 PHP 这样的解释性语言引入面向对象的代码之后将大大降低其执行效率),也能够获得很高的性能。 - 重要图书: MySQL Stored Procedure Programming
- How do I change timezone for PHP?
- MySQL服务维护笔记
MySQL日常维护管理的一些要点。 - 10 Stupid Mistakes Made by the Newly Self-Employed
- 史上最强的幽默插图欣赏
- 有害食物的“解药”
- Code Igniter
an Open Source Web Application Framework that makes writing kick-ass PHP programs simple as apple pie。 这是 CodeIgniter 对自己的一个描述。看看别人是如何评价的:CodeIgniter: the PHP answer?
确实, Rails 的横空出世带给 PHP 巨大的震动。大家突然发现一个好的框架可以成就一个语言;而再美妙的语言如果缺乏一套强大易用的框架来支撑,多少会显得中气不足。于是,各式各样的 framework 应运而生, Zend 也急吼吼的占了个坑先。然而就目前来看,真正愿意去使用“别人”设计的 PHP framework 的开发者并不算多。更多时候我们宁愿按照自己实际应用的特点来实现一套自己的 framework -- 这样做至少不用去阅读一大堆的文档来熟悉理解别人的设计思路。
最近不断有朋友问我关于 framework 的问题,或者让我推荐一款框架。但实际上,虽然我自己也很希望能挑出一个比较满意的框架来支撑日常 web 应用的开发,可挑来挑去挑花了眼,文档也看了,别人的评测文章也读了,代码也 Down 下来研究了,到头来现在用的还是自己写的一套东西:虽然简陋,可是够用、好用。 PHP framework 的现状就好比战国争雄,风云变幻,快到你不敢轻易去接受。虽然我看好 CakePHP ;也觉得 Zend 亮的第一招虽不算惊艳但后劲十足;可也仅限于观望而已。
这次这个 Code Igniter ,同样雄心勃勃。在今年的两月份发布了第一个 beta 1.0 版本,到四月初已经是最新的 version 1.3 。同样 Down 了它的 1.3 版本粗略浏览了一番,有几个初步印象:- 其兼容于 PHP 4.x 的代码目前来说是好事,但对于以后的扩展就不见得有利。
- 文档化工作相当细致,条理也很清晰,这对于快速理顺思路,上手使用非常重要。
- 可以方便的在 framework 中创建多个 web application。
- 用一套 Help 函数集来封装了许多常用的重复性功能,比如文件操作/安全性控制/XML解析等。实际上即便不想使用一整套框架,单独把这套 Help 函数集拎出来也不错。
- ActiveRecord/Scaffolding/Logging/Caching/Template/URI Routing等常规功能的支持。不过似乎没发现关于 Ajax 方面的内容。
- AWF-CMS.org
Open Source Content Management System - 全面迎接SVN时代来临
- Subversion安装手记
眼下正在考虑到底是用 CVS 还是 SVN 来做 source control server 。既然 SVN 与 CVS 相比有那么多的优点,没道理还抱着老祖宗不放了。
- A Practical Tutorial of Zend Framework
- Getting an RSS feed with the Zend framework 0.1.1.
- A PHP 6 overview
register_globals等不安全的配置参数将被完全摒弃。对于不少老的php代码来说可不是件好事。 - web2.0关程序员什么事?
通过 UNIX_TIMESTAMP 函数把 MySQL 数据库中的 date 类型数据转换成 unix timestamp 形式的一个整形数字:
select UNIX_TIMESTAMP('2006-02-28') testdate;
按理说得到的时间戳应该可以直接拿来给 PHP 的 date() 等函数使用。但奇怪的是:
echo date("Y-m-d",$testdate);
显示出来的日期跟数据库实际的日期相比却少了一天,百思不得其解。反复查看 MySQL 关于 UNIX_TIMESTAMP 函数的说明,终于发现问题所在:“The server interprets date as a value in the current time zone and converts it to an internal value in UTC.” 原来 MySQL 的 UNIX_TIMESTAMP 函数得到的时间戳是 UTC 时间,而不是服务器设定的特定 Time zone 的时间。经过这样一转化,时间戳就凭空少了8个小时(对于咱这里来说),而 PHP 中的 timestamp 则计算的都是系统设定时区的当地时间。因此 2006-02-28 这个日期被减去了8个小时,自然变成了2006-02-27。
解决方法:把这八个小时加回去(UNIX_TIMESTAMP('2006-02-28' + INTERVAL 8 HOUR));或者弃用 UNIX_TIMESTAMP 函数, 直接得到 MySQL date 字符串之后通过 strtotime() 函数来把字符串转化成真正的本地时间戳。
- List of MVC Frameworks Written in PHP
搜集的比较齐全的PHP MVC frameworks清单。可惜没有各自好坏的比较。 - Sphider - a php spider and search engine
一个轻量级的PHP+MySQL搜索引擎。 - 没有了MySQL,能用Linux做的事情多着呢
其实这世界缺谁不行?它不免费自有后来人;即便免费的死绝了,大不了掏点钱买正版的去啊。再说了,Oracle收费收了这么多年,国内有多少家公司是花了钱买来的。 - 一个 HTML 的网页:Unipage 发布
Unipage就是一个把包括图片、CSS、JavaScript、Flash 和任何其他什么玩艺的网页就放入一个真正的 HTML 文件。当试图用 ie 打开这种 html 以便和 mht 格式比较一下时... - unserialize Yahoo! search results
Yahoo! have started exposing their search data as serialized PHP strings. That’s “serialized” as in the serialize function.Is this format safe?
- 10 Creative Commons Tips
- A PHP Easter Egg
PHP的彩蛋。隐藏的小狗。 - xampp for windows
配置apache及相关工具的傻瓜包。免去自己一个个下载安装的麻烦。 - Will the Zend Framework save PHP ?
对于写代码不喜欢排格式,或者需要去读别人留下的一堆写的极其丑陋的代码的程序员来说,可以试试 Beautify PHP 带给你的便利。这个系统还可以把源代码的函数自动整理到文件的头部作为注释,很实用的一个功能。以前一直觉得JBuilder的代码Reformat功能很酷,看来PHP也可以看上去很美俄。
Who needs it:
- people, who get PHP code from other coders and are slightly confused
- people, who can't read their own PHP code anymore
- people, who want to share their PHP code
Basic features:
- automatic indentation of PHP source code according to given number of spaces
- automatic newlines, if required
- includes settings for braces according to C or PEAR style
- can make use of PHPs integrated code highlight option
- can limit number of chars per line. This will break the code at a space and outputs the rest on the next line with an additional indent. (I used this to reformat my code to put it in a LATEX document. This PHP code normally can't be executed anymore, it is only useful for printout.)
- turn off and on beautifying by inserting "// NO_BEAUTIFY" or "// BEAUTIFY" in source code
phpXplorer是一个很酷的Web界面的服务器文件管理系统。只需要有PHP环境即可。能够通过浏览器进行服务器上文件的添加删除上下载等各种操作。具有用户/角色权限管理功能。如果Web Server是Apache的话可以提供更加高级的服务。
里面有个“共享”的概念。类似可访问目录。用root用户登陆以后再右边那个窗口的“系统”菜单选择之后可以进行管理员的各种管理操作。其中可以添加“可用共享”,即添加一个可以提供给用户访问的目录。然后把这个共享提供给某个用户或者角色,这些人就能看到这个目录下的东西并进行“文件”操作。
好像网上没找到汉化的版本,自己做了一个。同时这个系统没有操作日志记录功能,对于需要多用户使用的环境来说是一个缺憾。因此在我的这个汉化版本里面增加了日志记录功能,对于关键的文件添加/修改/删除操作进行了Logging。
初始超级用户: root / root
解压之后整个目录上传即可。首次访问会自动跳转到system/install.php进行安装检测,如果一切设置都没问题就可以进入使用了,否则请安装install界面的提示信息对错误进行修正。
原始英文版本(1,763,765 字节):
phpXplorer_0.9.33.zip
汉化+日志功能增强版本(1,638,123 字节):
phpXplorer_0.9.33_zh.rar
Updated 2005-11-10 19:47 -- 有朋友指出汉化版本对于包含中文的文件名不支持,这两天凑空把几个关键文件转化成utf-8格式,基本上可以支持对中文的访问(只是在下载的时候保存的文件名会变成乱码,但所下载的内容应该是正确的。这个似乎和Apache服务器的配置有关)
修改涉及的文件清单:
system/config.php
system/classes/pxCLS_system_class.php
system/tmp/lang.pxLNGd/zh.pxLNG.php
modules/TinyMCE/lang.pxLNGd/zh.pxLNG.php
modules/TinyMCE/includes/tinymce/jscripts/tiny_mce/langs/zh_cn.js
修改之后的版本可以在这里下载(1,638,637 字节):
phpXplorer_0.9.33_zh_utf-8.rar
php-4.3.10 + Oracle 9.2.0.4.0 , 在 linux下编译安装php的时候make报错:
/root/php-4.3.10/ext/oci8/oci8.c: In function `_oci_open_session':
/root/php-4.3.10/ext/oci8/oci8.c:2183: `OCI_NLS_CHARSET_ID' undeclared (first use in this function)
解决方法:
下载Oracle文件补丁 , 解压以后编辑文件oci.h,在文件最前面注释的下面增加一行内容:
#define OCI_NLS_CHARSET_ID 0
然后把所有的补丁文件 (.c 和 .h)拷贝到安装文件目录 /root/php-4.3.10/ext/oci8/ 以及 /root/php-4.3.10/main/ 下面
重新configure,make,install。
问题引起:应该是不同版本的PHP和Oracle之间的兼容性问题。
