C语言 c++ php mysql nginx linux lnmp lamp lanmp memcache redis 面试 笔记 ppt 设计模式 问题 远程连接

php随笔小技巧

//更改自动加载时调用的函数     
spl_autoload_register(array('Core_Fun','_class_autoload'));

//脚本执行完毕时调用
register_shutdown_function()

//获取指定下标的参数
func_get_arg($offset)

//把获取的全部参数放到一个数组里
func_get_args()

file_put_contents设置超时时间

 

$opt = array(
     'http'=>array(
        'method'=>"GET",
        'header'=>"Content-Type: text/html; charset=utf-8",
        'timeout'=>2
    )    
);
$context = stream_context_create($opt);
file_get_contents("http://www.baidu.com", false, $context);

curl中的超时设置:curl_setopt($ch, CURLOPT_TIMEOUT, 3)

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.baidu.com");
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$data = curl_exec($ch);
curl_close($ch);

 fscoketopen 超时

function request($host, $uri, $timeout = 3, $port = 80)
{
    $fp = fsockopen ( $host, 80, $errno, $errstr, $timeout );
    if (! $fp) {
        echo "$errstr ($errno)<br />\n";
        exit;
    } else {
        $data = '';
        stream_set_timeout ( $fp, $timeout ); //#
        $out = "GET {$uri} HTTP/1.1\r\n";
        $out .= "Host: {$host}\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite ( $fp, $out );
        while ( ! feof ( $fp ) ) {
            $data .= fgets ( $fp, 128 );
        }
        fclose ( $fp );
        return $data;
    }
    
}

echo request('www.cnblogs.com', '/siqi');

 

 

 

抽象类的妙用:可以用来做单例模式用

 

class man{
    public $a = 1;
    
    public function __construct()
    {
        echo 'new';
    }
    
    public function say()
    {
        echo 'saying';
    }
}

//抽象类不可以直接被实例化(巧妙的运用)
abstract class people{
    
    public $a = 123;
    
    public static function get_obj()
    {
        //这个的变量改成成员变量也是可以的
        static $obj = null;
        
        if(is_null($obj))
        {
            $obj = new man();
        }
        return $obj;
    }
}

// 只输出的一个new说明只实例化了一次
$p1 = people::get_obj();
$p2 = people::get_obj();

 

用数组中的每个值一次去替换字符串中的自定字符

//$sql = "?,?,?,?"
//$data = array('a', 'b', 'c', 'd');
//一次替换一个问号
for($i=0;$i<$count;$i++){
$sql=preg_replace('/\?/',"'".mysql_escape_string($data[$i])."'",$sql,1);// 一次只替换一个
}

 

 

 

/**
 * 当发生致命性错误或者exit时都会调用此函数
 * 
 */
error_reporting(0);
register_shutdown_function ( 'handleShutdown' );

function  handleShutdown (){
    $error  =  error_get_last ();
    
    // 根据错误信息,判断是否是超时了
    if ( $error  &&  strpos ( $error [ 'message' ], 'Maximum exec' )!== false ) 
    {
        echo 'handle time out';
    }
}

set_time_limit(2);

sleep(3);

 

 

/**
 * 获取最后一次出错信息,无论如何也能获取到
 * 
 * error_get_last set_error_handler 都不会受环境配置的影响
 * 
 */
error_reporting(0);
ini_set("display_errors", "off");


set_error_handler(function(){

    print_r(func_get_args());

});

echo $a ;
print_r(error_get_last());

 

//$php_errormsg 获取php前一个错误信息 ,必须在 php.ini 中 track_errors = On
ini_set('track_errors', true);
echo $a;
echo $php_errormsg; //Undefined variable: a

 

//调试

// 输出所有的函数
get_defined_functions();

//获取所定义的常量
get_defined_constants();

//获取所定义的变量
get_defined_vars();

 

 

#对于请求外部地址curl比file_get_contents效率更高
#禁用后者php.ini中修改
allow_url_fopen = Off
#重启php-fpm

 

 

#正则中对\的理解

$str = '<a href=\"db.house.qq\"></a>';

#双引号中可以转义的符合会被执行,输出后不在显示转义符
echo "/\\\\\"db.house.qq\\\\\"/" . "\n"; // /\\"db.house.qq\\"/ 总结:在双引号的正则中一个\需要写成 \\

#正则本身的转义符号也需要转义
var_dump(preg_match("/\\\\\"db.house.qq\\\\\"/", $str, $m));

#单引号写法,单引号中的内容不会执行
var_dump(preg_match('/\\\"db.house.qq\\\"/', $str, $m));

print_r($m);


 

 

// ?: 匹配但不捕获 加在前面
//? 去贪婪 加在后面
// \1 反向引用
// $1 捕获
$str = 'a a';
preg_match("/(a)(?:\s+)\\1/", $str, $m); #1
echo preg_replace("/(a)(\s+)\\1/", "$1", $str); #a
print_r($m);

 

#php通过mysql取出的数据库的数据都是字符串类型

 

#关闭gpc
magic_quotes_gpc=Off
get_magic_quotes_gpc()

 

#请不要在程序里面嵌套任何PHP标签(以免多次调用PHP解析器)

 

#strtolower会在没有安装中文语言的系统中把中文转成乱码,用下面的这个函数
strtr($string, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');

 

#如果print/echo输出HTML会被Apache加上缓存头,如果不希望被缓存,则需要加上上面的输出无缓存头代码来避免
@header('Cache-Control: no-cache, must-revalidate, max-age=0');
@header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
@header('Pragma: no-cache');

 

file_get_contents() 读取文件要比 fopen/fread 快30倍,但请求外部地址很慢,请用curl替代

 

null ++ 为1, -- 仍为null  字符串只可以++,相当于最后一个字节加1, --则没效果

 

 

/**
 * sql转义,并把输入转换成可插入的sql
 * @author root
 *
 */
class escape{

    /**
     * 内部函数,做insert操作时候的字符串过滤
     *
     * @param unknown_type $data
     * @return int or errorno
     */
    public function compile_insert_string($data)
    {
        $field_names  = '';
        $field_values = '';

        foreach ($data as $k => $v)
        {
            $field_names  .= "$k,";

            if ( is_numeric( $v ) and intval($v) == $v )
            {
                $field_values .= intval($v).",";
            }elseif ($v === null)
            {
                //兼容字段值为null的
                $field_values .= "null,";
            }else 
            {
                $field_values .= "'".$this->format_string($v)."',";
            }
        }
        //去掉最后一个,
        $field_names  = preg_replace( "/,$/" , "" , $field_names  );
        $field_values = preg_replace( "/,$/" , "" , $field_values );

        return array( 
            'FIELD_NAMES'  => $field_names,
            'FIELD_VALUES' => $field_values,
        );
    }
    
    /**
     * 格式化参数,php连接mysql的时候,可能导致SQL注入攻击,使用这个来做过滤
     *
     * @param string $str
     * @return string
     */
    public function format_string($str)
    {
        if (get_magic_quotes_gpc())
        {
            $str = stripslashes($str);
        }
        if (!is_numeric($str))
        {
            //$str = mysqli_real_escape_string($this->connection, $str);
        }
        return $str;
    }
}

$insert_arr = array("id"=>1, "name"=>"sjk");

$e = new escape();
$formated_array =  $e->compile_insert_string($arr);
$table = "card";
$insert_sql = 'INSERT INTO '.$table.' ('.$formated_array['FIELD_NAMES'].') VALUES('.$formated_array['FIELD_VALUES'].')';

 

#注意需要带上引号
(include 'mth.php') == "a";

 

#外部参数的验证原则:对外部参数进程合法性验证,对于不符合的应该拒绝而不是使其合法

 

spl_autoload_*类函数运用

//获取加载文件的扩展名
spl_autoload_extensions()

//获取所有注册的函数列表
spl_autoload_functions

//反注册一个自动加载函数
spl_autoload_unregister();

//注册一个函数,注意此操作会覆盖原来的 __autoload 函数
spl_autoload_register(func_name);
//某个类的某个方法
spl_autoload_register(array('AutoloadClass', 'autoload')); //autoload 为静态方法
spl_autoload_register(array($this, 'autoload')); //$this 代表一个对象

 

//spl_autoload_register 可重复调用,如果找到则停止搜索
function a ($c) {
    echo "a\n";
    class Bla {} // Usually "include 'path/to/file.php';"
}
function b ($c) {
    echo "b\n";
    class Bla {} // Usually "include 'path/to/file.php';"
}
spl_autoload_register('a');
spl_autoload_register('b');

$c = new Bla();

 

//php 1~100 单个输出 记得php.ini中设置 output_buffering = Off
echo str_repeat(' ',1024);
for($i=1;$i<100;$i++)
{
    echo $i;
    sleep(1);
//     ob_flush();
    flush();
    
}

 

set_time_limit() 仅计算脚本自己执行的时间,调用system(),io操作,数据库查询、连接、sleep()、外部的请求(curl)等都不算在之内,并且windows下并不是这样的

//通用的测试脚本
set_time_limit(1);
$time = time();    
while(time()-$time <5)
{
    echo 'timeout';
}    

 

限制程序使用内存的大小

ini_set("memory_limit", "128M");
ini_set("memory_limit", "100K");

 

根据输出的内容设置相应的头信息,可以减少攻击

header('Content-Type:text/plain');
header('Content-Type:application/json');

  

 php中模拟不可中断睡眠

class SleepWorkaroundForSIGALRM {
        private $time;
        function __construct($seconds) {
                $this->time = microtime(1) + $seconds;
                while ($this->time >= microtime(1)) {
                usleep(10);
                }

        }
} 

 

数组模拟循环链表

$a = array(0,1,2,3,4);

$i=0;
$len = count($a);

// 1
while(1)
{
    if($i==$len)
    {
        $i = 0;
    }
    
    ee($a[$i]);
    
    $i++;
    
}

// 2
while(1)
{
    $i = $i%$len;
    
    ee($a[$i]);
    
    $i++;
}

// 3
while(1)
{
    if(!next($a))
    {
        reset($a);
    }
    ee(current($a));
}

// 4
for($i=0;$i<$len;)
{
    ee($i);
    
    $i++;
    
    if($i == $len)
    {
        $i = 0;
    }
}

 

curl 当post超过1024byte时的问题

If you are doing a POST, and the content length is 1,025 or greater, then curl exploits a feature of http 1.1: 100 (Continue) Status.

 See http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3

 * it adds a header, "Expect: 100-continue".  
 * it then sends the request head, waits for a 100 response code, then sends the content 

 Not all web servers support this though.  Various errors are returned depending on the server.  If this happens to you, suppress the "Expect" header with this command:

<?php
 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
?>

 See http://www.gnegg.ch/2007/02/the-return-of-except-100-continue/ 

 

 检测url的连通性(只获取头信息,不获取返回的内容,但也必须等服务端执行完成)

function check_url($url) { 
     $c = curl_init(); 
     curl_setopt($c, CURLOPT_URL, $url); 
     curl_setopt($c, CURLOPT_HEADER, 1); // get the header 
     curl_setopt($c, CURLOPT_NOBODY, 1); // and *only* get the header 
     curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); // get the response as a string from curl_exec(), rather than echoing it 
     curl_setopt($c, CURLOPT_FRESH_CONNECT, 1); // don't use a cached version of the url 
     if (!curl_exec($c)) { return false; } 

     $httpcode = curl_getinfo($c, CURLINFO_HTTP_CODE); 
     return ($httpcode < 400); 
 } 

 

判断一个数组是否是关联数组

function is_assoc($arr) {
    return array_keys($arr) !== range(0, count($arr) - 1);
}

 

不同的 content-type

设置头信息(Post请求)
1、curl_setopt ( $ch, CURLOPT_HTTPHEADER, array('Content-type:text/plain') );
file_get_contents('php://input', 'r') 获取到
$_POST                                获取不到

2、curl_setopt ( $ch, CURLOPT_HTTPHEADER, array('Content-type:application/x-www-form-urlencoded') );#默认
file_get_contents('php://input', 'r') 获取到
$_POST                                获取到

3、curl_setopt ( $ch, CURLOPT_HTTPHEADER, array('Content-type:multipart/form-data; boundary=----WebKitFormBoundarygAvW9MJkUNVmzDjY') );
file_get_contents('php://input', 'r') 获取不到
$_POST                                获取到

 

 curl上传文件

/**
 * 
 * 传递一个数组到CURLOPT_POSTFIELDS,cURL会把数据编码成 multipart/form-data,
 * 而然传递一个URL-encoded字符串时,数据会被编码成 application/x-www-form-urlencoded。
 * 
 */
$ch = curl_init();

$data = array('name' => 'Foo', 'file' => '@/home/user/test.png;type=xx;filename=xx');

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

curl_exec($ch);

 

curl获取头信息 (注意包括\r\n)

$response = curl_exec($ch);
 $curl_info = curl_getinfo($ch);
 curl_close($ch);
 $header_size = $curl_info['header_size'];
 $header = substr($response, 0, $header_size);
 $body = substr($response, $header_size); 

 

curl边下载边输出内容

$ch = curl_init();
$fh = fopen('/path/to/stored/file/example_file.dat', 'w');
curl_setopt($ch, CURLOPT_FILE, $fh);
curl_setopt($ch, CURLOPT_URL, 'http://example.com/example_file.dat');
curl_exec($ch);
fflush($fh);
fclose($fh);

//must reset cURL file handle. Not doing so will cause a warning to be
//thrown and for cURL to default to output regardless
//for our example, we'll set return transfer.
curl_setopt($ch, CURLOPT_FILE, fopen('php://stdout', 'w'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, 'http://example.org/index.html');
$html = curl_exec($ch); //this will now work
/**
 * 注意:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
curl_setopt($ch, CURLOPT_FILE, $fp); 放在后面否则不起作用 ,开启后 curl_exec 不再能获取到值
 */

 

 

 

 

 

posted on 2012-12-02 14:51  思齐_  阅读(1093)  评论(0编辑  收藏  举报