<?php

Currently browsing php

fsockopen VS pfsockopen

前几天cyberty说起pfsockopen,我还不是很了解,大家平时用的最多的应该是fsockopen,事实上我基本没用过pfsockopen

那么这两个函数有什么区别呢?先看一下手册上的介绍:

resource fsockopen ( string target [, int port [, int &errno [, string &errstr [, float timeout]]]] )
resource pfsockopen ( string hostname [, int port [, int &errno [, string &errstr [, float timeout]]]] )

两函数的参数完全一致,从手册上能看出来的区别只是一句话It is the persistent version of fsockopen().

或许此时你想到了mysql_connect 和 mysql_pconnect,经验告诉我们mysql_pconnect并没有预期的效果。那么psocketopen会是什么效果呢?

下面我做了几组测试,每组测试时反复50次连接:
socket

给一些说明: 第一行的1~5代表测试次数的序号,fsockopen 和 pfsockopen在各种情况分别测试了5次;其他数字是执行时间(以秒为单位)。
从测试结果来看pfsockopen在同一次请求中大量反复使用的连接具有复用效果,但是在需要获取内容时表现不佳。

总体来看区别不是很大,或许需要更大量的测试数据来支持这一结论。

下面是测试代码,根据需要改动注释代码:

ini_set("display_errors", "On");
 error_reporting(E_ALL);
 set_time_limit(600);
 $t1 = microtime(true);
 $err = 0;

 echo "[code]\n";
 $func = isset($_GET['p']) ? "pfsockopen" : "fsockopen";
 for ($i = 0; $i < 50; $i++) {
	$fp = $func("www.163.com", 80);
	if(!is_resource($fp)) {
		echo "conn error\n";
		$err++;
		continue;
	}
	fwrite($fp, "GET / HTTP/1.1\r\n\r\n");
	$s = stream_get_contents($fp);
//	fclose($fp);
	echo strlen($s);
	echo "\n";
	flush();
 }
 $t2 = microtime(true);
 echo "time: ".($t2-$t1)."\n";
 echo "err: ".$err;

centos下nginx+php+mysql的自动安装SHELL

今天安装了一下新的测试环境,因为不想反复输入命令。。也就有了本文章。

打算找一找自动安装的脚本,一键安装自然是追求自动化的崇高追求。。gg后发现真的有不少,于是找了一个看了看,没错!是我要的。

因为安装目录、配置方面有些不同于是拿来修改一下就可以方便使用了~

修改后的脚本:lnmp-auto-install

安装目录是:
nginx: /home/nginx
php: /home/php
mysql: /home/mysql
eaccelerator: /home/eaccelerator

至于版本号就不说了吧,基本都是比较新的稳定版本了。

启动nginx:  /etc/init.d/nginx start
启动php-fpm: /home/nginx/sbin/php-fpm start
启动mysql: /etc/init.d/mysql start

感谢原作者Licess’s,以及提供镜像下载的vpser

PHP性能的血汗工厂

作为PHP性能血汗工厂的老板的你,打算如何榨干它的性能?最常用的数组操作、字符串操作需要注意的地方?给大家推荐一个网站,列举了一些常用代码不同写法的性能区别。

推荐看以下5部分:

  1. 字符串输出;echo vs. print
  2. 读循环;foreach() vs. for() vs. while(list() = each())
  3. 写循环;foreach() vs. for vs. while(list() = each())
  4. 变量类型检查;isSet() vs. empty() vs. is_array()
  5. 别名的使用;Using the &-ref-operator

http://www.phpbench.com/

ps: 每次刷新各项数据会重新计算,推荐firefox查看IE下样式有问题

foreach使用&引用赋值时要注意的问题

下文是同事整理出来的,以前也有遇到过。既然整理的很完善了就转帖过来共勉。

解决办法由几种,推荐:

unset 或者是 换用
foreach($arr as $k=>$value){//习惯用$value或$val
$arr[$k] .= ‘4′;
}

下转:

foreach 通过在 $value 之前加上 & 很容易就能修改数组的单元,如:

foreach($arr as &$value){
    
$value .= 4;
}

但这个用法也很容易造成错误,商务空间就发现有这个问题,而且也不容易找。
看例子更直截了当:

<?php
$arr = array(a,b,c);
$arr2 = array(d, e, f);
 
foreach($arr as &$value){//习惯用$value或$val
    
$value .= 4;
}
 
//都处理完毕我们在页面模版输出,首先输出$arr2
foreach($arr2 as $value){//习惯用$value或$val
    
//echo $value;
}
//然后再这样输出 $arr;
foreach($arr as $value){//习惯用$value或$val
    
echo $value, \n;
}
?>

大家看看输出的结果是否和期望的一样。这里结果是:

a4
b4
b4

结果和我期待的不一样,这个就是引用引起的问题。
在 foreach($arr as &$value) 数组遍历到最后,引用关系并没有断开,这是等同于 $value 与 $arr 的最后一个单元即 $arr[2] 引用。

再到 foreach($arr2 as $value),$value的值一直随数组单元的值变,由于引用关系没有断开,$arr[2] 的值也跟着变化。一直到$arr2遍历完,这是$value的值为f,所以$arr[2]值也为f。
这时$arr的值应为:

Array
(
[0] => a4
[1] => b4
[2] => f
)

这个和我们看到的最终输出结果又不一样。再到 foreach($arr as $value),同理,这时 $arr[2]的值也随着 $value 变化,当遍历到key为1,即$arr[1]时,$arr[2]的值也变成 $arr[1] 的值,即是

b4。然后再遍历到key为2时 $arr[2]的值又成了 $arr[2] 的值,也就是 b4 了。就是输出时的结果。

所以在 foreach 使用引用时要注意了。也可以在处理完后立即断开引用关系,后面就不会有上述情况了。

foreach($arr as &$value){
    
$value .= 4;
}
unset($value);

javascript版本的parse_url函数

在很多时候我们需要通过javascript在页面中获取GET方式传递的各个参数,很可惜javascript没有源生的支持。在PHP中可以通过parse_url函数来获取一个URL中所包含的各个参数及其他信息。以前我写过一个类似parse_url的js函数,不过只是提取参数,其他信息就直接抛弃了。今天看到另外一个比较完全的版本,一起放出来跟大家分享一下吧:)

首先是以前我的版本:

/*
 * @author zhys9
 * @date 20071010
 * @param String string URL
 * @return Object oRs
 * e.g. input: 'http://so.56.com/index?type=video&key=aaa'
 * 		ouput: {'type':video, 'key':'aaa'}
 */
function parse_str(string){
	var a = [];
	var oRs = {};
	var query = string.substr(string.indexOf('?')+1);
	var tmp = query.split('&');
	var k;
	for(var i=0;i<tmp.length;i++){
		a = tmp[i].split('=');
		oRs[a[0]] = a[1];
	}
	return oRs;
}

欠缺的地方就是单纯的字符串解析,没有获取协议、端口、域名、锚点等信息
下面再看一下比较完整的版本:

// This function creates a new anchor element and uses location
// properties (inherent) to get the desired URL data. Some String
// operations are used (to normalize results across browsers).

function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        source: url,
        protocol: a.protocol.replace(':',''),
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
        hash: a.hash.replace('#',''),
        path: a.pathname.replace(/^([^\/])/,'/$1'),
        relative: (a.href.match(/tp:\/\/[^\/]+(.+)/) || [,''])[1],
        segments: a.pathname.replace(/^\//,'').split('/')
    };
}

比较巧妙的是利用了A标签的DOM属性来获取更多的信息。不过,在document.location对象中包含了所有的信息,只是用这种方法只能获取document.location的信息,不具有更好的通用性。
用法:

var myURL = parseURL('http://zhys9.com:8080/blog/index.php?id=255&m=hello#top');

myURL.file;     // = 'index.php'
myURL.hash;     // = 'top'
myURL.host;     // = 'zhys9.com'
myURL.query;    // = '?id=255&m=hello'
myURL.params;   // = Object = { id: 255, m: hello }
myURL.path;     // = '/blog/index.php'
myURL.segments; // = Array = ['dir', 'index.php']
myURL.port;     // = '8080'
myURL.protocol; // = 'http'
myURL.source;   // = 'http://zhys9.com:8080/blog/index.php?id=255&m=hello#top'

比较完整的这个版本的代码取自:http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

PHP性能的血汗工厂

作为PHP性能血汗工厂的老板的你,打算如何榨干它的性能?最常用的数组操作、字符串操作需要注意的地方?给大家推荐一个网站,列举了一些常用代码不同写法的性能区别。

推荐看以下5部分:

  1. 字符串输出;echo vs. print
  2. 读循环;foreach() vs. for() vs. while(list() = each()) 
  3. 写循环;foreach() vs. for vs. while(list() = each())
  4. 变量类型检查;isSet() vs. empty() vs. is_array()
  5. 别名的使用;Using the &-ref-operator

http://www.phpbench.com/ 

ps: 每次刷新各项数据会重新计算,推荐firefox查看IE下样式有问题

zend server

前段时间收到zend发来邮件说是zend server测试邀请,安装后发现提供的包包真是够多啊,清单如下:

- PHP 5.2.8
— Common Extensions
— Additional Extensions
— Zend Optimizer+
— Zend Debugger
— Zend Data Cache
— Zend Java Bridge
— Zend Guard Loader
— Zend Page Cache
— Zend Monitor
- Zend Framework 1.7.2
— Zend Framework Base
— Zend Framework Dojo
— Zend Framework Extras
- Oracle OCI Driver
- phpMyAdmin
- IBM DB2 RTCL
- MS SQL Native Client
- Apache Web Server

今天看到zend官方已经放出了CE版,同时linux版本提供了RPM和DEB两种包包,性能方面还没有做测试。相信官方对自己的性能压榨还是有很强的先天优势啊~

Zend Server Beta Downloads

HTML Parser 简介

要介绍的HTML Parser就是PHP Simple HTML DOM Parser,这个是PHP5版,是根据原作者Jose Solorzano’s 的HTML Parser for PHP 4改写而来的。

或许是喜欢采集数据的伙计们的福音,也是工作需要这个工具是我一个同事发现的,用法很简单:

// Create DOM from URL or file
$html = file_get_html('http://www.google.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';

Description, Requirement & Features

  • A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way!
  • Require PHP 5+.
  • Supports invalid HTML.
  • Find tags on an HTML page with selectors just like jQuery.
  • Extract contents from HTML in a single line.

从 sourceforge下载最新版
查看文档 Online Document

RE. flash+php截图后保存图片

pingback test…
as2时代要实现该功能只有在本地draw完bitmap后,把所有widthxheight的图片都储存到数组里然后post给php,php通过gd库来生成,虽然可以不过效率就…一张120×90的图就够flash运算半天了.
as3要实现这个功能虽然还要借助php,但是只是借助php把图片数据给echo出来而已.图片生成关键步骤都在客户端进行了.
另外还需要adobe官方的as3corelib包.

客户端:
[code lang="actionscript"]
import com.adobe.images.JPGEncoder;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.navigateToURL;
import flash.utils.ByteArray;

//画位图数据
var jpgSource:BitmapData = new BitmapData (picture.width, picture.height);
jpgSource.draw(picture);
//生成编码容器
var jpgEncoder:JPGEncoder = new JPGEncoder(95);
//将位图数据编码到容器内成为ByteArray流
var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
//压缩ByteArray流
jpgStream.compress();
//添加stream的header请求
var header:URLRequestHeader = new URLRequestHeader(”Content-type”, “application/octet-stream”);
var jpgURLRequest:URLRequest = new URLRequest(”save.php”);
jpgURLRequest.requestHeaders.push(header);
jpgURLRequest.method = “POST”;
jpgURLRequest.data = jpgStream;
//推送图片数据到服务器端
navigateToURL(jpgURLRequest, “_blank”);[/code]
服务器端:

<?php
$jpg = gzuncompress($GLOBALS["HTTP_RAW_POST_DATA"]);
header("Content-Type: image/jpeg");
echo $jpg;
?>

这样的服务端代码没有实现保存图片吧。。
http://hirokimo.com/?p=49