存档

‘PHP开发’ 分类的存档

http_build_query 的一个问题

2012年2月6日 没有评论

当我们使用CURL来post数据的时候,需要设置post的数据
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data);

假如这里的$data是

$data = array(
   'name'=>'scofield',
   'time'=>'2012-2-3'
)

接下来,需要先将$data变成字符串
$post_data = http_build_query($data);
而采用 http_build_query 转换后再
curl_setopt($c, CURLOPT_POSTFIELDS, $post_data);

看起来没有什么问题。但在实际操作中,$post_data 并没有被post过去。于是,自己写了个转换的方法后就OK了。

 function getStr($array,$Separator='&') {
        if (empty($array))
            return;
        if (!is_array($array)) {
            return $array;
        }
        $returnStr = '';
        foreach ($array as $key => $val) {
            $temp = '';
            if (is_array($val)) {
                for ($i = 0; $i < count($val); $i++) {
                    $returnStr .= $key . '[' . $i . ']' . '=' . $val[$i] . $Separator;
                }
            } else {
                $returnStr.= $key . '=' . $val . $Separator;
            }
        }
        $returnStr = substr(trim($returnStr), 0, -1);
        return $returnStr;
    }

感谢 黄斌-huangbin 童鞋的测试 http_build_query($data,"","&"); 即可,无需自己写方法解析了。

分类: PHP开发 标签: ,

一个有意思的日期逻辑处理

2011年7月19日 3 条评论

今天处理了一个很小的问题。
需求是这样的,从周一到周日只能看到上周一到上周日的数据。
这里直接从数据库里根据 date 字段查询 范围即可。
但需要PHP生成 开始日期和结束日期。

最开始,我直接这么处理。

$start_date = date('Y-m-d' , strtotime("-2 week monday"));
$end_date = date('Y-m-d' , strtotime("$start_date +6 day"));

假如日期是 2011-07-19,$start_date= 2011-07-11 这样处理没有问题。
如果日期是 2011-07-18 ,$start_date 则会等于 2011-07-04,还活在上周。

于是换了种方法

$getWeekDay = date("w");
$startDay = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - $getWeekDay + 1 - 7, date("Y")));
$endDay = date("Y-m-d", strtotime("+6 day $startDay"));

假如日期是 2011-07-19,$start_date= 2011-07-11 这样处理没有问题,和我们期望的一样。
如果日期是 2011-07-24,我们期望的 $start_date 是 2011-07-11,但实际返回的是 2011-07-18。

不得已,我再改了下方法

$getWeekDay = date("N") ;
$startDay = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - $getWeekDay + 1 - 7, date("Y")));
$endDay = date("Y-m-d", strtotime("+6 day $startDay"));

这下就OK 了。

分类: PHP开发 标签:

PHP用CURL伪造IP和来源

2011年7月19日 1 条评论

以前没有这么搞过。

今天群里一个朋友在问这个问题。

查了下,CURL确实很强悍的可以伪造IP和来源。

1.php 请求 2.php 。

1.php代码:


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/2.php");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:8.8.8.8', 'CLIENT-IP:8.8.8.8'));  //构造IP
curl_setopt($ch, CURLOPT_REFERER, "http://www.gosoa.com.cn/ ");   //构造来路
curl_setopt($ch, CURLOPT_HEADER, 1);
$out = curl_exec($ch);
curl_close($ch);

2.php代码如下:


function getClientIp() {
    if (!empty($_SERVER["HTTP_CLIENT_IP"]))
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    else if (!empty($_SERVER["REMOTE_ADDR"]))
        $ip = $_SERVER["REMOTE_ADDR"];
    else
        $ip = "err";
    return $ip;
}

echo "IP: " . getClientIp() . "";
echo "referer: " . $_SERVER["HTTP_REFERER"];

伪造成功,这是不是给“刷票”的朋友提供了很好的换IP的方案!!
哈哈。

分类: PHP开发 标签:

优化PHP代码的40条建议[转]

2011年7月1日 没有评论

1.如果一个方法可静态化,就对它做静态声明。速率可提升至4倍。

2.echo 比 print 快。

3.使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接。

4.在执行for循环之前确定最大循环数,不要每循环一次都计算最大值。

5.注销那些不用的变量尤其是大数组,以便释放内存。

6.尽量避免使用__get,__set,__autoload。

7.require_once()代价昂贵。

8.在包含文件时使用完整路径,解析操作系统路径所需的时间会更少。

9.如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time()。

10.函数代替正则表达式完成相同功能。

11.str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。

12.如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。

13.使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。

14.用@屏蔽错误消息的做法非常低效。

15.打开apache的mod_deflate模块。

16.数据库连接当使用完毕时应关掉。

17.$row[‘id’]的效率是$row[id]的7倍。

18.错误消息代价昂贵。

19.尽量不要在for循环中使用函数,比如for ($x=0; $x < count($array); $x)每循环一次都会调用count()函数。

20.在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。

21.递增一个全局变量要比递增一个局部变量慢2倍。

22.递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。

23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。

24.仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。PHP大概会检查看是否存在全局变量。

25.方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但性能上没有变化。

26.派生类中的方法运行起来要快于在基类中定义的同样的方法。

27.调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。

28.用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。当然,只有当你不需要在字符串中包含变量时才可以这么做。

29.输出多个字符串时,用逗号代替句点来分隔字符串,速度更快。注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。

30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面,少用脚本。

31.除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。

32.尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。

33.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。

(举例如下)
if (strlen($foo) < 5) { echo “Foo is too short”; }
(与下面的技巧做比较)
if (!isset($foo)) { echo “Foo is too short”; }

调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。

34.当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提供商(ISPs)和服务器。

35.并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。

36.并非要用类实现所有的数据结构,数组也很有用。

37.不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?

38.当你需要时,你总能把代码分解成方法。

39.尽量采用大量的PHP内置函数。

40.如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。

41.评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。

42.mod_zip可作为Apache模块,用来即时压缩你的数据,并可让数据传输量降低80%。

原文地址: http://www.builder.com.cn/2008/0203/728680.shtml

分类: PHP开发 标签:

PHP几个不常用但很有用的函数

2011年6月29日 没有评论
  • glob()

直接print_r(glob(‘*’)) 看看效果吧。

再  print_r(glob(‘*.PHP’)) 再看看效果吧。

———————————-

  • PHP Filter函数

PHP自带的filter函数。直接可以用来验证email,IP等。也可以用来验证 INPUT等。

具体见这里 http://php.net/manual/en/book.filter.php

———————————-

  • get_browser()

获得浏览器信息的。

———————————-

  • sys_getloadavg()

这个函数只针对linux系统有用。

可以用来监测系统的负载。 其值就是linux的 load average值。


分类: PHP开发 标签:

推荐一款开源的flashchart生成柱状图

2011年6月27日 没有评论

最近项目中需要生成类似excel的柱状图、饼图、趋势图等等。。。

网上google了一番,发现了 Open Flash Chart   地址:  http://teethgrinder.co.uk/open-flash-chart-2/

非常好用的一款开源工具。目前最新版是2.0

——————————————————————————–

http://ofcgwt.googlecode.com/svn/demo/Demo.html 这里有很多示例可供参考。

不过不太推荐使用 googlecode上的这个示例代码,建议采用官方的示例代码和flash chart 。

flash chart的使用很简单。

如下示例:

//url形式
function embSwfWithUrl(dataurl,divcon){
     var params = {
        "wmode": "transparent",
        "menu": "false",
        "scale": "noScale",
        "allowFullscreen": "false",
        "allowScriptAccess": "always",
        "bgcolor": "#c0c0c0"  //背景
    };
    var flashvars = {
        'data-file' : dataurl
    };
    swfobject.embedSWF("/swf/open-flash-chart.swf?timestamp=" + Math.random(),divcon, "450", "300", "10.0.0", "./swf/expressInstall.swf" ,flashvars,params);
}

embSwfWithUrl('http://xxx.com/xxx.html','swfCon');

这里的http://xxx.com/xxx.html返回的是相应的json格式的数据。

swfCon是放flash的div容器。

swfobject是开源的js处理flash的类。http://code.google.com/p/swfobject/

——————————————————————————–

注意下,flash chart 获得数据的方式有两种,

一种是   data-file  一种是 get-data

data-file 正是如上示例,值必须是个 url地址,里面返回的是 json数据。

而get-data的值则是一个函数名称。 函数返回 json 数据。

如下示例:

//get-data
function embSwfWithData(divcon,getdataFn){
    var params = {
        "wmode": "transparent",  //窗口模式
        "menu": "false",  //菜单显示
        "scale": "noScale",  //缩放
        "allowFullscreen": "false", //允许全屏
        "allowScriptAccess": "always",  //允许脚本
        "bgcolor": "#c0c0c0"  //背景
    };
var flashVar = {
 "get-data":getdataFn
};
    swfobject.embedSWF("/swf/open-flash-chart.swf?timestamp=" + Math.random(), divcon, "450", "300", "10", "/swf/expressInstall.swf",flashVar  ,params);
}

function getJsonData(){
return 'json data';
}

这里 “get-data”:getdataFn 需要传递的就是一个函数名称。函数中返回json数据。

还有一点需要注意下,/swf/open-flash-chart.swf?timestamp=+Math.random() .

这里之所以加随机数,是因为有的浏览器在缓存flash后,使其flash参数失效了。加上随机数后,每次浏览器会重新加载flash。

PHP导出excel

2011年6月27日 没有评论

最近做一个项目,其中涉及到了数据导成excel的功能。

后来使用了 开源的 PHPExcel  http://phpexcel.codeplex.com/ 目前最新版是1.7.6

PHPExcel 可以生成 .xls 和 .xlsx (office2007)。其封装的方法很全了。

比如设置 excel的title,keywords,description

获得某个sheet,某个列的数据 等等。

具体的文档,查看这里,http://phpexcel.codeplex.com/releases/view/45412 非常详细。

下面是一段简单的示例。

//这里要 include进来 phpexcel类
include ROOT_PATH . 'library/PHPExcel-1.7.6/PHPExcel.PHP';
include ROOT_PATH . 'library/PHPExcel-1.7.6/PHPExcel/Writer/Excel2007.PHP';

class MyExcel {

    public static function makeExcel($title, $data, $excle_name) {
        $exclefile = 'excel/' . date('Y-m-d') . '/' . md5($excle_name) . '.xlsx';

        $Excel = new PHPExcel();
        $Excel->setActiveSheetIndex(0);
        $Excel->getSheet()->setTitle($title);

        $cell_one = $data[0];
        $j = 0;
        foreach ($cell_one as $k => $v) {
            $Excel->getSheet()->setCellValue(self::getCharByNunber($j) . '1', $k);
            $j++;
        }

        $x = 2;
        foreach ($data as $value) {
            $y = 0;
            foreach ($value as $k => $v) {
                $Excel->getSheet()->setCellValue(self::getCharByNunber($y) . $x, $v);
                $y++;
            }
            $x++;
        }

        $objwriter = new PHPExcel_Writer_Excel2007($Excel);
        $objwriter->save($exclefile);
        TMDebugUtils::debugLog('make ' . $exclefile);
        return $exclefile;
    }

    protected static function getCharByNunber($num) {
        $num = intval($num);
        $arr = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',);
        return $arr[$num];
    }

}

//导出用户基本信息
function exportUserBaseInfo() {
    $excelTitle = '用户基本信息';
    $excelFileName = 'userbase';
    $data = array();
    // $rs = ....  这里rs是从db读取的数据
    for ($i = 0; $i < count($rs); $i++) {         $data[$i]['姓名'] = $rs[$i]->name;
        $data[$i]['年龄'] = intval($rs[$i]->age);
        $data[$i]['日期'] = $rs[$i]->date;
    }
    MyExcel::makeExcel($excelTitle, $data, $excelFileName);
}

//导出新闻资讯信息
function exportUserBaseInfo() {
    $excelTitle = '新闻资讯信息';
    $excelFileName = 'news';
    $data = array();
    // $rs = ....  这里rs是从db读取的数据
    for ($i = 0; $i < count($rs); $i++) {         $data[$i]['标题'] = $rs[$i]->title;
        $data[$i]['作者'] = $rs[$i]->author;
        $data[$i]['日期'] = $rs[$i]->date;
        $data[$i]['浏览数'] = floatval($rs[$i]->view_count);
        $data[$i]['被评论数'] = floatval($rs[$i]->comment_count);
    }
    MyExcel::makeExcel($excelTitle, $data, $excelFileName);
}

//end

这里只是简单的生成的xlsx,其他需要读取更复杂的,可以阅读官方的手册,有很详细的说明。

如果不需要保存,直接输出到浏览,如下:

//不用保存,直接输出到浏览器
$objwriter = new PHPExcel_Writer_Excel2007($Excel);
        header("Content-Type: application/force-download");
        header("Content-Type: application/octet-stream");
        header("Content-Type: application/download");
        header('Content-Disposition:inline;filename=temp.xlsx');
        header("Content-Transfer-Encoding: binary");
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Pragma: no-cache");
        $objwriter->save('php://output');

The End

分类: PHP开发 标签: ,

NoSQL – Redis几个认识误区

2011年1月15日 1 条评论

转自 http://timyang.net/data/redis-misunderstanding/

前几天微博发生了一起大的系统故障,很多技术的朋友都比较关心,其中的原因不会超出James Hamilton在On Designing and Deploying Internet-Scale Service(1)概括的那几个范围,James第一条经验“Design for failure”是所有互联网架构成功的一个关键。互联网系统的工程理论其实非常简单,James paper中内容几乎称不上理论,而是多条实践经验分享,每个公司对这些经验的理解及执行力决定了架构成败。

题外话说完,最近又研究了Redis。去年曾做过一个MemcacheDB, Tokyo Tyrant, Redis performance test,到目前为止,这个benchmark结果依然有效。这1年我们经历了很多眼花缭乱的key value存储产品的诱惑,从Cassandra的淡出(Twitter暂停在主业务使用)到HBase的兴起(Facebook新的邮箱业务选用HBase(2)),当再回头再去看Redis,发现这个只有1万多行源代码的程序充满了神奇及大量未经挖掘的特性。Redis性能惊人,国内前十大网站的子产品估计用1台Redis就可以满足存储及Cache的需求。除了性能印象之外,业界其实普遍对Redis的认识存在一定误区。本文提出一些观点供大家探讨。

1. Redis是什么

这个问题的结果影响了我们怎么用Redis。如果你认为Redis是一个key value store, 那可能会用它来代替MySQL;如果认为它是一个可以持久化的cache, 可能只是它保存一些频繁访问的临时数据。Redis是REmote DIctionary Server的缩写,在Redis在官方网站的的副标题是A persistent key-value database with built-in net interface written in ANSI-C for Posix systems,这个定义偏向key value store。还有一些看法则认为Redis是一个memory database,因为它的高性能都是基于内存操作的基础。另外一些人则认为Redis是一个data structure server,因为Redis支持复杂的数据特性,比如List, Set等。对Redis的作用的不同解读决定了你对Redis的使用方式。

互联网数据目前基本使用两种方式来存储,关系数据库或者key value。但是这些互联网业务本身并不属于这两种数据类型,比如用户在社会化平台中的关系,它是一个list,如果要用关系数据库存储就需要转换成一种多行记录的形式,这种形式存在很多冗余数据,每一行需要存储一些重复信息。如果用key value存储则修改和删除比较麻烦,需要将全部数据读出再写入。Redis在内存中设计了各种数据类型,让业务能够高速原子的访问这些数据结构,并且不需要关心持久存储的问题,从架构上解决了前面两种存储需要走一些弯路的问题。

2. Redis不可能比Memcache快

很多开发者都认为Redis不可能比Memcached快,Memcached完全基于内存,而Redis具有持久化保存特性,即使是异步的,Redis也不可能比Memcached快。但是测试结果基本是Redis占绝对优势。一直在思考这个原因,目前想到的原因有这几方面。

  • Libevent。和Memcached不同,Redis并没有选择libevent。Libevent为了迎合通用性造成代码庞大(目前Redis代码还不到libevent的1/3)及牺牲了在特定平台的不少性能。Redis用libevent中两个文件修改实现了自己的epoll event loop(4)。业界不少开发者也建议Redis使用另外一个libevent高性能替代libev,但是作者还是坚持Redis应该小巧并去依赖的思路。一个印象深刻的细节是编译Redis之前并不需要执行./configure。
  • CAS问题。CAS是Memcached中比较方便的一种防止竞争修改资源的方法。CAS实现需要为每个cache key设置一个隐藏的cas token,cas相当value版本号,每次set会token需要递增,因此带来CPU和内存的双重开销,虽然这些开销很小,但是到单机10G+ cache以及QPS上万之后这些开销就会给双方相对带来一些细微性能差别(5)。

3. 单台Redis的存放数据必须比物理内存小

Redis的数据全部放在内存带来了高速的性能,但是也带来一些不合理之处。比如一个中型网站有100万注册用户,如果这些资料要用Redis来存储,内存的容量必须能够容纳这100万用户。但是业务实际情况是100万用户只有5万活跃用户,1周来访问过1次的也只有15万用户,因此全部100万用户的数据都放在内存有不合理之处,RAM需要为冷数据买单。

这跟操作系统非常相似,操作系统所有应用访问的数据都在内存,但是如果物理内存容纳不下新的数据,操作系统会智能将部分长期没有访问的数据交换到磁盘,为新的应用留出空间。现代操作系统给应用提供的并不是物理内存,而是虚拟内存(Virtual Memory)的概念。

基于相同的考虑,Redis 2.0也增加了VM特性。让Redis数据容量突破了物理内存的限制。并实现了数据冷热分离。

4. Redis的VM实现是重复造轮子

Redis的VM依照之前的epoll实现思路依旧是自己实现。但是在前面操作系统的介绍提到OS也可以自动帮程序实现冷热数据分离,Redis只需要OS申请一块大内存,OS会自动将热数据放入物理内存,冷数据交换到硬盘,另外一个知名的“理解了现代操作系统(3)”的Varnish就是这样实现,也取得了非常成功的效果。

作者antirez在解释为什么要自己实现VM中提到几个原因(6)。主要OS的VM换入换出是基于Page概念,比如OS VM1个Page是4K, 4K中只要还有一个元素即使只有1个字节被访问,这个页也不会被SWAP, 换入也同样道理,读到一个字节可能会换入4K无用的内存。而Redis自己实现则可以达到控制换入的粒度。另外访问操作系统SWAP内存区域时block进程,也是导致Redis要自己实现VM原因之一。

5. 用get/set方式使用Redis

作为一个key value存在,很多开发者自然的使用set/get方式来使用Redis,实际上这并不是最优化的使用方法。尤其在未启用VM情况下,Redis全部数据需要放入内存,节约内存尤其重要。

假如一个key-value单元需要最小占用512字节,即使只存一个字节也占了512字节。这时候就有一个设计模式,可以把key复用,几个key-value放入一个key中,value再作为一个set存入,这样同样512字节就会存放10-100倍的容量。

这就是为了节约内存,建议使用hashset而不是set/get的方式来使用Redis,详细方法见参考文献(7)。

6. 使用aof代替snapshot

Redis有两种存储方式,默认是snapshot方式,实现方法是定时将内存的快照(snapshot)持久化到硬盘,这种方法缺点是持久化之后如果出现crash则会丢失一段数据。因此在完美主义者的推动下作者增加了aof方式。aof即append only mode,在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作上,这样就看出aof是一个非常不协调的部分。

其实aof目的主要是数据可靠性及高可用性,在Redis中有另外一种方法来达到目的:Replication。由于Redis的高性能,复制基本没有延迟。这样达到了防止单点故障及实现了高可用。

小结

要想成功使用一种产品,我们需要深入了解它的特性。Redis性能突出,如果能够熟练的驾驭,对国内很多大型应用具有很大帮助。希望更多同行加入到Redis使用及代码研究行列。

分类: PHP开发 标签: ,

推荐一款PHP调试工具 — FirePHP

2011年1月1日 3 条评论

PHP调试工具之 — FirePHP

PHP调试有很多中方法。今天给大家推荐的是 FirePHP(http://www.firephp.org/)。

这个工具,是基于firefox的一个组件。Firephp组件安装地址。使用之前需要先安装下这个组件。完了还需要down一个FirePHP的包。下载地址

下载完成后可以看到包里的文件如下:

我们现在来写个例子测试下。(需要include 进来fb.php文件哦)代码如下:

我们在firefox下运行。结果如下:
firephp - 3

在这里就可以看到$str的值了。

接下来来介绍下FirePHP的几个常用方法:

1、  fb($para) 该方法就是如上示例。可以监测某个变量的值。该方法等同于FB::log($para)。

2、  FB:: info ($str);   该方法和fb()方法类似。不同的地方在于其运行结果在firefox中会有个不同的标志。(见图三)

3、  FB::warn($str);   同上类似。

4、  FB::error($str);   同上类似。


图三

5、  FB::trace($str); 该方法用于监控变量的调用栈。如下图示例。

我们也可以在类中使用FB。如下示例:

运行结果如下:
firephp

在fb.php中,我们可以看到有如下多的方法,在这里就不一一介绍了。主要常用的就是上面五个。有兴趣的同学可以仔细去研究测试下其他方法。

firephp

分类: PHP开发 标签: ,

PHP CURL CURLOPT_HTTPHEADER设置HOST

2010年9月25日 没有评论

为了安全,我们的web服务主机往往不能上网。维护的时候,也是通过跳板机,ssh登录后去操作。

有时候我们的程序需要访问外网。比如需要调用外网其他程序的某个接口。这下该怎么办呢?

我们可以通过PHP的CURL函数的CURLOPT_HTTPHEADER来配置设置host访问。

在开发中,我遇到这样一个例子。

有一个活动程序,需要调用qzone那边的一个接口。

如下代码示例:

$host = array("Host: act.qzone.qq.com");
$data = 'user=xxx&qq=xxx&id=xxx&post=xxx';
$url = 'http://192.168.1.12/xxx/xxx/api/';
var_dump( $this->curl_post($host, $data,$url) );

/
* 提交请求
* @param $host array 需要配置的域名 array("Host: act.qzone.qq.com");
* @param $data string 需要提交的数据 'user=xxx&qq=xxx&id=xxx&post=xxx'....
* @param $url string 要提交的url 'http://192.168.1.12/xxx/xxx/api/';
*/
 function curl_post($host,$data,$url)
    {
       $ch = curl_init();
       $res= curl_setopt ($ch, CURLOPT_URL,$url);
       var_dump($res);
       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
       curl_setopt ($ch, CURLOPT_HEADER, 0);
       curl_setopt($ch, CURLOPT_POST, 1);
       curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
       curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
       curl_setopt($ch,CURLOPT_HTTPHEADER,$host);
       $result = curl_exec ($ch);
       curl_close($ch);
       if ($result == NULL) {
           return 0;
       }
       TMDebugUtils::debugLog($result);
       return $result;
    }

通过PHP CURL CURLOPT_HTTPHEADER设置HOST很方便的解决了访问外网接口的问题。

分类: PHP开发 标签: , ,