2015年11月

php闭包

<?php
//提到闭包就不得不想起匿名函数,
//也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:
$func=function ($value='')
{
    echo "test!!!";
};
$func();//输出test!!!
?>

闭包函数当成变量使用

<?php
//闭包函数当作变量来使用
$func_1=function ($value='')
{
    echo "This is func_1!!!";
};
$func_2=function ($value='')
{
    echo "This is func_2!!!";
};
//闭包函数当作变量来使用
function test($value){
    $value();
}
test($func_1);//输出  This is func_1!!!
test($func_2);//输出  This is func_2!!!
//或者直接传递
test(function ($value='')//输出  This is func_3!!!
{
    echo "This is func_3!!!";
});
?>

闭包函数使用外部变量:PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。
如下,会报错

<?php
//闭包函数当作变量来使用
$str='This is string';
$num=1;
$func_1=function ($value='')
{
    echo "This is func_1!!!";
    echo $str;//报错Notice: Undefined variable: str in D:\wamp\wamp\www\mytest\tp_ceshi.php on line <em>8</em>
    echo $num;//报错Notice: Undefined variable: num in D:\wamp\wamp\www\mytest\tp_ceshi.php on line <em>9</em>
};
$func_1();
?>
```php
如下
```php
<?php
//闭包函数使用外部变量
$str='This is string';
$num=1;
$func_1=function ($value='')use($str,$num)
{
    echo "This is func_1!!!";
    echo "<br/>";
    echo $str;
    echo "<br/>";
    echo $num;
};
$func_1();
//输出
This is func_1!!!
This is string
1
?>

闭包改变外部变量

<?php
//闭包函数使用外部变量
$str='This is string';
$num=1;
$func_1=function ($value='')use($str,$num)
{
    echo $num;
    $num++;
};
$func_1();
echo $num;
//输出结果: 1   1
?>

和一般函数一样,闭包函数不能改变外部变量的值,因为是值传递,想要改变外部变量的值,只需要在传递变量进去的时候在变量前加上"&"
php php

php发送get,post

转载自:http://blog.csdn.net/haha00217/article/details/7969504

一,用file_get_contents来发送get以get方式接受

<?php
$url='http://localhost/mytest/tset.php';
$html=file_get_contents($url);
var_dump($html);
?>

二, 用fopen打开url, 以get方式获取内容

<?php
$url='http://localhost/mytest/tset.php';
//php手册上说是把资源绑定到一个流上面,成功之后返回文件指针资源
$html=fopen($url, 'r');
//这个函数会返回当前协议文件中取得一些信息(php手册上这样说,我自己把这个理解成取得当前请求的一些信息,比如请求是否成功,服务器版本啊之类的信息)
var_dump(stream_get_meta_data($html));
$str='';
//因为$html是一个指针资源,不能直接输出,所以要使用下面的循环来取出,类似于从数据库取出资源
//循环,没到文件结尾就循环feof检测是否到达文件指针结尾
while (!feof($html)) {
    //从文件指针中读取后面设置的字节
    $str.=fgets($html,1024);
}
var_dump($str);
//关闭已经打开的文件指针,免得占用资源,感觉和mysql连接一样,不用的时候要关掉~~~
fclose($html);
?>

三,用file_get_contents函数,以post方式获取

<?php
$url='http://localhost/mytest/tset.php';
//要传递的参数
$data=array('boo'=>'bar');
//这个函数是可以把数组转换成boo=bar形式,现在参数很少所以没什么,但是参数多的话用这个函数很方便(应该是这个作用吧~~)
$data=http_build_query($data);
//http请求的参数,注意header项的值要用双引号,不然\r\n不会被解析成换行符,会影响传值,别的影响没遇到,不知道
$options=array(
    'http'=>array(
            'method'=>'POST',
            'header'=>"Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . strlen($data) . "\r\n",
            'content' => $data
    )
);
//创建一个上下文资源流
$content=stream_context_create($options);
//发送请求第一个参数是文件位置,改成false和true没什么影响啊,第三个就是http请求头以及一些设置选项了
$html=file_get_contents($url,true,$content);
var_dump($html);
?>

四,用fsockopen函数
post

<?php
//@file phpinput_post.php
//要传递的参数
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
//应该是请求发送给接受者的实体正文类型
$http_entity_type = 'application/x-www-form-urlencoded';
//正文的长度
$http_entity_length = strlen($http_entity_body);
$host = '127.0.0.1';
$port = 80;
$path = 'http://localhost/mytest/tset.php';
//依次是,主机,端口,错误号,错误信息,过期时间,这步好像没发请求
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
    //写协议内容。。。页面地址
fputs($fp, "POST {$path} HTTP/1.1\r\n");
//主机
fputs($fp, "Host: {$host}\r\n");
//请求正文类型
fputs($fp, "Content-Type: {$http_entity_type}\r\n");
//正文长度
fputs($fp, "Content-Length: {$http_entity_length}\r\n");
//这个不知道....
fputs($fp, "Connection: close\r\n\r\n");
//发送的数据
fputs($fp, $http_entity_body . "\r\n\r\n");
$d='';
//取出数据
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
//关闭连接
fclose($fp);
//直接输出会输出http协议信息,所以做一些处理
//先从http协议中计算出正文的长度
preg_match('/Content-Length: (\d+)/', $d, $maths );
//var_dump($maths[1]);
//用字符串的总长度减去正文的长度就是http协议的长度了,再用substr截取就ok了
$d=substr($d,strlen($d)-(int)$maths[1]);
//输出请求结果
echo $d;
}
?>

get

<?php
//@file phpinput_post.php
//要传递的参数
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
$host = '127.0.0.1';
$port = 80;
$path = 'http://localhost/mytest/tset.php';
//依次是,主机,端口,错误号,错误信息,过期时间,这步好像没发请求
$fp = fsockopen($host, $port, $error_no, $error_desc, 10);
if ($fp) {
    //写协议内容。。。页面地址
fputs($fp, "GET {$path}?{$http_entity_body} HTTP/1.1\r\n");
//主机
fputs($fp, "Host: {$host}\r\n");
//这个不知道....
fputs($fp, "Connection: close\r\n\r\n");
$d='';
//取出数据
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
//关闭连接
fclose($fp);
//直接输出会输出http协议信息,所以做一些处理
//先从http协议中计算出正文的长度
preg_match('/Content-Length: (\d+)/', $d, $maths );
//var_dump($maths[1]);
//用字符串的总长度减去正文的长度就是http协议的长度了,再用substr截取就ok了
//$d=substr($d,strlen($d)-(int)$maths[1]);
//输出请求结果
echo $d;
}
?>

五,使用curl库,使用curl库之前,需要查看一下php.ini是否已经打开了curl扩展

<?php
//初始化一个curl回话(感觉就是实例化了一个对象。。)
$cu=curl_init();
$timeout=30;
//设置一个curl回话的传输选项,有很多选项可以设置,这里就不一一设置了
curl_setopt($cu, CURLOPT_URL, 'http://localhost/mytest/tset.php');
//设置值为"1"成功会返回请求页面的内容,设置为"0"成功会返回1
curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, $timeout);
$res=curl_exec($cu);
echo $res;
?>

$_POST,php://input,$_GET直接的区别

参考http://www.jb51.net/article/31317.htm

1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。
2,php://input 与$HTTP_RAW_POST_DATA读取的数据是一样的,都只读取Content-Type不为multipart/form-data的数据。


1,Coentent-Type仅在取值为application/x-www-form-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST
2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
3, 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。
4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。
5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。

PHP的反射类ReflectionClass、ReflectionMethod记录

ReflectionClass
类变量

<?php
class ClassName{
    /**
     * [$a description]公开变量
     * @var integer
     */
    public $a=1;
    //私有
    private $b=2;
    protected $c=3;
    public function __construct()
    {

    }
    public function a(){
        echo "a";
    }
    private function b(){
        echo "b";
    }
    protected function c(){
        echo "c";
    }
}
$class=new ClassName();
$obj=new ReflectionClass($class);
//打印类的信息,包括变量方法,都打印出来
print_r($obj->export($class));
<?php
class ClassName{
    /**
     * [$a description]公开变量
     * @var integer
     */
    public $a=1;
    //私有
    private $b=2;
    protected $c=3;
    const D=4;
    const E=5;
    public function __construct($value,$key)
    {

    }
    public function a(){
        echo "a";
    }
    private function b(){
        echo "b";
    }
    protected function c(){
        echo "c";
    }
    public function p($key,$value){
        echo $key;
        echo $value;
    }
}
$class=new ClassName(1,2);
$obj=new ReflectionClass($class);
//取出类里面定义的常量
print_r($obj->getConstant ('D'));
//取出所有常量
print_r($obj->getConstants ());
//方法很多,就不一一使用了,挑几个感觉比较常用的用用~~
//检测方法是否已经存在
var_dump($obj->hasMethod('a'));//方法存在,返回true
var_dump($obj->hasMethod('nnn'));//方法不存在,返回false
//实例化一个类(函数里面的值回传到构造函数里面)
$obj->newInstance(3,4)->a();//输出a,$obj->newInstance(3,4)执行完毕之后返回的是ClassName类
//取出类的方法并使用这个方法,这个函数返回的是ReflectionMethod对象了
$method=$obj->getMethod('a');
//使用ReflectionMethod方法就是执行这个方法,函数里面的值一个对象示例
$method->invoke($class);
//传参
$method=$obj->getMethod('p');
//参数直接安装顺序直接写在对象后面
$method->invoke($class,1,2);
//或者用invokeArgs方法,用数组传参数,在数组里面按顺序放好就ok了
$method->invokeArgs($class, array('zzz','aaa'));
//判断方法属性
var_dump($method->isPublic());//true
var_dump($method->isProtected());//false
?>

PHP中刷新输出缓冲

转载自:http://www.cnblogs.com/mutuan/archive/2012/03/18/2404957.html
PHP中刷新输出缓冲
buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入 一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁 盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。
同样的道理,在PHP中,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser

在PHP中与刷新缓冲相关的函数有三个:
1). flush
刷新PHP程序的缓冲,而不论PHP执行在何种情况下。该函数将当前为止程序的所有输出发送到用户的浏览器。 但是该函数不会对服务器或客户端浏览器的缓存模式产生任何影响,也不会对PHP本身的缓存产生任何影响。
2).ob_flush
该函数对PHP本身的的缓存进行输出。PHP本身的缓存受php.ini中的output_buffering的控制。ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。
与PHP本身输出缓冲相关的两个PHP配置是:
参数1:output_buffering :on/off 或 者整数 。设置为on时,将在所有脚本中使用输出缓存控制,不限制缓存的大小。而设置为整数时,如output_buffering=4096,当缓存数 据达到4096字节时会自动输出刷新缓存。而这个参数的不同正是导致以上代码在不同时候执行结果不同的原因。当output_buffering关闭时, 脚本所有的输出(echo)都会即时发送到客户端,执行上面代码时就是每秒输出一个数字。而开启output_buffering后,输出内容就会先缓存 在服务端,直到脚本结束时才一起发送给客户端。
参数2:implicit_flush:on/off。设定ON意味着,当脚本有输出时,自动立即发送到客户端。相当于在echo后自动加flush()。

3).ob_implicit_flush
这个函数强制每当有输出的时候,即刻把输出发送到浏览器。这样就不需要每次输出(echo)后,都用flush()来发送到浏览器了。
以下是举例:

<?php  
ob_end_clean();  
echo str_pad(" ", 256);  
for ($i=100; $i>0; $i--) {  
   echo $i.'<br/>';  
   flush();  
   sleep(1);   
}   
?>

以上代码应该隔一秒钟输出一次$i
echo str_pad(" ", 256)的目的是IE需要接受到256个字节之后才开始显示。 以上代码还有以下两种写法。

<?php  
echo str_pad(" ", 256);  
for ($i=100; $i>0; $i--) {  
   echo $i.'<br />';  
   ob_flush();  
   flush();  
   sleep(1);   
}   
?>
<?php  
ob_implicit_flush(true);  
echo str_pad(" ", 256);  
for ($i=100; $i>0; $i--) {  
   echo $i, '<br />';  
   ob_flush();  
   sleep(1);   
}

另外我们还需要注意刷新缓冲不光受以上几方面的影响,还受以下影响:
1). 个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函 数产生的结果不会立即被发送到客户端浏览器。甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 标记之前,不会显示出整个表格。一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。
2). PHP安装模式的影响。以上方式对于PHP以Apache模块方式安装的情况,可以直接使用。 如果以FastCgi方式还需要注意以下几下配置:
a). Apache+Fcgid+PHP
FcgidOutputBufferSize 0(默认是65536)
在配置Fcgid时, 设置这项值为0, 以上代码做刷新缓冲时,才能达到自己想要的效果。
b).IIS+FastCgi+PHP
ResponseBufferLimit=0
修改WINDOWS\system32\inetsrv\fcgiext.ini下的这一项。
c).nginx+php-fpm
fastcgi_buffer_size 4k;
fastcgi_buffers 8 4k;
fastcgi_busy_buffers_size 4k
gzip off;

PHP函数说明:
1.string str_pad ( string $input , int $pad_length [, string $pad_string = " " [, int $pad_type = STR_PAD_RIGHT ]] )
该函数返回 input 被从左端、右端或者同时两端被填充到制定长度后的结果。如果可选的 pad_string 参数没有被指定,input 将被空格字符填充,否则它将被 pad_string 填充到指定长度

2.相关flush类似函数如下

flush
ob_ clean
ob_ end_ clean
ob_ end_ flush
ob_ flush
ob_ get_ clean
ob_ get_ contents
ob_ get_ flush
ob_ get_ length
ob_ get_ level
ob_ get_ status
ob_ gzhandler
ob_ implicit_ flush
ob_ list_ handlers
ob_ start
output_ add_ rewrite_ var
output_ reset_ rewrite_ var