php中数组到字符串的键值变换

简单而言,遇到了这么一个需求:

$db_config=array('host'=>'localhost','user'=>'u','password'=>'p','dbname'=>'test');

 

需要将其转换为:

$pg_link="host=localhost user=u password=p dbname=test";

 

一开始是想到用imlode实现,但发现有问题,不能处理键名。搜索后发现可以用http_build_query函数实现这个需求,即:

$pg_link=http_build_query($db_config,'',' ');

 

php的数组与postgresql中的数组之间的转换处理

数据中心的DOI在设计时采用了PostgreSQL的数组类型来进行处理,因此在代码中涉及到PHP的数组和PostgreSQL数组之间的转换。其中比较麻烦的就是字符串数组之间的相互转换,因为涉及到转义的问题。

PostgreSQL的数组是这样存储的:
{"a1 a2","a2 a3","a3,a4"}
这就是PHP从PostgreSQL中直接读取出来的结果。要是不考虑逗号的转义,通常可以用函数来处理:
$phparray=explode(',',substr($pgarray,1,-1));
要考虑逗号的转义,网上通常有两种方法,一种是正则方法进行处理,一种是在PostgreSQL中转换为json进行处理(9.2版本以后支持)。个人推荐采用json转换的方法进行处理,应用范围更广。即:
在sql中使用array_to_json()函数转换为json字符串,然后在php代码中使用json_decode()函数转换为字符串。

而从PHP数组转换为PostgreSQL数组则稍显麻烦一些,可以用字符串方法进行(即组合成pg中的数组形式),也可以用array数组函数来组合。推荐采用array数组进行组合,这样可以避免处理逗号转义的麻烦(非常麻烦)。
SQL示例如下:
insert into table1 (id,pgarray) values(10,array['a1','a2,a3','a4,a5']);

php遭遇内存不足问题

服务器上有一个自动生成数据的程序,是从另一个数据库中获取生成的。

结果最近经常用户反应数据生成不完整,检查log发现是内存用满了,默认是128MB,于是调整为256MB,结果还是有问题,于是调整为1024MB,还是有问题。

这样就必须回头检查代码了,发现之前的代码是如此写的:

$sql2= "...";
$sth2 = $db->query($sql2);
$rows2 = $sth2->fetchAll();
foreach($rows as $k=>$v)
{
...
}

这样以来,若数据库中一次性取出的数据很大,就用使用太多的内存,于是修改代码,调整为:

$sql2= "...";
$sth2 = $db->query($sql2);
while($v=$sth2->fetch())
{
...
}

这样就应该能解决问题了。

总结:fetchAll速度会有所提升,但在大数据量下耗费内存直线上升。因此在合适的场景下可以选择用fetch迭代。

用php处理时间文本

从数据库中直接导出的文本(数据的日期范围及服务次数):
2 2003-07-19 2003-08-18
10 2004-03-22 2004-03-22
9 2005-11-05 2005-11-05
4 2006-10-01 2008-10-31
18 2007-01-01 2009-07-15

想把其中的服务次数累加到每一天上去,本来想用sql直接处理,结果没有想到什么好的方法,只好请小李写了一个脚本来处理:

<?php
$file_handle = fopen("./water-time-service.txt", "r");
$arr = array();
$index = 0;
while (!feof($file_handle)) {
	$index ++;
   $line = fgets($file_handle);
   $times = (int)mb_substr($line,0,2,"UTF-8");
   $date_start = trim(mb_substr($line,2,11,"UTF-8"));
   $date_end = trim(mb_substr($line,13,11,"UTF-8"));
   $end_day = strtotime($date_end);
   $days = round((strtotime($date_end) - strtotime($date_start)) / (3600*24)) + 1;
   $_thisline = array();
   for(;;)
   {
	   if($days < 1)
	   {
		   break;
	   }
	   $_thisline[] = date("Y-m-d",$end_day - ($days - 1) * (3600 * 24));
	   $days --;
   }
   foreach($_thisline as $v)
   {
	   @$arr[$v] += $times;
   }
}
fclose($file_handle);
foreach($arr as $n=>$v) echo $n. " ". $v."\r\n";
?>

这样就能处理成这样的结果:
2003-07-19 2
2003-07-20 2
2003-07-21 2
2003-07-22 2
2003-07-23 2

然后就可以用gnuplot画图了。water-time-service

山寨长微博:txt2img插件问题

txt2img插件安装后在一直有问题,显示:

PHP Warning:  imagettftext() [<a href='function.imagettftext'>function.imagettftext</a>]: Could not find/open font in <phpfile>

看了其代码,发现需要使用gd和freetype支持,但在服务器上搜索了一下,发现这两个包都已经安装了:

sudo apt-get install php5-gd libfreetype6
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
libfreetype6 已经是最新的版本了。
php5-gd 已经是最新的版本了。
升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。

最终还是在stackoverflow找到了答案。
就是要在代码中添加一行(在使用imagettftext函数的前面):

putenv('GDFONTPATH=' . realpath('.'));

wordpress升级到3.5.2:数据库升级问题

wordpress后台提示有新版本,3.5.2,于是就升级,提示需要升级数据库,但升级数据库后就一篇空白,页面也不再更新了。

网上搜了很多,多数说是禁止插件、主题。但这个问题应该和插件、主题没有关系的。最终搜索到有可能是内存的问题,于是把php的内存从64M调整到128M。然后问题就解决了。

参考:
http://setwordpress.com/2013/06/24/fix-wordpress-3-5-2-database-update-required-error/

zend mail路径问题

在使用zend mail发送邮件时,若需要多次发送邮件,则会遇到这个问题,导致系统反馈错误:

Failed opening required ‘Zend/Mail/Protocol/Exception.php‘

搜索了一下,网上也有同样的问题:
http://stackoverflow.com/questions/1605918/problem-with-sending-emails-using-zend-mail

在ZF官方的issue上也有对应的汇报:

http://framework.zend.com/issues/browse/ZF-10196

但这里都只是建议采用绝对路径来避免此错误,暂时也没有更好的办法,也就只能采用绝对路径来避免此错误了。

php下mkdir不能设置777的问题

在php里,用mkdir可以创建一个目录,按照官方文档的说明,默认mode参数为0777,但实际测试结果,默认情况下为755。

sudo su www-data
php -r "mkdir('test');"
ls -l

显示结果为:

drwxrwxr-x 2 www-data www-data 4096  9月 17 12:05 test

即使指定mode,结果也是一样:

php -r "mkdir('test',0777);"

搜索后发现是需要先行umask处理,参考这个帖子

因此,最终处理方法是:

php -r "$old=umask(0);mkdir('test');umask($old);"