php整理

备注说明

  1. 以下相关书面介绍来源于W3CSCHOOL 和 PHP 官网
  2. 所有DEMO都是经过测试运行,PHP版本为PHP5.5
  3. 此WIKI仅个人学习用
  4. ===表示示完成待添加_表示有疑问

PHP

PHP(中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发。

基本语法

文件处理

[TOC]

引入文件

require

生成一个致命错误(E_COMPILE_ERROR),在错误发生后脚本会停止执行。

include

生成一个警告(E_WARNING),在错误发生后脚本会继续执行。

文件处理

fopen()

r 只读。在文件的开头开始。
r+ 读/写。在文件的开头开始。
w 只写。打开并清空文件的内容;如果文件不存在,则创建新文件。
w+ 读/写。打开并清空文件的内容;如果文件不存在,则创建新文件。
a 追加。打开并向文件末尾进行写操作,如果文件不存在,则创建新文件。
a+ 读/追加。通过向文件末尾写内容,来保持文件内容。
x 只写。创建新文件。如果文件已存在,则返回 FALSE 和一个错误。
x+ 读/写。创建新文件。如果文件已存在,则返回 FALSE 和一个错误。

fclose()

函数用于关闭打开的文件:

feof()

eof() 函数检测是否已到达文件末尾(EOF)。
在循环遍历未知长度的数据时,feof() 函数很有用。
注释:在 w 、a 和 x 模式下,您无法读取打开的文件
if (feof($file)) echo "文件结尾";

fgetc()

函数用于从文件中逐字符地读取文件。
注释:在调用该函数之后,文件指针会移动到下一个字符。

全局变量/魔术变量

[TOC]

全局变量

超全局变量 — 超全局变量是在全部作用域中始终可用的内置变量

$GLOBALS — 引用全局作用域中可用的全部变量

$_SERVER — 服务器和执行环境信息

$_GET — HTTP GET 变量

$_POST — HTTP POST 变量

$_FILES — HTTP 文件上传变量

$_REQUEST — HTTP Request 变量

$_SESSION — Session 变量

$_ENV — 环境变量

$_COOKIE — HTTP Cookies

$php_errormsg — 前一个错误信息

$HTTP_RAW_POST_DATA — 原生POST数据

$http_response_header — HTTP 响应头

$argc — 传递给脚本的参数数目

$argv — 传递给脚本的参数数组

魔术变量

__LINE__:文件中的当前行号
这是第 “ 2 ” 行

__FILE__:文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名
该文件位于 “ E:\wamp\www\test\index.php ”

__DIR__:文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。
该文件位于 “ E:\wamp\www\test ”

__FUNCTION__: 4.3.0 新加 自 PHP 5 起本常量返回该函数被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。

CLASS__:PHP 4.3.0 新加自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。注意自 PHP 5.4 起 __CLASS 对 trait 也起作用。当用在 trait 方法中时

__TRAIT__: PHP 5.4.0 新加自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。Trait 名包括其被声明的作用区域(例如 Foo\Bar)。从基类继承的成员被插入的 SayWorld Trait 中的 MyHelloWorld 方法所覆盖。其行为 MyHelloWorld 类中定义的方法一致。优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法。

<?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}
trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
} 
class MyHelloWorld extends Base {
    use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>

以上例程会输出:Hello World!

__METHOD__:类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。
__NAMESPACE__:当前命名空间的名称(区分大小写)。此常量是在编译时定义的(PHP 5.3.0 新增)。

数据类型

[TOC]

类型

Boolean 布尔类型

Integer 整型

Float 浮点型

String 字符串

Array 数组

Object 对象

Resource 资源类型

NULL

Callback 回调类型

gettype()

获得数据类型

流程控制

[TOC]

流程控制

替代写法 (PHP 4, PHP 5, PHP 7)

注意:不支持在同一个控制块内混合使用两种语法。

PHP 提供了一些流程控制的替代语法,包括 if,while,for,foreach 和 switch。替代语法的基本形式是把左花括号({)换成冒号(:),把右花括号(})分别换成 endif;,endwhile;,endfor;,endforeach; 以及 endswitch;。

<?php if ($a == 5): ?>
A is equal to 5
<?php endif; ?>

<?php
if ($a == 5):
    echo "a equals 5";
    echo "...";
elseif ($a == 6):
    echo "a equals 6";
    echo "!!!";
else:
    echo "a is neither 5 nor 6";
endif;
?>

判断

if
else
elseif/else if

while

while ($i <= 10) {
 ##do sth 
}

/* example 2 */

$i = 1;
while ($i <= 10):
    print $i;
    $i++;
endwhile;

do-while

do-while 循环和 while 循环非常相似,区别在于表达式的值是在每次循环结束时检查而不是开始时。和一般的 while 循环主要的区别是
do-while :的循环语句保证会执行一次(表达式的真值在每次循环结束后检查)
while: 循环中就不一定了(表达式真值在循环开始时检查,如果一开始就为 FALSE 则整个循环立即终止)。
$i = 0;
do {
   echo $i;
} while (0);
##只执行一次

for

<?php
/* example 1 */

for ($i = 1; $i <= 10; $i++) {
    echo $i;
}

/* example 2 */

for ($i = 1; ; $i++) {
    if ($i > 10) {
        break;
    }
    echo $i;
}

/* example 3 */

$i = 1;
for (;;) {
    if ($i > 10) {
        break;
    }
    echo $i;
    $i++;
}

/* example 4 */

for ($i = 1, $j = 0; $i <= 10; $j += $i, print $i, $i++);

/* example 5 */
for (expr1; expr2; expr3):
    statement;
    ...
endfor;
?>

foreach

<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // 最后取消掉引用
?>

break&&continue

break:可以接受一个可选的数字参数来决定跳出几重循环 explame break2 默认为1
continue:接受一个可选的数字参数来决定跳过几重循环到循环结尾 continue3 默认为1

5.4.0    continue 0/break0; 不再合法。这在之前的版本被解析为 continue 1/break1;。
5.4.0    取消变量作为参数传递(例如 $num = 2; continue $num/break $num;)。
引处的数字参数是指"循环层级"不是"指循环次数",两者有本质区别

switch/case

<?php
switch($beer)
{
    case 'tuborg';
    case 'carlsberg';
    case 'heineken';
        echo 'Good choice';
    break; 
    default;
        echo 'Please make a new selection...';
    break;
}
switch($beer)
{
    case 'tuborg':
    case 'carlsberg':
    case 'heineken':
        echo 'Good choice';
    break;
    default;
        echo 'Please make a new selection...';
    break;
}
##一样的意思,允许使用分号代替 case 语句后的冒号
?>

goto

(PHP 5 >= 5.3.0, PHP 7)

goto 操作符可以用来跳转到程序中的另一位置。该目标位置可以用目标名称加上冒号来标记,而跳转指令是 goto 之后接上目标位置的标记。PHP 中的 goto 有一定限制,目标位置只能位于同一个文件和作用域,也就是说无法跳出一个函数或类方法,也无法跳入到另一个函数。也无法跳入到任何循环或者 switch 结构中。可以跳出循环或者 switch,通常的用法是用 goto 代替多层的 break。
<?php
for($i=0,$j=50; $i<100; $i++) {
  while($j--) {
    if($j==17) goto end; 
  }  
}
echo "i = $i";
end:
echo 'j hit 17';
?>

declare (没用过,手册没看懂)

return 一种结构,不是函数

require

include

require_once

include_once

函数

[TOC]

bool function_exists ( string $function_name ) 检测函数是否存在 返出为BOOL

可变函数

PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。
换句话说,可变函数只支持自定义结构,不支持系统类函数结构

匿名函数 version >= 5.3

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

内置函数

PHP 有很多标准的函数和结构。还有一些函数需要和特定地 PHP 扩展模块一起编译,否则在使用它们的时候就会得到一个致命的"未定义函数"错误。例如,要使用 image 函数中的 imagecreatetruecolor(),需要在编译 PHP 的时候加上 GD 的支持。或者,要使用 mysql_connect() 函数,就需要在编译 PHP 的时候加上 MySQL 支持。有很多核心函数已包含在每个版本的 PHP 中如字符串和变量函数。调用 phpinfo() 或者 get_loaded_extensions() 可以得知 PHP 加载了那些扩展库。同时还应该注意,很多扩展库默认就是有效的

参数

  1. 默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等
  2. 注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作

(待练习)匿名函数示例代码version >=5.3

[TOC]

5.4.0: $this 可用于匿名函数 /5.3.0:可以使用匿名函数

可以在闭包中使用 func_num_args(),func_get_arg() 和 func_get_args()

Example

Example #1 匿名函数示例

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world');
// 输出 helloWorld
?>

Example #2 匿名函数变量赋值示例

闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号:

    <?php
    $greet = function($name)
    {
        printf("Hello %s\r\n", $name);
    };
    
    $greet('World');
    $greet('PHP');
    ?>
    

Example #3 从父作用域继承变量

闭包可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。


    <?php
    $message = 'hello';
    
    // 没有 "use"
    $example = function () {
        var_dump($message);
    };
    echo $example();
    
    // 继承 $message
    $example = function () use ($message) {
        var_dump($message);
    };
    echo $example();
    
    // Inherited variable's value is from when the function
    // is defined, not when called
    $message = 'world';
    echo $example();
    
    // Reset message
    $message = 'hello';
    
    // Inherit by-reference
    $example = function () use (&$message) {
        var_dump($message);
    };
    echo $example();
    
    // The changed value in the parent scope
    // is reflected inside the function call
    $message = 'world';
    echo $example();
    
    // Closures can also accept regular arguments
    $example = function ($arg) use ($message) {
        var_dump($arg . ' ' . $message);
    };
    $example("hello");
    ?>

输出
Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hello"
string(5) "hello"
string(5) "hello"
string(5) "world"
string(11) "hello world"

Example #4 Closures 和作用域

这些变量都必须在函数或类的头部声明。 从父作用域中继承变量与使用全局变量是不同的。全局变量存在于一个全局的范围,无论当前在执行的是哪个函数。而 闭包的父作用域是定义该闭包的函数(不一定是调用它的函数)

<?php
// 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。
// 其中有一个方法用来计算购物车中所有商品的总价格,该方法使
// 用了一个 closure 作为回调函数。
class Cart
{
    const PRICE_BUTTER  = 1.00;
    const PRICE_MILK    = 3.00;
    const PRICE_EGGS    = 6.95;

    protected   $products = array();
    
    public function add($product, $quantity)
    {
        $this->products[$product] = $quantity;
    }
    
    public function getQuantity($product)
    {
        return isset($this->products[$product]) ? $this->products[$product] :
               FALSE;
    }
    
    public function getTotal($tax)
    {
        $total = 0.00;
        
        $callback =
            function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };
        
        array_walk($this->products, $callback);
        return round($total, 2);;
    }
}

$my_cart = new Cart;

// 往购物车里添加条目
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);

// 打出出总价格,其中有 5% 的销售税.
print $my_cart->getTotal(0.05) . "\n";
// 最后结果是 54.29
?>


















可变函数示例代码

[TOC]

第一种情况 方法

function foo() {
    echo "In foo()<br />\n";
}
$func = 'foo';
$func();        // This calls foo()


第二种情况 对象

 class Foo
    {
        function Variable()
        {
            $name = 'Bar';
            $this->$name(); // This calls the Bar() method
        }
        function Bar()
        {
            echo "This is Bar";
        }
    }

第三种情况 静态方法

class Foo
{
    static $variable = 'static property';
    static function Variable()
    {
        echo 'Method Variable called';
    }
}
echo Foo::$variable; // This prints 'static property'. It does need a $variable in this scope.
$variable = "Variable";
Foo::$variable();  // This calls $foo->Variable() reading $variable in this scope.

`

&引用传参(特别拿出来说明下)

默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。

如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面加上符号 &:

<?php
function add_some_extra(&$string)
{
    $string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>

简单总结下:
&引用传参,函数内部的更改会改变外面参数变量值 。

可变参数(version5.6+)

PHP 在用户自定义函数中支持可变数量的参数列表。在 PHP 5.6 及以上的版本中,由 ... 语法实现;在 PHP 5.5 及更早版本中,使用函数 func_num_args(),func_get_arg(),和 func_get_args() 。

Example #1

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);
?>

Example #2

<?php
function add($a, $b) {
    return $a + $b;
}

echo add(...[1, 2])."\n";

$a = [1, 2];
echo add(...$a);
?>

Example #3

<?php
function total_intervals($unit, DateInterval ...$intervals) {
    $time = 0;
    foreach ($intervals as $interval) {
        $time += $interval->$unit;
    }
    return $time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' days';

// This will fail, since null isn't a DateInterval object.
echo total_intervals('d', null);
?>

分析func_num_args(),func_get_arg(),和 func_get_args()

[TOC]

func_num_args

int func_num_args ( void ) 输出参数数量个数 (PHP 4, PHP 5, PHP 7)

Explame #1

<?php
function foo()
{
    $numargs = func_num_args();
    echo "Number of arguments: $numargs\n";
}

foo(1, 2, 3);   
?>

##输出 3

func_get_arg

mixed func_get_arg ( int $arg_num ) 返回参数列表的某一项 (PHP 4, PHP 5, PHP 7)

该函数可以配合 func_get_args() 和 func_num_args() 一起使用,从而使得用户自定义函数可以接受自定义个数的参数列表。
<?php
    function foo()
    {
         $numargs = func_num_args();
         echo "Number of arguments: $numargs<br />\n";
         if ($numargs >= 2) {
             echo "Second argument is: " . func_get_arg(1) . "<br />\n";
         }
    }
    
    foo (1, 2, 3);

输出:
Number of arguments: 3
Second argument is: 2

?>

返回指定的参数,错误则返回 FALSE 。

func_get_args

array func_get_args ( void ) 返回一个包含函数参数列表的数组 (PHP 4, PHP 5, PHP 7)

 function foo()
{
    $numargs = func_num_args();
    $arg_list = func_get_args();
    for ($i = 0; $i < $numargs; $i++) {
        echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
    }
}

function foo2(){
    foreach (func_get_args() as $key => $v) {
        echo "Argument  is: " . $v . "<br />\n";
    }
}

foo(1, 2, 3);
foo2(1, 2, 3);

输出:
Argument 0 is: 1
Argument 1 is: 2
Argument 2 is: 3
Argument is: 1
Argument is: 2
Argument is: 3
感觉用foreach会更方便

所有内置函数(待完善/练习)

[TOC]

什么是 PHP 过滤器?

  1. PHP 过滤器用于验证和过滤来自非安全来源的数据。
  2. 测试、验证和过滤用户输入或自定义数据是任何 Web 应用程序的重要组成部分。
  3. PHP 的过滤器扩展的设计目的是使数据过滤更轻松快捷。

    过滤函数

    filter_var() - 通过一个指定的过滤器来过滤单一的变量

    filter_var_array() - 通过相同的或不同的过滤器来过滤多个变量

    filter_input - 获取一个输入变量,并对它进行过滤

    filter_input_array - 获取多个输入变量,并通过相同的或不同的过滤器对它们进行过滤

Array 数组

Array 函数

函数描述
array()创建数组。
array_change_key_case()把数组中所有键更改为小写或大写。
array_chunk()把一个数组分割为新的数组块。
array_column()返回输入数组中某个单一列的值。
array_combine()通过合并两个数组来创建一个新数组。
array_count_values()用于统计数组中所有值出现的次数。
array_diff()比较数组,返回差集(只比较键值)。
array_diff_assoc()比较数组,返回差集(比较键名和键值)。
array_diff_key()比较数组,返回差集(只比较键名)。
array_diff_uassoc()比较数组,返回差集(比较键名和键值,使用用户自定义的键名比较函数)。
array_diff_ukey()比较数组,返回差集(只比较键名,使用用户自定义的键名比较函数)。
array_fill()用给定的键值填充数组。
array_fill_keys()用指定键名的给定键值填充数组。
array_filter()用回调函数过滤数组中的元素。
array_flip()交换数组中的键和值。
array_intersect()比较数组,返回交集(只比较键值)。
array_intersect_assoc()比较数组,返回交集(比较键名和键值)。
array_intersect_key()比较数组,返回交集(只比较键名)。
array_intersect_uassoc()比较数组,返回交集(比较键名和键值,使用用户自定义的键名比较函数)。
array_intersect_ukey()比较数组,返回交集(只比较键名,使用用户自定义的键名比较函数)。
array_key_exists()检查指定的键名是否存在于数组中。
array_keys()返回数组中所有的键名。
array_map()把数组中的每个值发送到用户自定义函数,返回新的值。
array_merge()把一个或多个数组合并为一个数组。
array_merge_recursive()递归地合并一个或多个数组。
array_multisort()对多个数组或多维数组进行排序。
array_pad()用值将数组填补到指定长度。
array_pop()删除数组的最后一个元素(出栈)。
array_product()计算数组中所有值的乘积。
array_push()将一个或多个元素插入数组的末尾(入栈)。
array_rand()返回数组中一个或多个随机的键。
array_reduce()通过使用用户自定义函数,以字符串返回数组。
array_replace()使用后面数组的值替换第一个数组的值。
array_replace_recursive()递归地使用后面数组的值替换第一个数组的值。
array_reverse()以相反的顺序返回数组。
array_search()搜索数组中给定的值并返回键名。
array_shift()删除数组中首个元素,并返回被删除元素的值。
array_slice()返回数组中被选定的部分。
array_splice()删除并替换数组中指定的元素。
array_sum()返回数组中值的和。
array_udiff()比较数组,返回差集(只比较值,使用一个用户自定义的键名比较函数)。
array_udiff_assoc()比较数组,返回差集(比较键和值,使用内建函数比较键名,使用用户自定义函数比较键值)。
array_udiff_uassoc()比较数组,返回差集(比较键和值,使用两个用户自定义的键名比较函数)。
array_uintersect()比较数组,返回交集(只比较值,使用一个用户自定义的键名比较函数)。
array_uintersect_assoc()比较数组,返回交集(比较键和值,使用内建函数比较键名,使用用户自定义函数比较键值)。
array_uintersect_uassoc()比较数组,返回交集(比较键和值,使用两个用户自定义的键名比较函数)。
array_unique()删除数组中的重复值。
array_unshift()在数组开头插入一个或多个元素。
array_values()返回数组中所有的值。
array_walk()对数组中的每个成员应用用户函数。
array_walk_recursive()对数组中的每个成员递归地应用用户函数。
arsort()对关联数组按照键值进行降序排序。
asort()对关联数组按照键值进行升序排序。
compact()创建包含变量名和它们的值的数组。
count()返回数组中元素的数目。
current()返回数组中的当前元素。
each()返回数组中当前的键/值对。
end()将数组的内部指针指向最后一个元素。
extract()从数组中将变量导入到当前的符号表。
in_array()检查数组中是否存在指定的值。
key()从关联数组中取得键名。
krsort()对数组按照键名逆向排序。
ksort()对数组按照键名排序。
list()把数组中的值赋给一些变量。
natcasesort()用“自然排序”算法对数组进行不区分大小写字母的排序。
natsort()用“自然排序”算法对数组排序。
next()将数组中的内部指针向前移动一位。
pos()current() 的别名。
prev()将数组的内部指针倒回一位。
range()创建包含指定范围单元的数组。
reset()将数组的内部指针指向第一个元素。
rsort()对数组逆向排序。
shuffle()将数组打乱。
sizeof()count() 的别名。
sort()对数组排序。
uasort()使用用户自定义的比较函数对数组中的键值进行排序。
uksort()使用用户自定义的比较函数对数组中的键名进行排序。
usort()使用用户自定义的比较函数对数组进行排序。
对比
待补充array_intersect_uassoc
待补充array_intersect_ukey
array_uintersect_assoc
array_uintersect_uassoc
待补充array_intersect_key
待补充array_intersect_assoc
array_intersect

定义和用法

array_intersect() 函数用于比较两个(或更多个)数组的键值,并返回交集。
该函数比较两个(或更多个)数组的键值,并返回交集数组,该数组包括了所有在被比较的数组(array1)中,同时也在任何其他参数数组(array2array3 等等)中的键值。

所有数组中的交集

说明

array_intersect() 函数返回两个或多个数组的交集数组。

结果数组包含了所有在被比较数组中,也同时出现在所有其他参数数组中的值,键名保留不变。

注释:仅有值用于比较。

语法

array_intersect(array1,array2,array3...);
参数描述
array1必需。与其他数组进行比较的第一个数组。
array2必需。与第一个数组进行比较的数组。
array3,...可选。与第一个数组进行比较的其他数组。

技术细节

返回值:返回交集数组,该数组包括了所有在被比较的数组(array1)中,同时也在任何其他参数数组(array2 或 array3 等等)中的键值。
PHP 版本:4.0.1+

demo

$array1 = [11,22,33,44,55,11,77];
$array2 = [11,2,3,4,55,6,7];
$array3 = [11,220,33,440,550,660,77];
show(array_intersect($array1, $array2,$array3));

多个不同KEY的值会返出KEY=>VALUE,如果KEY相同,只返出位置

输出

Array
(

[0] => 11
[5] => 11

)

待补充array_diff_ukey
待补充array_diff_uassoc
待补充array_diff_key
array_diff_assoc

定义和用法

array_diff_assoc() 函数用于比较两个(或更多个)数组的键名和键值 ,并返回差集。

该函数比较两个(或更多个)数组的键名和键值,并返回一个差集数组,该数组包括了所有在被比较的数组(array1)中,但是不在任何其他参数数组(array2array3 等等)中的键名和键值。

  1. 返出的为array1与其它数组比较后的差异值,并不会返出其它数组里面的值

语法

array_diff_assoc(array1,array2,array3...);
参数描述
array1必需。与其他数组进行比较的第一个数组。
array2必需。与第一个数组进行比较的数组。
array3,...可选。与第一个数组进行比较的其他数组。

技术细节

返回值:返回数组,该数组包含所有在 array1 中,但是不在任何其他参数数组(array2array3 等等)中的键名和键值。
PHP 版本:4.3+

demo

$array1 = [11,22,33,44,55];
$array2 = ['test1','test2','test3','test4','test5'];
$array3 = ['test1','test2','test3','test4','test6','trrs'=>['test1','test2'],'trrsd'=>'test1','22'];

show(array_diff_assoc($array3,$array2, $array1));

##输出
Array
(
    [4] => test6
    [trrs] => Array
        (
            [0] => test1
            [1] => test2
        )

    [trrsd] => test1
    [5] => 22
)
array_diff

定义和用法

array_diff() 函数返回两个数组的差集数组。该数组包括了所有在被比较的数组中,但是不在任何其他参数数组中的键值。(只比较键值)
在返回的数组中,键名保持不变。

  1. 返出的为array1与其它数组比较后的差异值,并不会返出其它数组里面的值

语法

array_diff(array1,array2,array3...);
参数描述
array1必需。与其他数组进行比较的第一个数组。
array2必需。与第一个数组进行比较的数组。
array3,...可选。与第一个数组进行比较的其他数组。

提示和注释

提示:可用一个或任意多个数组与第一个数组进行比较。
注释:仅有值用于比较。

技术细节

返回值:返回差集数组,该数组包括了所有在被比较的数组(array1)中,但是不在任何其他参数数组(array2array3 等等)中的键值。【感觉官方的好难看懂,其实就是拿array1和其它的数组比较差异,也只返出array1中与其它比较后的差异值】
PHP 版本:4.0.1+

DEMO

$array1 = [11,22,33,44,55];
$array2 = ['test1','test2','test3','test4','test5'];
$array3 = ['test1','test2','test3','test4','test6','trrs'=>['test1','test2'],'trrsd'=>'test1','22'];

##输出

Array
(
    [0] => 11
    [2] => 33
    [3] => 44
    [4] => 55
)
array_udiff
array_udiff_assoc
array_uintersect
array_udiff_uassoc
去重 array_flip和array_unique区别

1 array_flip ,如果同一值出现了多次,则最后一个键名将作为它的值,所有其他的键名都将丢失。如果原数组中的值的数据类型不是字符串或整数,函数将报错。

个人理解:函数返回一个反转后的数组,数组KEY是不能重复,如果发现相同的VALUE,会覆盖前面的值
  1. array_unique() 先将值作为字符串排序,然后对每个值只保留第一个遇到的键名,接着忽略所有后面的键名。这并不意味着在未排序的 array 中同一个值的第一个出现的键名会被保留。

    算是真正意义上的去重,会保存遇到的第一个KEY
array_unique(去掉重复的值)

定义和用法

array_unique() 函数用于移除数组中重复的值。如果两个或更多个数组值相同,只保留第一个值,其他的值被移除。

注释:被保留的数组将保持第一个数组项的键名类型。


语法

array_unique(array)

参数描述
array必需。规定数组。
sortingtype可选。规定排序类型。可能的值:SORT_STRING - 默认。把每一项作为字符串来处理。SORT_REGULAR - 把每一项按常规顺序排列(Standard ASCII,不改变类型)。SORT_NUMERIC - 把每一项作为数字来处理。SORT_LOCALE_STRING - 把每一项作为字符串来处理,基于当前区域设置(可通过 () 进行更改)。

技术细节

返回值:返回过滤后的数组。
PHP 版本:4.0.1+
更新日志:在 PHP 5.2.10 中,sortingtype 的默认值改回 SORT_STRING。 在 PHP 5.2.9 中,sortingtype 的默认值改为 SORT_REGULAR。在这之前的版本,sortingtype 的默认值为 SORT_STRING。
array_flip(去掉重复的值)

定义和用法

  1. array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。
  2. array_flip() 函数返回一个反转后的数组,如果同一值出现了多次,则最后一个键名将作为它的值,所有其他的键名都将丢失。
应用场景:除数组重复值

如果原数组中的值的数据类型不是字符串或整数,函数将报错。

语法

array_flip(array);
参数描述
array必需。规定需进行键/值对反转的数组。

技术细节

返回值:如果反转成功,则返回反转后的数组。如果失败,则返回 NULL。
PHP 版本:4+

demo

##可以用此函数去掉重复的值

$array1 = [11,22,33,44,55,11,77];
##反转两次,第一次反转为去掉重复的值,然后把值反转回来达到重的效果
show(array_flip(array_flip($array1)));

##输出
Array
(
    [5] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [6] => 77
)

运算
array_product
array_sum

定义和用法

array_sum() 函数返回数组中所有值的和。


语法

array_sum(array)

参数描述
array必需。规定数组。

技术细节

返回值:返回数组中所有值的和。
PHP 版本:4.0.4+
更新日志:PHP 4.2.1 之前的版本修改了传入的数组本身,将其中的字符串值转换成数值(大多数情况下都转换成了零,根据具体值而定)。
排序

sort() - 对数组进行升序排列
rsort() - 对数组进行降序排列
asort() - 根据关联数组的值,对数组进行升序排列
ksort() - 根据关联数组的键,对数组进行升序排列
arsort() - 根据关联数组的值,对数组进行降序排列
krsort() - 根据关联数组的键,对数组进行降序排列

待补充array_multisort
arsort
asort
krsort
ksort
uasort
uksort
usort
rsort
natsort
替换
array_replace_recursive

定义和用法

array_replace_recursive() 函数递归地使用后面数组的值替换第一个数组的值。

提示:您可以向函数传递一个数组,或者多个数组。

如果一个键存在于第一个数组 array1 同时也存在于第二个数组 array2,第一个数组 array1 中的值将被第二个数组 array2 中的值替换。如果一个键仅存在于第一个数组 array1,它将保持不变。如果一个键存在于第二个数组 array2,但是不存在于第一个数组 array1,则会在第一个数组 array1 中创建这个元素。如果传递了多个替换数组,它们将被按顺序依次处理,后面数组的值将覆盖之前数组的值。

注释:如果没有为每个数组指定一个键,该函数的行为将等同于 array_replace 函数。


语法

array_replace_recursive(array1,array2,array3...)

参数描述
array1必需。指定一个数组。
array2可选。指定一个要替换 array1 的值的数组。
array3,...可选。指定多个要替换 array1array2, ... 的值的数组。后面数组的值将覆盖之前数组的值。

技术细节

返回值:返回被替换的数组,如果发生错误则返回 NULL。
PHP 版本:5.3.0+
array_replace

array_replace() 函数使用后面数组的值替换第一个数组的值。

提示:您可以向函数传递一个数组,或者多个数组。

如果一个键存在于第一个数组 array1 同时也存在于第二个数组 array2,第一个数组 array1 中的值将被第二个数组 array2 中的值替换。如果一个键仅存在于第一个数组 array1,它将保持不变。(详见下面的实例 1)

如果一个键存在于第二个数组 array2,但是不存在于第一个数组 array1,则会在第一个数组 array1 中创建这个元素。(详见下面的实例 2)

如果传递了多个替换数组,它们将被按顺序依次处理,后面数组的值将覆盖之前数组的值。(详见下面的实例 3)

提示:请使用 array_replace_recursive 来递归地使用后面数组的值替换第一个数组的值。

函数使用后面数组的值替换第一个数组的值,如果前面的值不存在就会创建

语法

array_replace(array1,array2,array3...)

参数描述
array1必需。指定一个数组。
array2可选。指定一个要替换 array1 的值的数组。
array3,...可选。指定多个要替换 array1array2, ... 的值的数组。后面数组的值将覆盖之前数组的值。

技术细节

返回值:返回被替换的数组,如果发生错误则返回 NULL。
PHP 版本:5.3.0+

demo

$a1=array("a"=>"red","green");
$a2=array("a"=>"orange","b"=>"burgundy");
show(array_replace($a1,$a2));
Array
(
    [a] => orange
    [0] => green
    [b] => burgundy
)
array_replace和array_replace_recursive区别

array_replace 不会处理二级,只会把VALUE看成一个整体,但array_replace_recursive不会


CODE

$a1=array("a"=>array("red"),"b"=>array("green","blue"),);
$a2=array("a"=>array("yellow"),"b"=>array("black"));

$result=array_replace_recursive($a1,$a2);
show($result);

$result=array_replace($a1,$a2);
show($result);

##输出
Array
(
    [a] => Array
        (
            [0] => yellow
        )

    [b] => Array
        (
            [0] => black
            [1] => blue
        )

)
Array
(
    [a] => Array
        (
            [0] => yellow
        )

    [b] => Array
        (
            [0] => black
        )

)
array_values

定义和用法

array_values() 函数返回包含数组中所有的值的数组。

提示:被返回的数组将使用数值键,从 0 开始且以 1 递增。


语法

array_values(array)

参数描述
array必需。规定数组。

技术细节

返回值:返回包含数组中所有的值的数组。
PHP 版本:4+

demo

$array1 = [11,22,33,44,55,11,77=>[71,72,73,74]];
show(array_values($array1));
Array
(
    [0] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [5] => 11
    [6] => Array
        (
            [0] => 71
            [1] => 72
            [2] => 73
            [3] => 74
        )

)
array_map/array_filter/array_walk和foreach
  1. array_map 返回的是新数组,原数组不变(新数组和原数组的数组长度应该一样)。
  2. array_walk 返回的布尔值,如果要改变数组元素的值,回调函数第一个参数必须是引用,如 array_walk($array, function(&$v, $k){}); , arrary_walk 的回调函数还能够接收数组的key。
  3. array_filter 返回的是新数组,原数组不变。它的作用是过滤数组中的元素。回调函数返回真,元素才能保存到新数组中,即(新数组和原数组的数组长度可能不一样)
  4. foreach 循环处理
*array_reduce

定义和用法

array_reduce() 函数发送数组中的值到用户自定义函数,并返回一个字符串。

注释:如果数组是空的或者初始值未传递,该函数返回 NULL。


语法

array_reduce(array,myfunction,initial)

参数描述
array必需。规定数组。
myfunction必需。规定函数的名称。
initial可选。规定发送到函数处理的第一个值。

技术细节

返回值:返回结果值。
PHP 版本:4.0.5+
更新日志:自 PHP 5.3.0 起,initial 参数接受多类型(混合的),PHP 5.3.0 之前的版本只支持整数。
从数据库中查询出一组数据,接下来想得到他们的 id 值,拼接成类似 (1,2,3,4,5) 字符串,然后在 “SELECT * WHERE id in(1,2,3,4,5) ” 处理,这时候完全可以 foreach() 数组处理,其实也可以使用 array_reduce(),因为 array_reduce()就是“迭代地将数组简化为单一的值”,如下

$arr = array(
  array("id"=>1,'name'=>"a"),
  array("id"=>2,"name"=>"c"),
  array("id"=>3,"name"=>"d")
     );
      echo array_reduce($arr , function($result , $v){
  Return $result.','.$v['id'];
      });
在业务中遇到foreach循环处理,有时候我们就可以想想能不能像这样处理。
*array_map

定义和用法

array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。

回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。

提示:您可以向函数输入一个或者多个数组。

语法

array_map(myfunction,array1,array2,array3...)
参数描述
myfunction必需。用户自定义函数的名称,或者是 null。
array1必需。规定数组。
array2可选。规定数组。
array3可选。规定数组。

技术细节

返回值:返回包含 array1 的值的数组,在向每个值应用自定义函数后。
PHP 版本:4.0.6+

demo

    $array1 = [11,22,33,44,55,11,77];
    $array2 = [11,2,3,4,55,6,7];
    $array3 = [11,220,33,440,550,660,77,88];
  
##ex1 比较常用的用法
show(array_map('intval', $array1));##在拼接sql查询的时候,很有用
array_map('htmlspecialchars' , $arr);##在拼接sql查询的时候,很有用


    ##ex2
    show(array_map(null, $array1,$array2,$array3));
    #输出:
    Array
    (
        [0] => Array
            (
                [0] => 11
                [1] => 11
                [2] => 11
            )
    
        [1] => Array
            (
                [0] => 22
                [1] => 2
                [2] => 220
            )
    
        [2] => Array
            (
                [0] => 33
                [1] => 3
                [2] => 33
            )
    
        [3] => Array
            (
                [0] => 44
                [1] => 4
                [2] => 440
            )
    
        [4] => Array
            (
                [0] => 55
                [1] => 55
                [2] => 550
            )
    
        [5] => Array
            (
                [0] => 11
                [1] => 6
                [2] => 660
            )
    
        [6] => Array
            (
                [0] => 77
                [1] => 7
                [2] => 77
            )
    
        [7] => Array
            (
                [0] => 
                [1] => 
                [2] => 88
            )
    
    )
    ##ex3
    function testFun($var){
        if($var==11){
            return 'true';
        }
    }
    show(array_map('testFun', $array1,$array2,$array3));
    Array
    (
        [0] => true
        [1] => 
        [2] => 
        [3] => 
        [4] => 
        [5] => true
        [6] => 
        [7] => 
    )
array_walk_recursive

定义和用法

array_walk_recursive() 函数对数组中的每个元素应用用户自定义函数。在函数中,数组的键名和键值是参数。该函数与 array_walk 函数的不同在于可以操作更深的数组(一个数组中包含另一个数组)。

递归地应用用户函数。

语法

array_walk_recursive(array,myfunction,parameter...)

参数描述
array必需。规定数组。
myfunction必需。用户自定义函数的名称。
parameter,...可选。规定用户自定义函数的参数,您可以为函数设置一个或多个参数。

技术细节

返回值:如果成功则返回 TRUE,否则返回 FALSE。
PHP 版本:5+
*array_walk

定义和用法

array_walk() 函数对数组中的每个元素应用用户自定义函数。在函数中,数组的键名和键值是参数。

注释:您可以通过把用户自定义函数中的第一个参数指定为引用:&$value,来改变数组元素的值(参见实例 2)。

提示:如需操作更深的数组(一个数组中包含另一个数组),请使用 array_walk_recursive 函数。


语法

array_walk(array,myfunction,parameter...)

参数描述
array必需。规定数组。
myfunction必需。用户自定义函数的名称。
parameter,...可选。规定用户自定义函数的参数,您可以为函数设置一个或多个参数。

技术细节

返回值:如果成功则返回 TRUE,否则返回 FALSE。
PHP 版本:4+

demo

#ex1
$array1 = [11,22,33,44,55,11,77];

function func1($val){
    echo  'this is v'.$val.'<br/>';
}
show(array_walk($array1, 'func1'));
##输出
this is v11
this is v22
this is v33
this is v44
this is v55
this is v11
this is v77
bool(true)

#ex2
$array1 = [11,22,33,44,55,11,77];
function func2(&$val){
    $val =  'this is '.$val;
}
show($array1);
Array
(
    [0] => this is 11
    [1] => this is 22
    [2] => this is 33
    [3] => this is 44
    [4] => this is 55
    [5] => this is 11
    [6] => this is 77
)
*array_filter

定义和用法

array_filter() 函数用回调函数过滤数组中的值。

该函数把输入数组中的每个键值传给回调函数。如果回调函数返回 true,则把输入数组中的当前键值返回结果数组中。数组键名保持不变。

语法

array_filter(array,callbackfunction);
参数描述
array必需。规定要过滤的数组。
callbackfunction必需。规定要使用的回调函数。

技术细节

返回值:返回过滤的数组。
PHP 版本:4.0.6+

demo

    $array1 = [11,22,33,44,55];
    
    function callFun($array){
        if($array==11) return 1;
    }
    ##原数据
    show($array1);
    
    ##过滤后的数据
    show(array_filter($array1,'callFun'));
    ##原数组
    Array
    (
        [0] => 11
        [1] => 22
        [2] => 33
        [3] => 44
        [4] => 55
    )
    ##过滤后的数组
    Array
    (
        [0] => 11
    )
array_change_key_case

[TOC]

定义和用法

函数将数组的所有的键都转换为大写字母或小写字母。

语法

array_change_key_case(array,case);
参数描述
array必需。规定要使用的数组。
case可选。可能的值:CASE_LOWER - 默认值。将数组的键转换为小写字母。CASE_UPPER - 将数组的键转换为大写字母。

技术细节

返回值:返回键为大写或小写的数组,或者如果 array 非数组则返回 FALSE。
PHP 版本:4.2+

demo

$array2 = ['bill'=>['slary'=>100],'cherry'=>['slary'=>200]];

show(array_change_key_case($array2,CASE_UPPER));
##输出


Array
(
    [BILL] => Array
        (
            [slary] => 100
        )

    [CHERRY] => Array
        (
            [slary] => 200
        )

)
array_chunk

[TOC]

定义和用法

数组分割为新的数组块。每个数组的单元数目由 size 参数决定。最后一个数组的单元数目可能会少几个。
可选参数 preserve_key 是一个布尔值,它指定新数组的元素是否有和原数组相同的键(用于关联数组),还是从 0 开始的新数字键(用于索引数组)。默认是分配新的键。

语法

array_chunk(array,size,preserve_key);
参数描述
array必需。规定要使用的数组。
size必需。整数值,规定每个新数组包含多少个元素。
preserve_key可选。可能的值:true - 保留原始数组中的键名。false - 默认。每个结果数组使用从零开始的新数组索引。

技术细节

返回值:返回一个多维的索引数组,从 0 开始,每个维度都包含 size 个元素。
PHP 版本:4.2+

demo

    $arr = ['array1','array2','array3','array4'];
    show(array_chunk($arr, 3));
    ##输出
    Array
    (
        [0] => Array
            (
                [0] => array1
                [1] => array2
                [2] => array3
            )

        [1] => Array
            (
                [0] => array4
            )

    )
array_column

[TOC]

定义和用法

返回输入数组中某个单一列的值。

语法

array_column(array,column_key,index_key);
参数描述
array必需。规定要使用的多维数组(记录集)。
column_key必需。需要返回值的列。可以是索引数组的列的整数索引,或者是关联数组的列的字符串键值。该参数也可以是 NULL,此时将返回整个数组(配合 index_key 参数来重置数组键的时候,非常有用)。
index_key可选。用作返回数组的索引/键的列。

技术细节

返回值:返回数组,此数组的值为输入数组中某个单一列的值。
PHP 版本:5.5+

demo

        $array = [
          [
            'id' => 5698,
            'first_name' => 'Bill',
            'last_name' => 'Gates',
          ],
          [
            'id' => 4767,
            'first_name' => 'Steve',
            'last_name' => 'Jobs',
          ],
          [
            'id' => 3809,
            'first_name' => 'Mark',
            'last_name' => 'Zuckerberg',
          ]
        ];

show(array_column($array,'first_name','id'));
##输出

Array
(
    [5698] => Bill
    [4767] => Steve
    [3809] => Mark
)
array_combine

[TOC]

定义和用法

函数通过合并两个数组来创建一个新数组,其中的一个数组是键名,另一个数组的值为键值。
注释:键名数组和键值数组的元素个数必须相同!
如果其中一个数组为空,或者两个数组的元素个数不同,则该函数返回 false。

语法

array_combine(keys,values);
参数描述
keys必需。键名数组。
values必需。键值数组。

提示和注释

注释:两个参数必须有相同数目的元素。

技术细节

返回值:返回合并后的数组。如果两个数组的元素个数不匹配,则返回 FALSE。
PHP 版本:5+
更新日志:在 PHP 5.4 版本之前,如果数组为空,将会报 E_WARNING 级别错误并返回 FALSE。
                                                  |

demo

$array1 = [11,22,33,44,55];
$array2 = ['test1','test2','test3','test4','test5'];
show(array_combine($array1, $array2));
##输出

   Array
(
    [11] => test1
    [22] => test2
    [33] => test3
    [44] => test4
    [55] => test5
)
array_count_values

定义和用法

array_count_values() 函数对数组中的所有值进行计数。

说明

array_count_values() 函数用于统计数组中所有值出现的次数。

本函数返回一个数组,其元素的键名是原数组的值,键值是该值在原数组中出现的次数。

语法

array_count_values(array)
参数描述
array必需。规定需要对值进行计数的数组。

技术细节

返回值:返回关联数组,其元素的键名是原数组的值,键值是该值在原数组中出现的次数。
PHP 版本:4+

demo

       $array2 = ['test1','test2','test3','test4','test2','trrs'=>['test1','test2'],'trrsd'=>'test1'];
    show(array_count_values($array2));
##多维数组并不在计算列
##输出:
Array
(
    [test1] => 2
    [test2] => 2
    [test3] => 1
    [test4] => 1
)
array_fill

定义和用法

array_fill() 函数用键值填充数组。

说明

array_fill() 函数用给定的值填充数组,返回的数组有 number 个元素,值为 value。返回的数组使用数字索引,从 start 位置开始并递增。如果 number 为 0 或小于 0,就会出错。

语法

array_fill(index,number,value);
参数描述
index必需。被返回数组的第一个索引。 (开始的索引数)
number必需。规定要插入的元素数。 (插入几个)
value必需。规定供填充数组所使用的值。(值)

技术细节

返回值:返回被填充的数组。
PHP 版本:4.2+

DEMO

$a1=array_fill(3,4,"test");
show($a1);
#输出
Array
(
    [3] => test
    [4] => test
    [5] => test
    [6] => test
)
array_fill_keys

定义和用法

array_fill_keys() 函数使用指定的键和值填充数组。

语法

array_fill_keys(keys,value);
参数描述
keys必需。使用该数组的值作为键。非法值将被转换为字符串。
value必需。填充数组所使用的值。

技术细节

返回值:返回被填充的数组。
PHP 版本:5.2+

demo

$array1 = [11,22,33,44,55];
show(array_fill_keys($array1, 'test'));
##输出
Array
(
    [11] => test
    [22] => test
    [33] => test
    [44] => test
    [55] => test
)
array_key_exists

定义和用法

array_key_exists() 函数检查某个数组中是否存在指定的键名,如果键名存在则返回 true,如果键名不存在则返回 false。

提示:请记住,如果您指定数组的时候省略了键名,将会生成从 0 开始并且每个键值对应以 1 递增的整数键名。(参阅例子 2)

语法

array_key_exists(key,array)
参数描述
key必需。规定键名。
array必需。规定数组。

技术细节

返回值:如果键名存在则返回 TRUE,如果键名不存在则返回 FALSE。
PHP 版本:4.0.7+

demo

$array1 = [11,22,33,44,55,11,77];
show(array_key_exists(0, $array1));

##输出
bool(true)
array_keys

定义和用法

array_keys() 函数返回包含数组中所有键名的一个新数组。
如果提供了第二个参数,则只返回键值为该值的键名。
如果 strict 参数指定为 true,则 PHP 会使用全等比较 (===) 来严格检查键值的数据类型。

语法

array_keys(array,value,strict)
参数描述
array必需。规定数组。
value可选。您可以指定键值,然后只有该键值对应的键名会被返回。
strict可选。与 value 参数一起使用。可能的值:true - 返回带有指定键值的键名。依赖类型,数字 5 与字符串 "5" 是不同的。false - 默认值。不依赖类型,数字 5 与字符串 "5" 是相同的。

技术细节

返回值:返回包含数组中所有键名的一个新数组。
PHP 版本:4+
更新日志:strict 参数是在 PHP 5.0 中新增的。

DEMO

$array3 = ['test1','test2','test3','test4','test6','trrs'=>['test1','test2'],'trrsd'=>'test1','22'];

show(array_keys($array3));


#输出
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => trrs
    [6] => trrsd
    [7] => 5
)

##EX2
$array3 = ['test1','test2','test3','test4','test6','trrs'=>['test1','test2'],'trrsd'=>'test1','22'];
show(array_keys($array3,'test2'));

Array
(
    [0] => 1
)
array_merge

定义和用法

array_merge() 函数把一个或多个数组合并为一个数组。

提示:您可以向函数输入一个或者多个数组。

注释:如果两个或更多个数组元素有相同的键名,则最后的元素会覆盖其他元素。

注释:如果您仅向 array_merge() 函数输入一个数组,且键名是整数,则该函数将返回带有整数键名的新数组,其键名以 0 开始进行重新索引(参见下面的实例 1)。

提示:该函数与 array_merge_recursive()函数之间的不同是在处理两个或更多个数组元素有相同的键名的情况。array_merge_recursive() 不会进行键名覆盖,而是将多个相同键名的值递归组成一个数组。

语法

array_merge(array1,array2,array3...)
参数描述
array1必需。规定数组。
array2可选。规定数组。
array3可选。规定数组。

技术细节

返回值:返回合并的数组。
PHP 版本:4+
更新日志:自 PHP 5.0 起,该函数仅接受数组类型的参数。

demo

array_merge_recursive

定义和用法

array_merge_recursive() 函数把一个或多个数组合并为一个数组。

该函数与 array_merge() 函数的区别在于处理两个或更多个数组元素有相同的键名时。array_merge_recursive() 不会进行键名覆盖,而是将多个相同键名的值递归组成一个数组。

注释:如果您仅仅向 array_merge_recursive() 函数输入一个数组,结果与 array_merge() 相同,函数将返回带有整数键名的新数组,其键名以 0 开始进行重新索引。

语法

array_merge_recursive(array1,array2,array3...)
参数描述
array1必需。规定数组。
array2可选。规定数组。
array3可选。规定数组。

技术细节

返回值:返回合并的数组。
PHP 版本:4.0.1+

demo

见array_merge,array_recursive区别分析

array_merge,array_recursive区别

我们先看下DEMO

总结

+号

(键名相同,不追加)

  1. 不覆盖,只是追加不存在的键名和对应的值
  2. 键名不重新索引
  3. 无论是全部数字键名还是混合,都只是追加键名和值,如果键名相同则不进行追加,即把最先出现的值作为最终结果返回

array_merge

合并

array_merge_recursive

递规合并,它和ARRAY_MERGE不同的是,如果KEY值相加,但VALUE不同,不会覆盖,会组成新的数组元素,并不会覆盖

DEMO

$fruit1 = array("apple" => "red", "banana" => "yellow");
$fruit2 = array("pear" => "yellow", "apple" => "green");
show(array_merge($fruit1, $fruit2));
show(array_merge_recursive($fruit1, $fruit2));
show($fruit1+$fruit2);

    ##输出
##array_merge
Array
(
    [apple] => green
    [banana] => yellow
    [pear] => yellow
)
##array_merge_recursive
Array
(
    [apple] => Array
        (
            [0] => red
            [1] => green
        )

    [banana] => yellow
    [pear] => yellow
)
##+号
Array
(
    [apple] => red
    [banana] => yellow
    [pear] => yellow
)

array_pad

定义和用法

array_pad() 函数将指定数量的带有指定值的元素插入到数组中。

提示:如果您将 size 参数设置为负数,该函数会在原始数组之前插入新的元素(参见下面的实例)。

注释:如果 size 参数小于原始数组的长度,该函数不会删除任何元素。
注意:size必需大于数组个数,不然插入无效果array_pad并不会覆盖或者更改数组元素。


语法

array_pad(array,size,value)

参数描述
array必需。规定数组。
size必需。规定从函数返回的数组元素个数。
value必需。规定从函数返回的数组中新元素的值。

技术细节

返回值:返回带有新元素的数组。
PHP 版本:4+

demo

##SIZE小于、等于数组元素,插入无效
$array1 = [11,22,33,44,55,11,77];
show(array_pad($array1,7,"blue"));
##输出
Array
(
    [0] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [5] => 11
    [6] => 77
)

##SIZE大于数组元素(或负数组个数时)
$array1 = [11,22,33,44,55,11,77];
show(array_pad($array1,-8,"blue"));
##输出
Array
(
    [0] => blue
    [1] => 11
    [2] => 22
    [3] => 33
    [4] => 44
    [5] => 55
    [6] => 11
    [7] => 77
)
show(array_pad($array1,8,"blue"));
#输出
Array
(
    [0] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [5] => 11
    [6] => 77
    [7] => blue
)

array_pop

定义和用法

array_pop() 函数删除数组中的最后一个元素。(出栈)


语法

array_pop(array)

参数描述
array必需。规定数组。

技术细节

返回值:返回数组的最后一个值。如果数组是空的,或者不是一个数组,将返回 NULL。
PHP 版本:4+

demo

##一维数组
$array1 = [11,22,33,44,55,11,77];
show(array_pop($array1));
show($array1);
##输出
77
Array
(
    [0] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [5] => 11
)
##多维数组
$array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
show(array_pop($array3));
show($array3);
Array
(
    [0] => test1
    [1] => test2
)
Array
(
    [0] => test1
    [1] => test2
    [2] => test3
    [3] => test4
    [4] => test6
)
array_pash

定义和用法

array_push() 函数向数组尾部插入一个或多个元素。(入栈)

提示:您可以添加一个或者多个值。

注释:即使您的数组有字符串键名,您所添加的元素将是数字键名(参见下面的实例)。


语法

array_push(array,value1,value2...)

参数描述
array必需。规定一个数组。
value1必需。规定要添加的值。
value2可选。规定要添加的值。

技术细节

返回值:返回新数组的元素个数。
PHP 版本:4+

demo

$array1 = [11,22,33,44,55,11,77];
$array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
$fruit2 = array("pear" => "yellow", "apple" => "green");



show(array_push($array1, $array3,$fruit2));
show($array1);

#输出
9
Array
(
    [0] => 11
    [1] => 22
    [2] => 33
    [3] => 44
    [4] => 55
    [5] => 11
    [6] => 77
    [7] => Array
        (
            [0] => test1
            [1] => test2
            [2] => test3
            [3] => test4
            [4] => test6
            [last] => Array
                (
                    [0] => test1
                    [1] => test2
                )

        )

    [8] => Array
        (
            [pear] => yellow
            [apple] => green
        )

)
array_rand

定义和用法

array_rand() 函数返回数组中的一个随机键名,或者如果指定函数返回键名不只一个,则返回一个包含随机键名的数组。


语法

array_rand(array,number)

参数描述
array必需。规定数组。
number可选。规定返回多少个随机的元素。

技术细节

返回值:返回数组中的一个随机键名,或者如果指定函数返回键名不只一个,则返回一个包含随机键名的数组。
PHP 版本:4+
更新日志:自 PHP 5.2.10 起,键名的结果数组不再ay of keys is no longer shuffled。 自 PHP 4.2.0 起,随机数生成器会自动播种。

demo

$array1 = [11,22,33,44,55,11,77];
show(array_rand($array1,3));
##输出
##随机生成
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)
array_reverse

定义和用法

array_reverse() 函数返回翻转顺序的数组。

个人理解为数组倒序

语法

array_reverse(array,preserve)

参数描述
array必需。规定数组。
preserve可选。规定是否保留原始数组的键名。 可能的值:true/false

技术细节

返回值:返回翻转后的数组。
PHP 版本:4+
更新日志:preserve 参数是在 PHP 4.0.3 中新增的。

## demo

$a=array("a"=>"Volvo","b"=>"BMW","c"=>"Toyota");

show(array_reverse($a));

##输出
Array
(
    [c] => Toyota
    [b] => BMW
    [a] => Volvo
)
array_search

定义和用法

array_search() 函数在数组中搜索某个键值,并返回对应的键名。

如果在数组中找到键值超过一次,则返回第一次找到的键值所匹配的键名

语法

array_search(value,array,strict)

参数描述
value必需。规定在数组中搜索的键值。
array必需。规定被搜索的数组。
strict可选。如果该参数被设置为 TRUE,则函数在数组中搜索数据类型和值都一致的元素。可能的值:truefalse - 默认如果设置为 true,则在数组中检查给定值的类型,数字 5 和字符串 5 是不同的(参见实例 2)。

技术细节

返回值:如果在数组中找到指定的键值,则返回对应的键名,否则返回 FALSE。如果在数组中找到键值超过一次,则返回第一次找到的键值所匹配的键名。
PHP 版本:4.0.5+
更新日志:如果向函数传递无效的参数,函数返回 NULL(这个适用于自 PHP 5.3.0 起的所有的 PHP 函数)。 自 PHP 4.2.0 起,如果搜索失败,该函数返回 FALSE,而不是 NULL。

demo

$array3 = ['test1','test1','test3','test4','test6','last'=>['test1','test2']];

show(array_search('test2', $array3));

##输出
0
array_shift

定义和用法

array_shift() 函数删除数组中第一个元素,并返回被删除元素的值。

注释:如果键名是数字的,所有元素都将获得新的键名,从 0 开始,并以 1 递增(参见下面实例)。


语法

array_shift(array)

参数描述
array必需。规定数组。

技术细节

返回值:返回从数组中删除元素的值,如果数组为空则返回 NULL。
PHP 版本:4+

demo

$array1 = [11,22,33,44,55,11,77=>[71,72,73,74]];
$array2 = [11=>[11,22],22,33,44,55,11,77=>[71,72,73,74],2315,189,8,2,11,852,77=>[71,72,73,74]];
show(array_shift($array1));
show(array_shift($array2));
## 输出 
11
Array
(
    [0] => 11
    [1] => 22
)
array_unshift

定义和用法

array_unshift() 函数用于向数组插入新元素。新数组的值将被插入到数组的开头。

提示:您可以插入一个或多个值。

注释:数值键名将从 0 开始,以 1 递增。字符串键名将保持不变。

value 不能为数组

语法

array_unshift(array,value1,value2,value3...)

参数描述
array必需。规定数组。
value1必需。规定插入的值。
value2可选。规定插入的值。
value3可选。规定插入的值。

技术细节

返回值:返回新数组中元素的个数。
PHP 版本:4+

demo

$array1 = [11,22,33,44,55,11,77=>[71,72,73,74]];
$array2 = [11=>[11,22],22,33,44,55,11,77=>[71,72,73,74],2315,189,8,2,11,852,77=>[71,72,73,74]];
show(array_unshift($array1, 'insert'));
show($array1);
##输出
8
Array
(
    [0] => insert
    [1] => 11
    [2] => 22
    [3] => 33
    [4] => 44
    [5] => 55
    [6] => 11
    [7] => Array
        (
            [0] => 71
            [1] => 72
            [2] => 73
            [3] => 74
        )

)
##当插和数为数组时,报错。
$insert = ['inster1','insert2'];
show(array_unshift($array2, $insert);

待补充array_splice
待补充compact
count/sizeof

定义和用法

count() 函数返回数组中元素的数目。
sizeof() 函数是 count() 函数的别名。

引处注意第三个参数mode 当MODE 为1时,递归计算元素数目

语法

count(array,mode);

参数描述
array必需。规定要计数的数组。
mode可选。规定函数的模式。可能的值:0 - 默认。不计算多维数组中的所有元素。1 - 递归地计算数组中元素的数目(计算多维数组中的所有元素)。

技术细节

返回值:返回数组中元素的数目。
PHP 版本:4+
更新日志:mode 参数是在 PHP 4.2 中新增的。

demo

$array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
show(count($array3));
show(count($array3,1));

##输出
6
8
current/pos

定义和用法

current() 函数返回数组中的当前元素的值。
pos() 函数是 current() 函数的别名。
每个数组中都有一个内部的指针指向它的"当前"元素,初始指向插入到数组中的第一个元素。

提示:该函数不会移动数组内部指针。

返出当前数组的第一个元素,并且不会移动指针

语法

current(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:返回数组中的当前元素的值,如果当前元素为空或者当前元素没有值则返回 FALSE。
PHP 版本:4+

demo

$array3 = ['last'=>['test1','test2'],'test1','test2','test3','test4','test6'];
$array4 = ['test1','test2','test3','test4','test6'];

show(current($array3));
##输出
Array
(
    [0] => test1
    [1] => test2
)
show(current($array4));
##输出
test1
list

定义和用法

list() 函数用于在一次操作中给一组变量赋值。(看不懂。。。。。)

简单理解,就是把数组里面的值,给list里面定义的变量
list($a,$a) = [1,2,3]; 那么$a值就是1,$b的值就是2

注释:该函数只用于数字索引的数组。


语法

list(var1,var2...)

参数描述
var1必需。第一个需要赋值的变量。
var2,...可选。更多需要赋值的变量。

技术细节

返回值:返回被赋值的数组。
PHP 版本:4+

demo

$my_array = array("Dog",'sr',"Horse",['test1','test2','test3','test4','test6']);

list($a, , $c,$d) = $my_array;
echo "Here I only use the $a and $c variables.";
show($d);
##输出
Here I only use the Dog and Horse variables.
Array
(
    [0] => test1
    [1] => test2
    [2] => test3
    [3] => test4
    [4] => test6
)
each

定义和用法

each() 函数返回当前元素的键名和键值,并将内部指针向前移动。
该元素的键名和键值返回到带有四个元素的数组中。两个元素(1 和 Value)包含键值,两个元素(0 和 Key)包含键名。


语法

each(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:返回当前元素的键名和键值。该元素的键名和键值返回到带有四个元素的数组中。两个元素(1 和 Value)包含键值,两个元素(0 和 Key)包含键名。如果没有更多的数组元素,则函数返回 FALSE。
PHP 版本:4+

demo

##配合LIST使用
#ex1
$array3 = ['last'=>['test1','test2'],'test1','test2','test3','test4','test6'];
while (list($key, $val) = each($array3))
{
echo "$key => $val<br>";
}
##输出
last => Array
0 => test1
1 => test2
2 => test3
3 => test4
4 => test6

#ex2
$array3 = ['last'=>['test1','test2'],'test1','test2','test3','test4','test6'];
show(each($array3));
show(each($array3));
show(each($array3));
show(each($array3));
show(each($array3));
show(each($array3));
##输出
Array
(
    [1] => Array
        (
            [0] => test1
            [1] => test2
        )

    [value] => Array
        (
            [0] => test1
            [1] => test2
        )

    [0] => last
    [key] => last
)
Array
(
    [1] => test1
    [value] => test1
    [0] => 0
    [key] => 0
)
Array
(
    [1] => test2
    [value] => test2
    [0] => 1
    [key] => 1
)
Array
(
    [1] => test3
    [value] => test3
    [0] => 2
    [key] => 2
)
Array
(
    [1] => test4
    [value] => test4
    [0] => 3
    [key] => 3
)
Array
(
    [1] => test6
    [value] => test6
    [0] => 4
    [key] => 4
)

end

定义和用法

end() 函数将内部指针指向数组中的最后一个元素,并输出。

相关的方法:


语法

end(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:如果成功则返回数组中最后一个元素的值,如果数组为空则返回 FALSE。
PHP 版本:4+

## demo

 $array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
$array4 = ['test1','test2','test3','test4','test6'];

show(end($array3));
show(end($array4));
##输出
Array
(
    [0] => test1
    [1] => test2
)

test6
extract

定义和用法

extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

该函数返回成功设置的变量数目。


语法

extract(array,extract_rules,prefix)

参数描述
array必需。规定要使用的数组。
extract_rules可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。可能的值:EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。EXTR_SKIP - 如果有冲突,不覆盖已有的变量。EXTR_PREFIX_SAME - 如果有冲突,在变量名前加上前缀 prefix。EXTR_PREFIX_ALL - 给所有变量名加上前缀 prefix。EXTR_PREFIX_INVALID - 仅在不合法或数字变量名前加上前缀 prefix。EXTR_IF_EXISTS - 仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。EXTR_PREFIX_IF_EXISTS - 仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。EXTR_REFS - 将变量作为引用提取。导入的变量仍然引用了数组参数的值。
prefix可选。如果 extract_rules 参数的值是 EXTR_PREFIX_SAME、EXTR_PREFIX_ALL、 EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS,则 prefix 是必需的。 该参数规定了前缀。前缀和数组键名之间会自动加上一个下划线。

技术细节

返回值:返回成功设置的变量数目。
PHP 版本:4+
更新日志:extract_rules 的值 EXTR_REFS 是在 PHP 4.3 中新增的。 extract_rules 的值 EXTR_IF_EXISTS 和 EXTR_PREFIX_IF_EXISTS 是在 PHP 4.2 中新增的。 自 PHP 4.0.5 起,该函数返回成功设置的变量数目。 extract_rules 的值 EXTR_PREFIX_INVALID 是在 PHP 4.0.5 中新增的。 自 PHP 4.0.5 起,extract_rules 的值 EXTR_PREFIX_ALL 也包含数字变量。

demo

$a = "Original";
$my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse");
extract($my_array, EXTR_PREFIX_SAME, "dup");
echo "$a = $a; $b = $b; $c = $c; $dup_a = $dup_a";

##输出
Original = Original; Dog = Dog; Horse = Horse; Cat = Cat
in_array

定义和用法

in_array() 函数搜索数组中是否存在指定的值。

注释:如果 search 参数是字符串且 type 参数被设置为 TRUE,则搜索区分大小写。

语法

in_array(search,array,type)

参数描述
search必需。规定要在数组搜索的值。
array必需。规定要搜索的数组。
type可选。如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。

技术细节

返回值:如果在数组中找到值则返回 TRUE,否则返回 FALSE。
PHP 版本:4+
更新日志自 PHP 4.2 起,search 参数可以是一个数组。
next

定义和用法

next() 函数将内部指针指向数组中的下一个元素,并输出。

相关的方法:


语法

next(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:如果成功则返回数组中下一个元素的值,如果没有更多的数组元素则返回 FALSE。
PHP 版本:4+

demo

$array4 = ['test1','test2','test3','test4','test6'];
show(next($array4));
show(next($array4));
show(next($array4));
##输出
test2
test3
test4
prev

定义和用法

prev() 函数将内部指针指向数组中的上一个元素,并输出。


语法

prev(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:如果成功则返回数组中上一个元素的值,如果没有更多的数组元素则返回 FALSE。
PHP 版本:4+

demo

$array4 = ['test1','test2','test3','test4','test6'];
show(next($array4));
show(prev($array4));
show(prev($array4));
##输出
test2
test1
bool(false)

range

定义和用法

range() 函数创建一个包含指定范围的元素的数组。

该函数返回一个包含从 low 到 high 之间的元素的数组。

注释:如果 low 参数大于 high 参数,则创建的数组将是从 high 到 low。


语法

range(low,high,step)

参数描述
low必需。规定数组元素的最小值。
high必需。规定数组元素的最大值。
step可选。规定元素之间的步进制。默认是 1。

技术细节

返回值:返回一个包含从 lowhigh 的元素的数组。
PHP 版本:4+
更新日志:step 参数是在 PHP 5.0 中新增的。 在 PHP 4.1.0 到 4.3.2 版本中,该函数将数字字符串看作字符串而不是整数。数字字符串将被用于字符序列,例如,"5252" 被看作 "5"。 支持字符序列和递减数组是在 PHP 4.1.0 中新增的。字符序列的值被限制在一个长度。如果长度大于一个,只使用第一个字符。在该版本之前,range() 只生成递增的整数数组。

demo

show(range(1, 10,2));
Array
(
    [0] => 1
    [1] => 3
    [2] => 5
    [3] => 7
    [4] => 9
)
reset

定义和用法

reset() 函数将内部指针指向数组中的第一个元素,并输出。

函数将内部指针指向数组中的第一个元素,并输出。

语法

reset(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:如果成功则返回数组中第一个元素的值,如果数组为空则返回 FALSE。
PHP 版本:4+

demo

$array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
show(next($array3));
show(reset($array3));
##输出
test2
test1


shuffle(数组随机重新排序)

定义和用法

shuffle() 函数把数组中的元素按随机顺序重新排列。
该函数为数组中的元素分配新的键名,已存在的键名将被删除(参见下面的实例 1)。

数组随机重新排序

语法

shuffle(array)

参数描述
array必需。规定要使用的数组。

技术细节

返回值:如果成功则返回 TRUE,如果失败则返回 FALSE。
PHP 版本:4+
更新日志:自 PHP 4.2.0 起,随机数生成器会自动播种。

demo

$array3 = ['test1','test2','test3','test4','test6','last'=>['test1','test2']];
show(shuffle($array3));
show($array3);

bool(true)
Array
(

[0] => test6
[1] => test2
[2] => test4
[3] => Array
    (
        [0] => test1
        [1] => test2
    )

[4] => test1
[5] => test3

)

String 字符串

PHP String 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

函数描述
addcslashes()返回在指定的字符前添加反斜杠的字符串。
addslashes()返回在预定义的字符前添加反斜杠的字符串。
bin2hex()把 ASCII 字符的字符串转换为十六进制值。
chop()移除字符串右侧的空白字符或其他字符。
chr()从指定 ASCII 值返回字符。
chunk_split()把字符串分割为一连串更小的部分。
convert_cyr_string()把字符串由一种 Cyrillic 字符集转换成另一种。
convert_uudecode()对 uuencode 编码的字符串进行解码。
convert_uuencode()使用 uuencode 算法对字符串进行编码。
count_chars()返回字符串所用字符的信息。
crc32()计算一个字符串的 32 位 CRC(循环冗余校验)。
crypt()单向的字符串加密法(hashing)。
echo()输出一个或多个字符串。
explode()把字符串打散为数组。
fprintf()把格式化的字符串写入到指定的输出流。
get_html_translation_table()返回 htmlspecialchars() 和 htmlentities() 使用的翻译表。
hebrev()把希伯来(Hebrew)文本转换为可见文本。
hebrevc()把希伯来(Hebrew)文本转换为可见文本,并把新行(\n)转换为
hex2bin()把十六进制值的字符串转换为 ASCII 字符。
html_entity_decode()把 HTML 实体转换为字符。
htmlentities()把字符转换为 HTML 实体。
htmlspecialchars_decode()把一些预定义的 HTML 实体转换为字符。
htmlspecialchars()把一些预定义的字符转换为 HTML 实体。
implode()返回一个由数组元素组合成的字符串。
join()implode() 的别名。
lcfirst()把字符串中的首字符转换为小写。
levenshtein()返回两个字符串之间的 Levenshtein 距离。
localeconv()返回本地数字及货币格式信息。
ltrim()移除字符串左侧的空白字符或其他字符。
md5()计算字符串的 MD5 散列。
md5_file()计算文件的 MD5 散列。
metaphone()计算字符串的 metaphone 键。
money_format()返回格式化为货币字符串的字符串。
nl_langinfo()返回指定的本地信息。
nl2br()在字符串中的每个新行之前插入 HTML 换行符。
number_format()通过千位分组来格式化数字。
ord()返回字符串中第一个字符的 ASCII 值。
parse_str()把查询字符串解析到变量中。
print()输出一个或多个字符串。
printf()输出格式化的字符串。
quoted_printable_decode()把 quoted-printable 字符串转换为 8 位字符串。
quoted_printable_encode()把 8 位字符串转换为 quoted-printable 字符串。
quotemeta()引用元字符。
rtrim()移除字符串右侧的空白字符或其他字符。
setlocale()设置地区信息(地域信息)。
sha1()计算字符串的 SHA-1 散列。
sha1_file()计算文件的 SHA-1 散列。
similar_text()计算两个字符串的相似度。
soundex()计算字符串的 soundex 键。
sprintf()把格式化的字符串写入一个变量中。
sscanf()根据指定的格式解析来自一个字符串的输入。
str_getcsv()把 CSV 字符串解析到数组中。
str_ireplace()替换字符串中的一些字符(大小写不敏感)。
str_pad()把字符串填充为新的长度。
str_repeat()把字符串重复指定的次数。
str_replace()替换字符串中的一些字符(大小写敏感)。
str_rot13()对字符串执行 ROT13 编码。
str_shuffle()随机地打乱字符串中的所有字符。
str_split()把字符串分割到数组中。
str_word_count()计算字符串中的单词数。
strcasecmp()比较两个字符串(大小写不敏感)。
strchr()查找字符串在另一字符串中的第一次出现。(strstr() 的别名。)
strcmp()比较两个字符串(大小写敏感)。
strcoll()比较两个字符串(根据本地设置)。
strcspn()返回在找到任何指定的字符之前,在字符串查找的字符数。
strip_tags()剥去字符串中的 HTML 和 PHP 标签。
stripcslashes()删除由 addcslashes() 函数添加的反斜杠。
stripslashes()删除由 addslashes() 函数添加的反斜杠。
stripos()返回字符串在另一字符串中第一次出现的位置(大小写不敏感)。
stristr()查找字符串在另一字符串中第一次出现的位置(大小写不敏感)。
strlen()返回字符串的长度。
strnatcasecmp()使用一种"自然排序"算法来比较两个字符串(大小写不敏感)。
strnatcmp()使用一种"自然排序"算法来比较两个字符串(大小写敏感)。
strncasecmp()前 n 个字符的字符串比较(大小写不敏感)。
strncmp()前 n 个字符的字符串比较(大小写敏感)。
strpbrk()在字符串中搜索指定字符中的任意一个。
strpos()返回字符串在另一字符串中第一次出现的位置(大小写敏感)。
strrchr()查找字符串在另一个字符串中最后一次出现。
strrev()反转字符串。
strripos()查找字符串在另一字符串中最后一次出现的位置(大小写不敏感)。
strrpos()查找字符串在另一字符串中最后一次出现的位置(大小写敏感)。
strspn()返回在字符串中包含的特定字符的数目。
strstr()查找字符串在另一字符串中的第一次出现(大小写敏感)。
strtok()把字符串分割为更小的字符串。
strtolower()把字符串转换为小写字母。
strtoupper()把字符串转换为大写字母。
strtr()转换字符串中特定的字符。
substr()返回字符串的一部分。
substr_compare()从指定的开始位置(二进制安全和选择性区分大小写)比较两个字符串。
substr_count()计算子串在字符串中出现的次数。
substr_replace()把字符串的一部分替换为另一个字符串。
trim()移除字符串两侧的空白字符和其他字符。
ucfirst()把字符串中的首字符转换为大写。
ucwords()把字符串中每个单词的首字符转换为大写。
vfprintf()把格式化的字符串写到指定的输出流。
vprintf()输出格式化的字符串。
vsprintf()把格式化字符串写入变量中。
wordwrap()按照指定长度对字符串进行折行处理。
输出
===vsprintf()
===vprintf()
===vfprintf()
_sprintf
_fprintf

定义和用法

fprintf() 函数把格式化的字符串写入指定的输出流(例如:文件或数据库)。

arg1arg2arg++ 参数将被插入主字符串中的百分号(%)符号处。该函数是逐步执行的。在第一个 % 符号处,插入 arg1,在第二个 % 符号处,插入 arg2,依此类推。

注释:如果 % 符号多于 arg 参数,则您必须使用占位符。占位符被插入到 % 符号后面,由数字和 "$" 组成。请参见实例 2。

语法

fprintf(stream,format,arg1,arg2,arg++)
参数描述
stream必需。规定在何处写入/输出字符串。
format必需。规定字符串以及如何格式化其中的变量。可能的格式值:%% - 返回一个百分号 %%b - 二进制数%c - ASCII 值对应的字符%d - 包含正负号的十进制数(负数、0、正数)%e - 使用小写的科学计数法(例如 1.2e+2)%E - 使用大写的科学计数法(例如 1.2E+2)%u - 不包含正负号的十进制数(大于等于 0)%f - 浮点数(本地设置)%F - 浮点数(非本地设置)%g - 较短的 %e 和 %f%G - 较短的 %E 和 %f%o - 八进制数%s - 字符串%x - 十六进制数(小写字母)%X - 十六进制数(大写字母)附加的格式值。必需放置在 % 和字母之间(例如 %.2f):+ (在数字前面加上 + 或 - 来定义数字的正负性。 默认地,只有负数才做标记,正数不做标记)' (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。 例如:%'x20s(使用 "x" 作为填充))- (左调整变量值)[0-9] (规定变量值的最小宽度).[0-9] (规定小数位数或最大字符串长度)注释:如果使用多个额外的格式值,则必须按照上面的顺序进行使用。
arg1必需。规定插到 format 字符串中第一个 % 符号处的参数。
arg2可选。规定插到 format 字符串中第二个 % 符号处的参数。
arg++可选。规定插到 format 字符串中第三、四等等 % 符号处的参数。

技术细节

返回值:返回被写字符串的长度。
PHP 版本:5+
echo

定义和用法

echo() 函数输出一个或多个字符串。

注释:echo() 函数实际不是一个函数,所以您不必对它使用括号。然而,如果您想要传多于一个参数给 echo(),使用括号将会生成解析错误。

提示:echo() 函数比 print 速度稍快。

提示:echo() 函数也有简化语法。在 PHP 5.4.0 版本之前,该语法只适用于 short_open_tag 配置设置启用的情况。


语法

echo(strings)

参数描述
strings必需。一个或多个要发送到输出的字符串。

技术细节

返回值:没有返回值。
PHP 版本:4+

demo

$test = 'test';
$number = 110152326;
echo $test;
echo "<br/>";
echo $test,$number;

##输出
test
test110152326
print

定义和用法

print() 函数输出一个或多个字符串。

注释:print() 函数实际不是一个函数,所以您不必对它使用括号。

提示:print() 函数比 echo() 速度稍慢。


语法

print(strings)

参数描述
strings必需。发送到输出的一个或多个字符串。

技术细节

返回值:总是返回 1。
PHP 版本:4+

## demo

 $test = 'test';
print $test;
echo "<br/>";
$p = print $test;
show($p);
##输出

test
test
1
printf

定义和用法

printf() 函数输出格式化的字符串。

arg1、arg2、++ 参数将被插入到主字符串中的百分号(%)符号处。该函数是逐步执行的。在第一个 % 符号处,插入 arg1,在第二个 % 符号处,插入 arg2,依此类推。

注释:如果 % 符号多于 arg 参数,则您必须使用占位符。占位符被插入到 % 符号之后,由数字和 "$" 组成。请参见实例 2。

提示:相关函数:sprintf()、vprintf()、 vsprintf()、 fprintf()和 vfprintf()


语法

printf(format,arg1,arg2,arg++)

参数描述
format必需。规定字符串以及如何格式化其中的变量。可能的格式值:<br/>%% - 返回一个百分号 <br/>%%b - 二进制数%c - ASCII 值对应的字符%d - 包含正负号的十进制数(负数、0、正数)<br/>%e - 使用小写的科学计数法(例如 1.2e+2)<br/>%E - 使用大写的科学计数法(例如 1.2E+2)<br/>%u - 不包含正负号的十进制数(大于等于 0)<br/>%f - 浮点数(本地设置)<br/>%F - 浮点数(非本地设置)<br/>%g - 较短的 <br/>%e 和 %f%G - 较短的 <br/>%E 和 %f%o - 八进制数<br/>%s - 字符串<br/>%x - 十六进制数(小写字母)<br/>%X - 十六进制数(大写字母)附加的格式值。必需放置在 % 和字母之间(例如 %.2f):+ (在数字前面加上 + 或 - 来定义数字的正负性。默认情况下,只有负数才做标记,正数不做标记)' (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。例如:%'x20s(使用 "x" 作为填充))- (左调整变量值)[0-9] (规定变量值的最小宽度).[0-9] (规定小数位数或最大字符串长度)<br/>注释:如果使用多个上述的格式值,它们必须按照上面的顺序进行使用,不能打乱。
arg1必需。规定插到 format 字符串中第一个 % 符号处的参数。
arg2可选。规定插到 format 字符串中第二个 % 符号处的参数。
arg++可选。规定插到 format 字符串中第三、四等等 % 符号处的参数。

技术细节

返回值:返回被输出字符串的长度。
PHP 版本:4+

demo18319996105

$number = 100;

printf("%f",$number);
printf("%%",$number);

##输出
100.000000
%


var_dump

定义和用法

var_dump() 此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。


语法

void var_dump ( mixed $expression [, mixed $... ] )

技术细节

返回值:没有返回值。
PHP 版本:4+
echo与print,var_dump()和print_r()的区别
  1. echo 和 print 的区别

共同点:首先echo 和 print 都不是严格意义上的函数,他们都是 语言结构;他们都只能输出 字符串,整型跟int型浮点型数据。不能打印复合型和资源型数据;

区别:echo 可以连续输出多个变量,而print只能一次输出一个变量。print打印的值能直接复制给一个变量,如 $test = print “test”;

而echo 不可以,它没有像函数的行为,所以不能用于函数的上下文。在使用时,echo() 函数比 print()速度稍快

  1. var_dump()和print_r()的区别

共同点:两者都可以打印数组,对象之类的复合型变量。

区别:print_r() 只能打印一些易于理解的信息,且print_r()在打印数组时,会将把数组的指针移到最后边,使用 reset() 可让指针回到开始处。 而var_dump()不但能打印复合类型的数据,还能打印资源类型的变量。且var_dump()输出的信息则比较详细,一般调试时用得多。

转义/反转
_htmlentities

定义和用法

htmlentities() 函数把字符转换为 HTML 实体。

提示:要把 HTML 实体转换回字符,请使用 html_entity_decode 函数。

提示:请使用 get_html_translation_table 函数来返回 htmlentities() 使用的翻译表。

语法

htmlentities(string,flags,character-set,double_encode)
参数描述
string必需。规定要转换的字符串。
flags可选。规定如何处理引号、无效的编码以及使用哪种文档类型。可用的引号类型:ENT_COMPAT - 默认。仅编码双引号。<br/>ENT_QUOTES - 编码双引号和单引号。<br/>ENT_NOQUOTES - 不编码任何引号。<br/>无效的编码:ENT_IGNORE - 忽略无效的编码,而不是让函数返回一个空的字符串。应尽量避免,因为这可能对安全性有影响。<br/>ENT_SUBSTITUTE - 把无效的编码替代成一个指定的带有 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD; 的字符,而不是返回一个空的字符串。<br/>ENT_DISALLOWED - 把指定文档类型中的无效代码点替代成 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD;。规定使用的文档类型的附加<br/> flags:<br/>ENT_HTML401 - 默认。作为 HTML 4.01 处理代码。ENT_HTML5 - 作为 HTML 5 处理代码。ENT_XML1 - 作为 XML 1 处理代码。ENT_XHTML - 作为 XHTML 处理代码。
character-set可选。一个规定了要使用的字符集的字符串。允许的值:UTF-8 - 默认。ASCII 兼容多字节的 8 位 UnicodeISO-8859-1 - 西欧ISO-8859-15 - 西欧(加入欧元符号 + ISO-8859-1 中丢失的法语和芬兰语字母)cp866 - DOS 专用 Cyrillic 字符集cp1251 - Windows 专用 Cyrillic 字符集cp1252 - Windows 专用西欧字符集KOI8-R - 俄语BIG5 - 繁体中文,主要在台湾使用GB2312 - 简体中文,国家标准字符集BIG5-HKSCS - 带香港扩展的 Big5Shift_JIS - 日语EUC-JP - 日语MacRoman - Mac 操作系统使用的字符集注释:在 PHP 5.4 之前的版本,无法被识别的字符集将被忽略并由 ISO-8859-1 替代。自 PHP 5.4 起,无法被识别的字符集将被忽略并由 UTF-8 替代。
double_encode可选。布尔值,规定是否编码已存在的 HTML 实体。TRUE - 默认。将对每个实体进行转换。FALSE - 不会对已存在的 HTML 实体进行编码。

技术细节

返回值:返回被转换的字符串。如果 string 包含无效的编码,则返回一个空的字符串,除非设置了 ENT_IGNORE 或者 ENT_SUBSTITUTE 标志。
PHP 版本:4+
更新日志:在 PHP 5 中,character-set 参数的默认值改为 UTF-8。在 PHP 5.4 中,新增了:ENT_SUBSTITUTE、ENT_DISALLOWED、ENT_HTML401、ENT_HTML5、ENT_XML1 和 ENT_XHTML。在 PHP 5.3 中,新增了 ENT_IGNORE。在 PHP 5.2.3 中,新增了 double_encode 参数。在 PHP 4.1 中,新增了 character-set 参数。

demo

addslashes

定义和用法

addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。

预定义的字符前添加反斜杠的字符串

预定义字符是:

  • 单引号(')
  • 双引号(")
  • 反斜杠(\)
  • NULL

提示:该函数可用于为存储在数据库中的字符串以及数据库查询语句准备合适的字符串。

反义:(),删除由 addslashes() 函数添加的反斜杠。该函数用于清理从数据库或 HTML 表单中取回的数据

注释:默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。


语法

addslashes(string)

参数描述
string必需。规定要转义的字符串。

技术细节

返回值:返回已转义的字符串。
PHP 版本:4+

demo

echo addslashes("this is demo . & my name is 'Jerry' .;");
##输出
this is demo . & my name is \'Jerry\' .;
stripslashes

定义和用法

stripslashes() 函数删除由addslashes 函数添加的反斜杠。

提示:该函数可用于清理从数据库中或者从 HTML 表单中取回的数据。


语法

stripslashes(string)

参数描述
string必需。规定要检查的字符串。

技术细节

返回值:返回剥离了反斜杠的字符串。
PHP 版本:4+

demo

echo stripslashes("this is demo . & my name is \'Jerry\' .;");

##输出
this is demo . & my name is 'Jerry' .;
addcslashes

定义和用法

addcslashes() 函数返回在指定的字符前添加反斜杠的字符串。

指定的字符前添加反斜杠的字符串。

注释:addcslashes() 函数是区分大小写的。

注释:在对 0(NULL)、r(回车)、n(换行)、t(换页)、f(制表符)和 v(垂直制表符)应用 addcslashes() 时要小心。在 PHP 中,\0、\r、\n、\t、\f 和 \v 是预定义的转义序列。


语法

addcslashes(string,characters)

参数描述
string必需。规定要转义的字符串。
characters必需。规定要转义的字符或字符范围。

技术细节

返回值:返回已转义的字符串。
PHP 版本:4+

demo

#ex1
$str = "Welcome to my humble Homepage!";
echo $str."<br>";
echo addcslashes($str,'A..Z')."<br>";
echo addcslashes($str,'a..z')."<br>";
echo addcslashes($str,'a..g');

##输出
Welcome to my humble Homepage!
\Welcome to my humble \Homepage!
W\e\l\c\o\m\e \t\o \m\y \h\u\m\b\l\e H\o\m\e\p\a\g\e!
W\el\com\e to my hum\bl\e Hom\ep\a\g\e!

#ex2
$str = addcslashes("Hello World!","W");
echo($str); 
##输出
Hello \World!


(乱码,待后面查解决方法)stripcslashes

定义和用法

stripcslashes() 函数删除由 addcslashes() 函数添加的反斜杠。

提示:该函数可用于清理从数据库中或者从 HTML 表单中取回的数据。


语法

stripcslashes(string)

参数描述
string必需。规定要检查的字符串。

技术细节

返回值:返回非转义的字符串。
PHP 版本:4+
 echo stripcslashes(addcslashes('Welcome to my humble Homepage!','a..g'));

##输出
#好像不是太好用。
Welcome to my humle Homepge!
htmlspecialchars_decode

定义和用法

htmlspecialchars_decode() 函数把一些预定义的 HTML 实体转换为字符。

会被解码的 HTML 实体是:

  • & 解码成 & (和号)
  • " 解码成 " (双引号)
  • ' 解码成 ' (单引号)
  • < 解码成 < (小于)
  • > 解码成 > (大于)

htmlspecialchars_decode() 函数是 htmlspecialchars() 函数的反函数。


语法

htmlspecialchars_decode(string,flags)

参数描述
string必需。规定要解码的字符串。
flags可选。规定如何处理引号以及使用哪种文档类型。可用的引号类型:<br/>ENT_COMPAT - 默认。仅解码双引号。<br/>ENT_QUOTES - 解码双引号和单引号。<br/>ENT_NOQUOTES - 不解码任何引号。规定使用的文档类型的附加<br/> flags:<br/>ENT_HTML401 - 默认。作为 HTML 4.01 处理代码。<br/>ENT_HTML5 - 作为 HTML 5 处理代码。<br/>ENT_XML1 - 作为 XML 1 处理代码。<br/>ENT_XHTML - 作为 XHTML 处理代码。

技术细节

返回值:返回已转换的字符串。
PHP 版本:5.1.0+
更新日志:在 PHP 5.4 中,新增了用于规定使用的文档类型的附加 flags:ENT_HTML401、ENT_HTML5、ENT_XML1 和 ENT_XHTML。
htmlspecialchars

## 定义和用法

htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。

预定义的字符是:

  • & (和号)成为 &
  • " (双引号)成为 "
  • ' (单引号)成为 '
  • < (小于)成为 <
  • \> (大于)成为 >

提示:要把特殊的 HTML 实体转换回字符,请使用htmlspecialchars_decode函数。


语法

htmlspecialchars(string,flags,character-set,double_encode)

参数描述
string必需。规定要转换的字符串。
flags可选。规定如何处理引号、无效的编码以及使用哪种文档类型。可用的引号类型:<br/>ENT_COMPAT - 默认。仅编码双引号。<br/>ENT_QUOTES - 编码双引号和单引号。<br/>ENT_NOQUOTES - 不编码任何引号。<br/>无效的编码:ENT_IGNORE - 忽略无效的编码,而不是让函数返回一个空的字符串。应尽量避免,因为这可能对安全性有影响。<br/>ENT_SUBSTITUTE - 把无效的编码替代成一个指定的带有 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD; 的字符,而不是返回一个空的字符串。<br/>ENT_DISALLOWED - 把指定文档类型中的无效代码点替代成 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD;。规定使用的文档类型的附加<br/> flags:<br/>ENT_HTML401 - 默认。作为 HTML 4.01 处理代码。<br/>ENT_HTML5 - 作为 HTML 5 处理代码。ENT_XML1 - 作为 XML 1 处理代码。<br/>ENT_XHTML - 作为 XHTML 处理代码。
character-set可选。一个规定了要使用的字符集的字符串。允许的值:UTF-8 - 默认。ASCII 兼容多字节的 8 位 UnicodeISO-8859-1 - 西欧ISO-8859-15 - 西欧(加入欧元符号 + ISO-8859-1 中丢失的法语和芬兰语字母)cp866 - DOS 专用 Cyrillic 字符集cp1251 - Windows 专用 Cyrillic 字符集cp1252 - Windows 专用西欧字符集KOI8-R - 俄语BIG5 - 繁体中文,主要在台湾使用GB2312 - 简体中文,国家标准字符集BIG5-HKSCS - 带香港扩展的 Big5Shift_JIS - 日语EUC-JP - 日语MacRoman - Mac 操作系统使用的字符集注释:在 PHP 5.4 之前的版本,无法被识别的字符集将被忽略并由 ISO-8859-1 替代。自 PHP 5.4 起,无法被识别的字符集将被忽略并由 UTF-8 替代。
double_encode可选。一个规定了是否编码已存在的 HTML 实体的布尔值。TRUE - 默认。将对每个实体进行转换。FALSE - 不会对已存在的 HTML 实体进行编码。

技术细节

返回值:返回已转换的字符串。 如果 string 包含无效的编码,则返回一个空的字符串,除非设置了 ENT_IGNORE 或者 ENT_SUBSTITUTE 标志。
PHP 版本:4+
更新日志:在 PHP 5 中,character-set 参数的默认值改为 UTF-8。 在 PHP 5.4 中,新增了:ENT_SUBSTITUTE、ENT_DISALLOWED、ENT_HTML401、ENT_HTML5、ENT_XML1 和 ENT_XHTML。 在 PHP 5.3 中,新增了 ENT_IGNORE。 在 PHP 5.2.3 中,新增了 double_encode 参数。 在 PHP 4.1 中,新增了 character-set 参数。
加密
crypt

定义和用法

crypt() 函数返回使用 DES、Blowfish 或 MD5 算法加密的字符串。

在不同的操作系统上,该函数的行为不同,某些操作系统支持一种以上的算法类型。在安装时,PHP 会检查什么算法可用以及使用什么算法。

确切的算法依赖于 salt 参数的格式和长度。salt 可以通过增加由一个特定字符串与一个特定的加密方法生成的字符串的数量来使得加密更安全。

这里有一些和 crypt() 函数一起使用的常量。这些常量值是在安装时由 PHP 设置的。

常量:

  • [CRYPT_SALT_LENGTH] - 默认的加密长度。使用标准的 DES 加密,长度为 2
  • [CRYPT_STD_DES] - 标准的基于 DES 加密有 2 个字符的 salt,来自字母表 "./0-9A-Za-z"。在 salt 中使用无效的字符将引发函数失败。
  • [CRYPT_EXT_DES] - 扩展的基于 DES 加密有 9 个字符的 salt,由 1 个下划线,后边跟 4 个字节的迭代次数和 4 个字节的 salt 组成。这些被编码为可打印字符,每个字符 6 位,最低有效字符优先。值 0 到 63 被编码为 "./0-9A-Za-z"。在 salt 中使用无效的字符将引发函数失败。
  • [CRYPT_MD5] - MD5 加密有 12 个字符的 salt,以 $1$ 开始。
  • [CRYPT_BLOWFISH] - Blowfish 加密有一个以 $2a$、$2x$ 或 $2y$ 开始的 salt,一个两位数的 cost 参数 "$",以及来自字母表 "./0-9A-Za-z" 中的 22 个字符。使用字母表以外的字符将引发函数返回一个长度为 0 的字符串。"$" 参数是以 2 为底的基于 Blowfish 散列算法的迭代次数的对数,必须在 04-31 范围内。在该范围以外的值将引发函数失败。
  • [CRYPT_SHA_256] - SHA-256 加密有 16 个字符的 salt,以 $5$ 开始。如果 salt 字符串以 "rounds=<N>$" 开始,N 的数字值用于表示散列循环被执行的次数,这与 Blowfish 中的 cost 参数类似。默认的循环次数是 5000,最小值是 1000,最大值是 999,999,999。任何超出这个范围的 N 的值将会转换成最接近的边界值。
  • [CRYPT_SHA_512] - SHA-512 加密有 16 个字符的 salt,以 $6$ 开始。 如果 salt 字符串以 "rounds=<N>$" 开始,N 的数字值用于表示散列循环被执行的次数,这与 Blowfish 中的 cost 参数类似。默认的循环次数是 5000,最小值是 1000,最大值是 999,999,999。任何超出这个范围的 N 的值将会转换成最接近的边界值。

在该函数支持多种算法的系统上,上面的常量如果支持则设置为 "1",否则设置为 "0"。

注释:没有相应的解密函数。crypt() 函数使用一种单向算法。


语法

crypt(str,salt)

参数描述
str必需。规定要编码的字符串。
salt可选。用于增加被编码字符数目的字符串,以使编码更加安全。如果未提供 salt 参数,则每次调用该函数时会随机生成一个。

技术细节

返回值:返回加密字符串,如果失败则返回一个小于 13 个字符并保证不同于 salt 的字符串。
PHP 版本:4+
更新日志:在 PHP 5.3.7 中,新增了 $2x$ 和 $2y$ Blowfish 模式,用来处理潜在的高位攻击。 在 PHP 5.3.2 中,新增了常量 SHA-256 和 SHA-512。 自 PHP 5.3.2 起,Blowfish 在无效的循环将返回 "failure" 字符串("0" 或 "1"),而不是后退到 DES。 自 PHP 5.3.0 起,PHP 自带 MD5 加密实现、标准 DES 实现、扩展 DES 实现以及 Blowfish 算法。如果系统不支持上述的算法,将使用 PHP 自带的算法实现。

demo

echo crypt('password','salt');
##输出
sa3tHJ3/KuYvI





md5

定义和用法

md5() 函数计算字符串的 MD5 散列。

md5() 函数使用 RSA 数据安全,包括 MD5 报文摘要算法。

在 PHP 5.0 中,raw 参数变成可选的。

来自 RFC 1321 的解释 - MD5 报文摘要算法:MD5 报文摘要算法将任意长度的信息作为输入值,并将其换算成一个 128 位长度的"指纹信息"或"报文摘要"值来代表这个输入值,并以换算后的值作为结果。MD5 算法主要是为数字签名应用程序而设计的;在这个数字签名应用程序中,较大的文件将在加密(这里的加密过程是通过在一个密码系统下[如:RSA]的公开密钥下设置私有密钥而完成的)之前以一种安全的方式进行压缩。

如需计算文件的 MD5 散列,请使用 md5_file() 函数。


语法

md5(string,raw)

参数描述
string必需。规定要计算的字符串。
raw可选。规定十六进制或二进制输出格式:<br/>TRUE - 原始 16 字符二进制格式<br/>FALSE - 默认。32 字符十六进制数

技术细节

返回值:如果成功则返回已计算的 MD5 散列,如果失败则返回 FALSE。
PHP 版本:4+
更新日志:在 PHP 5.0 中,raw 参数变成可选的。
md5_file

定义和用法

md5_file() 函数计算文件的 MD5 散列。

md5_file() 函数使用 RSA 数据安全,包括 MD5 报文摘要算法。

在 PHP 5.0 中,raw 参数变成可选的

来自 RFC 1321 的解释 - MD5 报文摘要算法:MD5 报文摘要算法将任意长度的信息作为输入值,并将其换算成一个 128 位长度的"指纹信息"或"报文摘要"值来代表这个输入值,并以换算后的值作为结果。MD5 算法主要是为数字签名应用程序而设计的;在这个数字签名应用程序中,较大的文件将在加密(这里的加密过程是通过在一个密码系统下[如:RSA]的公开密钥下设置私有密钥而完成的)之前以一种安全的方式进行压缩。

如需计算字符串的 MD5 散列,请使用 md5() 函数。


语法

md5_file(file,raw)

参数描述
file必需。规定要计算的文件。
raw可选。一个规定十六进制或二进制输出格式的布尔值:TRUE - 原始 16 字符二进制格式FALSE - 默认。32 字符十六进制数

技术细节

返回值:如果成功则返回已计算的 MD5 散列,如果失败则返回 FALSE。
PHP 版本:4.2.0+
更新日志:在 PHP 5.0 中,raw 参数变成可选的。 自 PHP 5.1 起,可以通过封装使用 md5_file()。例如: md5_file("https://jerrryblog.cn..")
sha1

定义和用法

sha1() 函数计算字符串的 SHA-1 散列。

sha1() 函数使用美国 Secure Hash 算法 1。

PHP 5.0 中,raw 参数变成可选的

来自 RFC 3174 的解释 - 美国 Secure Hash 算法 1:SHA-1 产生一个名为报文摘要的 160 位的输出。报文摘要可以被输入到一个可生成或验证报文签名的签名算法。对报文摘要进行签名,而不是对报文进行签名,这样可以提高进程效率,因为报文摘要的大小通常比报文要小很多。数字签名的验证者必须像数字签名的创建者一样,使用相同的散列算法。

提示:如需计算文件的 SHA-1 散列,请使用 sha1_file 函数。


语法

sha1(string,raw)

参数描述
string必需。规定要计算的字符串。
raw可选。规定十六进制或二进制输出格式:TRUE - 原始 20 字符二进制格式FALSE - 默认。40 字符十六进制数

技术细节

返回值:如果成功则返回已计算的 SHA-1 散列,如果失败则返回 FALSE。
PHP 版本:4.3.0+
更新日志:在 PHP 5.0 中,raw 参数变成可选的。
sha1_file
比对
===strcasecmp
===strnatcasecmp
===strnatcmp
===strncasecmp
===strncmp
===substr_compare()
字符截取/分割/打散
chunk_split

定义和用法

chunk_split() 函数把字符串分割为一连串更小的部分。

注释:该函数不改变原始字符串。


语法

chunk_split(string,length,end)

参数描述
string必需。规定要分割的字符串。
length可选。一个数字,定义字符串块的长度。默认为 76。
end可选。一个字符串,定义在每个字符串块之后放置的内容。默认为 \r\n。

技术细节

返回值:返回已分割的字符串。
PHP 版本:4+

demo

echo chunk_split('这是一个测试标题',2,'|');
echo "<br/>";
echo chunk_split('this is test',2,'|');

##输出
##中文处理时要注意,这个是中文字节的问题
�|��|��|�|��|��|�|��|��|�|��|��|
th|is| i|s |te|st|
strtok

定义和用法

strtok() 函数把字符串分割为更小的字符串(标记)。


语法

strtok(string,split)

参数描述
string必需。规定要分割的字符串。
split必需。规定一个或多个分割字符。

技术细节

返回值:返回字符串标记。
PHP 版本:4+

demo

$string = "Hello world. Beautiful day today.";
$token = strtok($string, " ");

while ($token != false)
{
    echo "$token<br>";
    $token = strtok(" ");
} 

##输出
Hello
world.
Beautiful
day
today.
substr()

定义和用法

substr() 函数返回字符串的一部分。

注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

在 PHP 5.2.2 到 5.2.6 版本中,如果 start 参数表示负截断或者越界位置,则返回 FALSE

语法

substr(string,start,length)

参数描述
string必需。规定要返回其中一部分的字符串。
start必需。规定在字符串的何处开始。正数 - 在字符串的指定位置开始负数 - 在从字符串结尾的指定位置开始0 - 在字符串中的第一个字符处开始
length可选。规定要返回的字符串长度。默认是直到字符串的结尾。正数 - 从 start 参数所在的位置返回负数 - 从字符串末端返回

技术细节

返回值:返回字符串的提取部分,如果失败则返回 FALSE,或者返回一个空字符串。
PHP 版本:4+
更新日志:在 PHP 5.2.2 到 5.2.6 版本中,如果 start 参数表示负截断或者越界位置,则返回 FALSE。其他版本则从 start 位置开始获取字符串。

demo

$phone = '13838384380';
echo substr($phone, 0,3).'****'.substr($phone, -3,3);
##输出
138****380
explode

定义和用法

explode() 函数把字符串打散为数组。

注释:"separator" 参数不能是一个空字符串。

注释:该函数是二进制安全的。

相关函数:implode用自定义连接符把数组组成字符串


语法

explode(separator,string,limit)

参数描述
separator必需。规定在哪里分割字符串。
string必需。要分割的字符串。
limit可选。规定所返回的数组元素的数目。可能的值:大于 0 - 返回包含最多 limit 个元素的数组小于 0 - 返回包含除了最后的 -limit 个元素以外的所有元素的数组0 - 返回包含一个元素的数组

技术细节

返回值:返回字符串数组。
PHP 版本:4+
更新日志:在 PHP 4.0.1 中,新增了 limit 参数。在 PHP 5.1.0 中,新增了对负数 limits 的支持。

demo

 show(explode(',', 'this,is,test'));

##输出
Array
(
    [0] => this
    [1] => is
    [2] => test
)
str_split

定义和用法

str_split() 函数把字符串分割到数组中。

语法

str_split(string,length)
参数描述
string必需。规定要分割的字符串。
length可选。规定每个数组元素的长度。默认是 1。

技术细节

返回值:如果 length 小于 1,则 str_split() 函数将返回 FALSE。如果 length 大于字符串的长度,则整个字符串将作为数组的唯一元素返回。
PHP 版本:5+

demo

show(str_split('Jerry'));
show(str_split('Jerry',2));
##输出
Array
(
    [0] => J
    [1] => e
    [2] => r
    [3] => r
    [4] => y
)
Array
(
    [0] => Je
    [1] => rr
    [2] => y
)
搜索
strpos/stripos/strripos/strrpos

定义和用法

  • stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
  • strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写)
  • strripos()- 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
  • strrpos - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)

语法

stripos(string,find,start)
参数描述
string必需。规定要搜索的字符串。
find必需。规定要查找的字符。
start可选。规定开始搜索的位置。

技术细节

返回值:返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。注释:字符串位置从 0 开始,不是从 1 开始。
PHP 版本:5+

demo

$str = 'i am lern php ,我爱php';
show(stripos($str, 'php'));
show(strpos($str, 'php'));
show(strripos($str, 'php'));
show(strrpos($str, 'php'));

10
10
21
21
stristr/strstr(strchr)

定义和用法

  1. stristr() 函数搜索字符串在另一字符串中的第一次出现 (不区分大小写)。
  2. strstr() 函数搜索字符串在另一字符串中的第一次出现(区分大小写)。
  3. strchr() strstr 的别名
    注释:该函数是二进制安全的。

语法

stristr(string,search,before_search)
参数描述
string必需。规定被搜索的字符串。
search必需。规定要搜索的字符串。如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符。
before_search可选。默认值为 "false" 的布尔值。如果设置为 "true",它将返回 search 参数第一次出现之前的字符串部分。

技术细节

返回值:返回字符串的剩余部分(从匹配点)。如果未找到所搜索的字符串,则返回 FALSE。
PHP 版本:4+
更新日志:在 PHP 5.3 中,新增了 before_search 参数。在 PHP 4.3 中,该函数变成是二进制安全的。

demo

show(strstr('i am lern php ,我爱php',"PHP"));
show(stristr('i am lern php ,我爱php',"PHP"));
##输出
bool(false)
php ,我爱php

##可以判断是否存在字符
if(strstr('i am lern php ,我爱php',"PHP")){
    do sth..;
}
_strpbrk

定义和用法

strpbrk() 函数在字符串中搜索指定字符中的任意一个。

注释:该函数对大小写敏感。

该函数返回指定字符第一次出现的位置开始的剩余部分。如果失败,则返回 FALSE。

语法

strpbrk(string,charlist)
参数描述
string必需。规定要搜索的字符串。
charlist必需。规定要查找的字符。

技术细节

返回值:返回从所查找的字符开始的字符串。如果没有找到,则返回 FALSE。
PHP 版本:5+

demo

show(strpbrk('i am lern php ,我爱php',"PHP"));
show(strpbrk('i am lern php ,我爱php',"php"));
#输出
bool(false)
php ,我爱php

##ex2 ???
show(strpbrk('i am lern php ,我爱php',"learn"));
##输出
am lern php ,我爱php
strrchr 比strpbrk靠谱

定义和用法

strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。

注释:该函数是二进制安全的。

语法

strrchr(string,char)
参数描述
string必需。规定要搜索的字符串。
char必需。规定要查找的字符。如果该参数是数字,则搜索匹配此数字的 ASCII 值的字符。

技术细节

返回值:返回从某个字符串在另一个字符串中最后一次出现的位置到主字符串结尾的所有字符。如果未找到此字符,则返回 FALSE。
PHP 版本:4+
更新日志:在 PHP 4.3 中,该函数成为二进制安全。

demo

show(strrchr('i am lern php ,我爱php',"PHP"));
show(strrchr('i am lern php ,我爱php',"learn"));
##输出
bool(false)
lern php ,我爱php
_strspn/strcspn

定义和用法

strspn() 函数返回在字符串中包含 charlist 参数中指定字符的数目。

strcspn() 函数来返回在找到任何指定的字符之前,在字符串查找的字符数。

注释:该函数是二进制安全的。

语法

strspn(string,charlist,start,length)
参数描述
string必需。规定被搜索的字符串。
charlist必需。规定要查找的字符。
start可选。规定在字符串的何处开始。
length可选。定义字符串的长度。

技术细节

返回值:返回在字符串中包含 charlist 参数中指定字符的数目。
PHP 版本:4+
更新日志:在 PHP 4.3 中,新增了 startlength 参数。

demo

show(strspn('i am lern php ,我爱php',"aphp"));
show(strcspn('i am lern php ,我爱php',"l"));
show(strspn('abcdef',"cba"));
##输出
0
5
3
字符替换
strtr

定义和用法

strtr() 函数转换字符串中特定的字符。

注释:如果 fromto 参数的长度不同,则会被格式化为最短的长度。eg: from:this to:are 会变成 thar
如果是替换用法,建议使用数组方式,数组方式不会出现这样的情况

语法

strtr(string,from,to)

或者:

strtr(string,array)
参数描述
string必需。规定要转换的字符串。
from必需(除非使用数组)。规定要改变的字符。
to必需(除非使用数组)。规定要改变为的字符。
array必需(除非使用 fromto)。数组,其中的键名是更改的原始字符,键值是更改的目标字符。

技术细节

返回值:返回已转换的字符。如果 array 参数包含一个空字符串("")的键名,则将返回 FALSE。
PHP 版本:4+

demo

$str = "this is Jerry & my best frend is tom !";
show(strtr($str, 'is', 'are'));
##输出
this is areey & my brst fernd is tom !

$re = ['is'=>'are'];
show(strtr($str, $re));

##输出
thare are Jerry & my best frend are tom !
substr_replace

定义和用法

substr_replace() 函数把字符串的一部分替换为另一个字符串。

注释:如果 start 参数是负数且 length 小于或者等于 start,则 length 为 0。

注释:该函数是二进制安全的。

语法

substr_replace(string,replacement,start,length)
参数描述
string必需。规定要检查的字符串。
replacement必需。规定要插入的字符串。
start必需。规定在字符串的何处开始替换。正数 - 在字符串中的指定位置开始替换负数 - 在从字符串结尾的指定位置开始替换0 - 在字符串中的第一个字符处开始替换
length可选。规定要替换多少个字符。默认是与字符串长度相同。正数 - 被替换的字符串长度负数 - 表示待替换的子字符串结尾处距离 string 末端的字符个数。0 - 插入而非替换

技术细节

返回值:返回被替换的字符串。如果 string 是数组,则返回数组。
PHP 版本:4+
更新日志:自 PHP 4.3.3 起,所有参数都接受数组。

demo

$str1 = 'hello this is Jerry';
$str2 = '你好,这里是杰瑞';
show(substr_replace($str1, 'tom', 6));
show(substr_replace($str2, 'tom', 6));


hello tom
你好tom
str_replace

定义和用法

str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。

该函数必须遵循下列规则:

  • 如果搜索的字符串是数组,那么它将返回数组。
  • 如果搜索的字符串是数组,那么它将对数组中的每个元素进行查找和替换。
  • 如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换
  • 如果查找的是数组,而替换的是字符串,那么替代字符串将对所有查找到的值起作用。

注释:该函数区分大小写。请使用 str_ireplace() 函数执行不区分大小写的搜索。

注释:该函数是二进制安全的。

语法

str_replace(find,replace,string,count)
参数描述
find必需。规定要查找的值。
replace必需。规定替换 find 中的值的值。
string必需。规定被搜索的字符串。
count可选。对替换数进行计数的变量。

技术细节

返回值:返回带有替换值的字符串或数组。
PHP 版本:4+
更新日志:在 PHP 5.0 中,新增了 count 参数。在 PHP 4.3.3 之前,该函数的 findreplace 参数都为数组时将会遇到麻烦,会引起空的 find 索引在内部指针没有更换到 replace 数组上时被忽略。新的版本不会有这个问题。自 PHP 4.0.5 起,大多数参数可以是一个数组。

demo

show(str_replace('Jerry', 'Tom', $str1));
show(str_replace('杰瑞', 'Tom', $str1));

##输出
hello this is Tom
hello this is Jerry
str_ireplace

定义和用法

str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。

该函数必须遵循下列规则:

  • 如果搜索的字符串是一个数组,那么它将返回一个数组。
  • 如果搜索的字符串是一个数组,那么它将对数组中的每个元素进行查找和替换。
  • 如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换
  • 如果是对一个数组进行查找,但只对一个字符串进行替换,那么替代字符串将对所有查找到的值起作用。

注释:该函数不区分大小写。请使用str_replace 函数来执行区分大小写的搜索。

注释:该函数是二进制安全的。

语法

str_ireplace(find,replace,string,count)
参数描述
find必需。规定要查找的值。
replace必需。规定替换 find 中的值的值。
string必需。规定被搜索的字符串。
count可选。一个变量,对替换数进行计数。

技术细节

返回值:返回带有替换值的字符串或数组。
PHP 版本:5+
更新日志:在 PHP 5.0 中,新增了 count 参数。

demo

show(str_ireplace('jerry', 'Tom', $str1));

hello this is Tom
bin2hex

定义和用法

bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。字符串可通过使用 pack() 函数再转换回去。


语法

bin2hex(string)

参数描述
string必需。规定要转换的字符串。

技术细节

返回值:返回要转换字符串的十六进制值。
PHP 版本:4+

DEMO

echo bin2hex('my name is Jerry');
##输出 
6d79206e616d65206973204a65727279

  #把16进制数转回去
     echo pack('H*','6d79206e616d65206973204a65727279');
    ##输出 my name is Jerry
    
    ## echo hex2bin('6d79206e616d65206973204a65727279');
    
hex2bin

定义和用法

hex2bin() 函数把十六进制值的字符串转换为 ASCII 字符。


语法

hex2bin(string)

参数描述
string必需。要转换的十六进制值。

技术细节

返回值:返回转换字符串的 ASCII 字符,如果失败则返回 FALSE。
PHP 版本:5.4.0+
更新日志:自 PHP 5.4.1 起,如果字符串长度为奇数,则抛出一个警告。在 PHP 5.4.0 中,奇数字符串被默默接受,但是最后一个字节会被移除。 自 PHP 5.5.1 起,如果字符串是无效的十六进制字符串,则抛出一个警告。

demo

## echo hex2bin('6d79206e616d65206973204a65727279');
##输出 my name is Jerry

pack

定义和用法

pack() 函数把数据装入一个二进制字符串。

语法

pack(format,args+)
参数描述
format必需。规定在包装数据时所使用的格式。
args+可选。规定被包装的一个或多个参数。

format 参数的可能值:

  • a - NUL-padded string
  • A - SPACE-padded string
  • h - Hex string, low nibble first
  • H - Hex string, high nibble first
  • c - signed char
  • C - unsigned char
  • s - signed short (always 16 bit, machine byte order)
  • S - unsigned short (always 16 bit, machine byte order)
  • n - unsigned short (always 16 bit, big endian byte order)
  • v - unsigned short (always 16 bit, little endian byte order)
  • i - signed integer (machine dependent size and byte order)
  • I - unsigned integer (machine dependent size and byte order)
  • l - signed long (always 32 bit, machine byte order)
  • L - unsigned long (always 32 bit, machine byte order)
  • N - unsigned long (always 32 bit, big endian byte order)
  • V - unsigned long (always 32 bit, little endian byte order)
  • f - float (machine dependent size and representation)
  • d - double (machine dependent size and representation)
  • x - NUL byte
  • X - Back up one byte
  • @ - NUL-fill to absolute position

DEMO

    #把16进制数转回去
     echo pack('H*','6d79206e616d65206973204a65727279');
    ##输出 my name is Jerry

##转成16进制
 echo bin2hex('my name is Jerry');
    ##输出 
    6d79206e616d65206973204a65727279
chr

定义和用法

chr() 函数从指定 ASCII 值返回字符。

ASCII 值可被指定为十进制值、八进制值或十六进制值。八进制值被定义为带前置 0,十六进制值被定义为带前置 0x。


语法

chr(ascii)

参数描述
ascii必需。ASCII 值。

技术细节

返回值:返回指定的字符。
PHP 版本:4+

demo

echo chr(52) . "<br>"; // Decimal value
echo chr(052) . "<br>"; // Octal value
echo chr(0x52) . "<br>"; // Hex value


4
*
R
chop

定义和用法

chop() 函数移除字符串右侧的空白字符或其他预定义字符。


语法

chop(string,charlist)

参数描述
string必需。规定要检查的字符串。
charlist可选。规定从字符串中删除哪些字符。 如果 charlist 参数为空,则移除下列字符:"\0" - NULL"\t" - 制表符"\n" - 换行"\x0B" - 垂直制表符"\r" - 回车" " - 空格

技术细节

返回值:返回已修改的字符串。
PHP 版本:4+
更新日志:在 PHP 4.1.0 中,新增了 charlist 参数。
待验证count_chars

定义和用法

count_chars() 函数返回字符串所用字符的信息(例如,ASCII 字符在字符串中出现的次数,或者某个字符是否已经在字符串中使用过)。


语法

count_chars(string,mode)

参数描述
string必需。规定要检查的字符串。
mode可选。规定返回模式。默认是 0。有以下不同的返回模式:0 - 数组,ASCII 值为键名,出现的次数为键值1 - 数组,ASCII 值为键名,出现的次数为键值,只列出出现次数大于 0 的值2 - 数组,ASCII 值为键名,出现的次数为键值,只列出出现次数等于 0 的值3 - 字符串,带有所有使用过的不同的字符4 - 字符串,带有所有未使用过的不同的字符

技术细节

返回值:取决于指定的 mode 参数。
PHP 版本:4+
待补get_html_translation_table
待补html_entity_decode
implode/join

定义和用法

implode() 函数返回由数组元素组合成的字符串。

注释:implode() 函数接受两种参数顺序。但是由于历史原因,explode() 是不行的,您必须保证 separator 参数在 string 参数之前才行。

注释:implode() 函数的 separator 参数是可选的。但是为了向后兼容,推荐您使用使用两个参数。

注释:该函数是二进制安全的。

语法

implode(separator,array)
参数描述
separator可选。规定数组元素之间放置的内容。默认是 ""(空字符串)。
array必需。要组合为字符串的数组。

技术细节

返回值:返回由数组元素组合成的字符串。
PHP 版本:4+
更新日志:在 PHP 4.3.0 中,separator 参数变成可选的。

demo

$arr = [1,2,3,4,5,6];
show(implode("-", $arr));

##输出

lcfirst/ucfirst/ucwords/strtolower/strtoupper

定义和用法

  • strtolower()- 把字符串转换为小写
  • strtoupper()- 把字符串转换为大写
  • ucfirst()- 把字符串中的首字符转换为大写
  • ucwords()- 把字符串中每个单词的首字符转换为大写

语法

lcfirst(string)
参数描述
string必需。规定要转换的字符串。

技术细节

返回值:返回已转换的字符串。
PHP 版本:5.3.0+

demo

$str = "this is jerry";
show(strtolower($str));
show(strtoupper($str));
show(ucfirst($str));
show(ucwords($str));
##输出
this is jerry
THIS IS JERRY
This is jerry
This Is Jerry
ltrim/rtrim/trim
_money_format

定义和用法

money_format() 函数返回被格式化为货币字符串的字符串。

该函数在主字符串中的百分号(%)位置插入一个格式化的数字。

注释:money_format() 函数无法在 Windows 平台上工作。

提示:该函数常与setlocale() 函数一起使用。

提示:如需查看所有可用的语言代码,请访问我们的语言代码参考手册

语法

money_format(string,number)
参数描述
string必需。规定要格式化的字符串及如何格式化其中的变量。可能的格式值:填充和标志:<br/>=f - 规定字符(f)用作填充(例如:%=t 使用 "t" 作为填充)。<br/>默认使用空格作为填充。<br/>^ - 移除分组字符的使用。+ 或 ( - 规定如何显示正数和负数。如果使用 "+",则使用本地设置的 + 和 -(通常在负数前加符号,赠书前不加任何符号)。<br/>如果使用 "(",负数被包含在括号内部。默认是使用 "+"。! - 停止在输出字符串中使用货币符号。<br/>-如果使用 "-",所有字段左对齐。<br/>默认是右对齐。<br/>字段宽度:x - 规定字段的最小宽度(x)。默认是 0。<br/>#x - 规定小数点左边数字的最大位数(x)。<br/>用于保持格式化输出在同一列对齐。如果数字位数大于 x,本规定将被忽略。.x - 规定小数点右边数字的最大位数(x)。<br/>如果 x 是 0,小数点及其右边的数字将不会显示。<br/>默认使用本地设置。<br/>转换字符:i - 数字被格式化为国际货币格式。<br/>n - 数字被格式化为国家货币格式。<br/>% - 返回 % 字符。<br/>注释:如果使用多个格式值,则它们必须以上面的顺序出现。注释:该函数受本地设置的影响。
number必需。被插入到格式化字符串中 % 符号位置的数字。

技术细节

返回值:返回已格式化的字符串。格式化字符串前后的字符将保持不变返回。非数值数字会返回 NULL 并产生 E_WARNING。
PHP 版本:4.3.0+

demo

$number = 9999999999999;
setlocale(LC_MONETARY,"de_ZH");
echo money_format("%.2n", $number);
##输出
9999999999999.00
number_format

定义和用法

number_format() 函数通过千位分组来格式化数字。

注释:该函数支持一个、两个或四个参数(不是三个)。

语法

number_format(number,decimals,decimalpoint,separator)
参数描述
number必需。要格式化的数字。如果未设置其他参数,则数字会被格式化为不带小数点且以逗号(,)作为千位分隔符。
decimals可选。规定多少个小数。如果设置了该参数,则使用点号(.)作为小数点来格式化数字。
decimalpoint可选。规定用作小数点的字符串。
separator可选。规定用作千位分隔符的字符串。仅使用该参数的第一个字符。比如 "xxx" 仅输出 "x"。注释:如果设置了该参数,那么所有其他参数都是必需的。

技术细节

返回值:返回已格式化的数字。
PHP 版本:4+
更新日志:自 PHP 5.4 起,该函数在参数 decimalpointseparator 中支持多字节。在更老的版本中,只使用每个分隔符的第一个字节。

demo

 echo number_format($number,2);
 ##输出
 
sscanf

定义和用法

sscanf() 函数根据指定的格式解析来自字符串的输入。 sscanf() 函数基于格式字符串向变量中解析字符串。

如果只向该函数传递两个参数,数据将以数组的形式返回。否则,如果传递了额外的参数,则被解析的数据会存储在这些参数中。如果区分符的数目大于包含它们的变量的数目,则会发生错误。不过,如果区分符的数目小于包含它们的变量的数目,则额外的变量包含 NULL。

相关函数:

  • printf() - 输出已格式化字符串
  • sprintf() - 写入一个已格式化字符串到变量中

语法

sscanf(string,format,arg1,arg2,arg++)
参数描述
string必需。规定要读取的字符串。
format必需。规定要使用的格式。可能的格式值:<br/>%% - 返回一个百分号 <br/>%%c - ASCII 值对应的字符%d - 包含正负号的十进制数(负数、0、正数)<br/>%e - 使用小写的科学计数法(例如 1.2e+2)<br/>%u - 不包含正负号的十进制数(大于等于 0)<br/>%f - 浮点数<br/>%o - 八进制数<br/>%s - 字符串%x - 十六进制数(小写字母)<br/>%X - 十六进制数(大写字母)<br/>附加的格式值。必需放置在 % 和字母之间(例如 %.2f)<br/>:+ (在数字前面加上 + 或 - 来定义数字的正负性。默认地,只有负数做标记,正数不做标记)<br/>' (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。)<br/>- (左调整变量值)[0-9] (规定变量值的最小宽度)<br/>.[0-9] (规定小数位数或最大字符串长度)<br/>注释:如果使用多个上述的格式值,它们必须按照上面的顺序使用。
arg1可选。存储数据的第一个变量。
arg2可选。存储数据的第二个变量。
arg++可选。存储数据的第三、四个变量,依此类推。

技术细节

返回值:如果只向该函数传递两个参数,数据将以数组的形式返回。否则,如果传递了额外的参数,那么被解析的数据会存储在这些参数中。如果区分符的数目大于包含它们的变量的数目,则会发生错误。不过,如果区分符的数目小于包含它们的变量的数目,则额外的变量包含 NULL。
PHP 版本:4.0.1+

demo

#ex1
$str = "age:30 weight:60kg";
sscanf($str,"age:%d weight:%dkg",$age,$weight);
var_dump($age,$weight);
##输出
int(30) int(60)
#ex2
$str = "If you divide 4 by 2 you'll get 2";
$format = sscanf($str,"%s %s %s %d %s %d %s %s %c");
show($format);
##输出
Array
(
    [0] => If
    [1] => you
    [2] => divide
    [3] => 4
    [4] => by
    [5] => 2
    [6] => you'll
    [7] => get
    [8] => 2
)
str_getcsv

定义和用法

str_getcsv() 函数解析 CSV 格式字段的字符串,并返回包含所读取字段的数组。

语法

str_getcsv(string,separator,enclosure,escape)
参数描述
string必需。规定要解析的字符串。
separator可选。字符,规定字段分隔符(只允许一个字符)。默认值为逗号( , )。
enclosure可选。字符,规定字段包裹字符。默认值为双引号( " )。
escape可选。字符,规定转义字符。默认为反斜线(\)。

技术细节

返回值:以数组形式返回 CSV 字段。
PHP 版本:5.3.0+
str_pad

定义和用法

str_pad() 函数把字符串填充为新的长度。

语法

str_pad(string,length,pad_string,pad_type)
参数描述
string必需。规定要填充的字符串。
length必需。规定新的字符串长度。如果该值小于字符串的原始长度,则不进行任何操作。
pad_string可选。规定供填充使用的字符串。默认是空白。
pad_type可选。规定填充字符串的哪边。可能的值:<br/>STR_PAD_BOTH - 填充字符串的两侧。如果不是偶数,则右侧获得额外的填充。<br/>STR_PAD_LEFT - 填充字符串的左侧。<br/>STR_PAD_RIGHT - 填充字符串的右侧。默认。

技术细节

返回值:返回被填充的字符串。
PHP 版本:4.0.1+

demo

$str = 'test';
show(str_pad($str, 15,'0'));
show(str_pad($str, 15,'0',STR_PAD_BOTH));
show(str_pad($str, 15,'0',STR_PAD_LEFT));
##输出
test00000000000
00000test000000
00000000000test
str_repeat

定义和用法

str_repeat() 函数把字符串重复指定的次数。

语法

str_repeat(string,repeat)
参数描述
string必需。规定要重复的字符串。
repeat必需。规定字符串将被重复的次数。必须大于等于 0。

技术细节

返回值:返回被重复的字符串。
PHP 版本:4+

demo

show(str_repeat('Jerry', 5));
str_rot13

定义和用法

str_rot13() 函数对字符串执行 ROT13 编码。

ROT13 编码把每一个字母在字母表中向前移动 13 个字母。数字和非字母字符保持不变。

提示:编码和解码都是由相同的函数完成的。如果您把已编码的字符串作为参数,那么将返回原始字符串。

语法

str_rot13(string)
参数描述
string必需。规定要编码的字符串。

技术细节

返回值:返回编码字符串的 ROT13 版本。
PHP 版本:4.2.0+
更新日志:在 PHP 4.3 之前,string 也能被修改,就像是通过引用传递一样。

demo

show(str_rot13('Jerry'));
show(str_rot13(str_rot13('Jerry')));
##输出
Wreel
Jerry
str_shuffle

定义和用法

str_shuffle() 函数随机打乱字符串中的所有字符。

语法

str_shuffle(string)
参数描述
string必需。规定要打乱的字符串。

技术细节

返回值:返回已打乱的字符串。
PHP 版本:4.3.0+

demo

show(str_shuffle('Jerry'));
##输出
erJyr
str_word_count

定义和用法

str_word_count() 函数计算字符串中的单词数。

语法

str_word_count(string,return,char)
参数描述
string必需。规定要检查的字符串。
return可选。规定 str_word_count() 函数的返回值。<br/>可能的值:<br/>0 - 默认。返回找到的单词的数目。<br/>1 - 返回包含字符串中的单词的数组。<br/>2 - 返回一个数组,其中的键名是单词在字符串中的位置,键值是实际的单词。
char可选。规定被视为单词的特殊字符。

技术细节

返回值:返回数字或者数组,取决于所选择的 return 参数。
PHP 版本:4.3.0+
更新日志:在 PHP 5.1 中,新增了 char 参数。

demo

$str = "this is Jerry & my best frend is tom !";
show(str_word_count($str));
show(str_word_count($str,1));
show(str_word_count($str,2));
show(str_word_count($str,2,'&'));

##输出
8
Array
(
    [0] => this
    [1] => is
    [2] => Jerry
    [3] => my
    [4] => best
    [5] => frend
    [6] => is
    [7] => tom
)
Array
(
    [0] => this
    [5] => is
    [8] => Jerry
    [16] => my
    [19] => best
    [24] => frend
    [30] => is
    [33] => tom
)
Array
(
    [0] => this
    [5] => is
    [8] => Jerry
    [14] => &
    [16] => my
    [19] => best
    [24] => frend
    [30] => is
    [33] => tom
)
===strcmp
===strcspn
strip_tags

定义和用法

strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。

注释:该函数始终会剥离 HTML 注释。这点无法通过 allow 参数改变。

注释:该函数是二进制安全的。

语法

strip_tags(string,allow)
参数描述
string必需。规定要检查的字符串。
allow可选。规定允许的标签。这些标签不会被删除。

技术细节

返回值:返回被剥离的字符串。
PHP 版本:4+
更新日志:自 PHP 5.0 起,该函数是二进制安全的。自 PHP 4.3 起,该函数始终会剥离 HTML 注释。

demo

echo strip_tags("Hello <b>world!</b>");
##输出
Hello world!

strlen/mb_strlen

定义和用法

strlen() 函数返回字符串的长度。

语法

strlen(string)
参数描述
string必需。规定要检查的字符串。

技术细节

返回值:若成功则返回字符串的长度,若字符串为空则返回 0。
PHP 版本:4+
更新日志:在 PHP 5.3.0 之前,该函数把数组当做字符串 Array,这样就返回一个长度为 5 的字符串,并产生一个 E_NOTICE 级别的错误。

demo

$str = 'this is test';
$str1 = '这是一个测试';
show(strlen($str));
show(mb_strlen($str1));
##输出
12
6
strrev

定义和用法

strrev() 函数反转字符串。

语法

strrev(string)
参数描述
string必需。规定要反转的字符串。

技术细节

返回值:返回已反转的字符串。
PHP 版本:4+

demo

 $str1 = 'this is test';
show(strrev($str1));
##输出
tset si siht
substr_count

substr_count() 函数计算子串在字符串中出现的次数。

注释:子串是区分大小写的。

注释:该函数不计数重叠的子串(参见例子 2)。

注释:如果 start 参数加上 length 参数大于字符串长度,则该函数生成一个警告(参见例子 3)。

语法

substr_count(string,substring,start,length)
参数描述
string必需。规定被检查的字符串。
substring必需。规定要搜索的字符串。
start可选。规定在字符串中何处开始搜索。
length可选。规定搜索的长度。

技术细节

返回值:返回子串在字符串中出现的次数。
PHP 版本:4+
更新日志:在 PHP 5.1 中,新增了 startlength 参数。

demo

$str = "This is nice";
echo strlen($str)."<br>"; // 使用 strlen() 来返回字符串长度
echo substr_count($str,"is")."<br>"; // 字符串中 "is" 出现的次数
echo substr_count($str,"is",2)."<br>"; // 字符串缩减为 "is is nice"
echo substr_count($str,"is",3)."<br>"; // 字符串缩减为 "s is nice"
echo substr_count($str,"is",3,3)."<br>"; // 字符串缩减为 "s i"
##输出
12
2
2
1
0
_wordwrap

定义和用法

wordwrap() 函数按照指定长度对字符串进行折行处理。

注释:该函数可能会在行的开头留下空白字符。

语法

wordwrap(string,width,break,cut)
参数描述
string必需。规定要进行折行的字符串。
width可选。规定最大行宽度。默认是 75。
break可选。规定作为分隔符使用的字符(字串断开字符)。默认是 "\n"。
cut可选。规定是否对大于指定宽度的单词进行折行:FALSE - 默认。No-wrapTRUE - 折行

技术细节

返回值:若成功,则返回折行后的字符串。若失败,则返回 FALSE。
PHP 版本:4.0.2+
更新日志:在 PHP 4.0.3 中,新增了 cut 参数。
Calendar 日历

[TOC]

为了让这些函数能够工作,您必须通过 --enable-calendar 编译 PHP。

函数

   函数    描述
cal_days_in_month()    针对指定的年份和历法,返回一个月中的天数。
cal_from_jd()    把儒略日计数转换为指定历法的日期。
cal_info()    返回有关指定历法的信息。
cal_to_jd()    把指定历法的日期转换为儒略日计数。
easter_date()    返回指定年份的复活节午夜的 Unix 时间戳。
easter_days()    返回指定年份的复活节与 3 月 21 日之间的天数。
frenchtojd()    把法国共和历法的日期转换成为儒略日计数。
gregoriantojd()    把格利高里历法的日期转换成为儒略日计数。
jddayofweek()    返回日期在周几。
jdmonthname()    返回月的名称。
jdtofrench()    把儒略日计数转换为法国共和历法的日期。
jdtogregorian()    把儒略日计数转换为格利高里历法的日期。
jdtojewish()    把儒略日计数转换为犹太历法的日期。
jdtojulian()    把儒略日计数转换为儒略历法的日期。
jdtounix()    把儒略日计数转换为 Unix 时间戳。
jewishtojd()    把犹太历法的日期转换为儒略日计数。
juliantojd()    把儒略历法的日期转换为儒略日计数。
unixtojd()    把 Unix 时间戳转换为儒略日计数。

常量

常量    类型    PHP 版本
CAL_GREGORIAN    Integer    PHP 4
CAL_JULIAN    Integer    PHP 4
CAL_JEWISH    Integer    PHP 4
CAL_FRENCH    Integer    PHP 4
CAL_NUM_CALS    Integer    PHP 4
CAL_DOW_DAYNO    Integer    PHP 4
CAL_DOW_SHORT    Integer    PHP 4
CAL_DOW_LONG    Integer    PHP 4
CAL_MONTH_GREGORIAN_SHORT    Integer    PHP 4
CAL_MONTH_GREGORIAN_LONG    Integer    PHP 4
CAL_MONTH_JULIAN_SHORT    Integer    PHP 4
CAL_MONTH_JULIAN_LONG    Integer    PHP 4
CAL_MONTH_JEWISH    Integer    PHP 4
CAL_MONTH_FRENCH    Integer    PHP 4
CAL_EASTER_DEFAULT    Integer    PHP 4.3
CAL_EASTER_ROMAN    Integer    PHP 4.3
CAL_EASTER_ALWAYS_GREGORIAN    Integer    PHP 4.3
CAL_EASTER_ALWAYS_JULIAN    Integer    PHP 4.3
CAL_JEWISH_ADD_ALAFIM_GERESH    Integer    PHP 5.0
CAL_JEWISH_ADD_ALAFIM    Integer    PHP 5.0
CAL_JEWISH_ADD_GERESHAYIM    Integer    PHP 5.0
cURL

[TOC]

要使用PHP的cURL支持你必须在编译PHP时加上--with-curl[=DIR] 选项,DIR为包含lib和include的目录路径。在include目录中必须有一个名为curl,包含了easy.h和curl.h的文件夹。lib文件夹里应该有一个名为libcurl.a的文件。对于PHP 4.3.0你可以配置--with-curlwrappers 使cURL使用URL流。
注意: Win32用户注意 要在Windows环境下使用这个模块,libeay32.dll和ssleay32.dll必须放到PATH环境变量包含的目录下。 不用cURL网站上的libcurl.dll。

函数

  函数    描述
curl_close()    关闭一个cURL会话。
curl_copy_handle()    复制一个cURL句柄和它的所有选项。
curl_errno()    返回最后一次的错误号。
curl_error()    返回一个保护当前会话最近一次错误的字符串。
curl_escape()    返回转义字符串,对给定的字符串进行URL编码。
curl_exec()    执行一个cURL会话。
curl_file_create()    创建一个 CURLFile 对象。
curl_getinfo()    获取一个cURL连接资源句柄的信息。
curl_init()    初始化一个cURL会话。
curl_multi_add_handle()    向curl批处理会话中添加单独的curl句柄。
curl_multi_close()    关闭一组cURL句柄。
curl_multi_exec()    运行当前 cURL 句柄的子连接。
curl_multi_getcontent()    如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流。
curl_multi_info_read()    获取当前解析的cURL的相关传输信息。
curl_multi_init()    返回一个新cURL批处理句柄。
curl_multi_remove_handle()    移除curl批处理句柄资源中的某个句柄资源。
curl_multi_select()    等待所有cURL批处理中的活动连接。
curl_multi_setopt()    设置一个批处理cURL传输选项。
curl_multi_strerror()    返回描述错误码的字符串文本。
curl_pause()    暂停及恢复连接。
curl_reset()    重置libcurl的会话句柄的所有选项。
curl_setopt_array()    为cURL传输会话批量设置选项。
curl_setopt()    设置一个cURL传输选项。
curl_share_close()    关闭cURL共享句柄。
curl_share_init()    初始化cURL共享句柄。
curl_share_setopt()    设置一个共享句柄的cURL传输选项。
curl_strerror()    返回错误代码的字符串描述。
curl_unescape()    解码URL编码后的字符串。
curl_version()    获取cURL版本信息。
Date/Time 时间

[TOC]

PHP.INI配置

Date/Time 函数的行为受到 php.ini 中设置的影响:

名称    描述    默认    PHP 版本
date.timezone    规定默认时区(所有的 Date/Time 函数使用该选项)    ""    PHP 5.1
date.default_latitude    规定默认纬度(date_sunrise() 和 date_sunset() 使用该选项)    "31.7667"    PHP 5.0
date.default_longitude    规定默认经度(date_sunrise() 和 date_sunset() 使用该选项)    "35.2333"    PHP 5.0
date.sunrise_zenith    规定默认日出天顶(date_sunrise() 和 date_sunset() 使用该选项)    "90.83"    PHP 5.0
date.sunset_zenith    规定默认日落天顶(date_sunrise() 和 date_sunset() 使用该选项)    "90.83"    PHP 5.0

函数

函数    描述
checkdate()    验证格利高里日期。
date_add()    添加日、月、年、时、分和秒到一个日期。
date_create_from_format()    返回一个根据指定格式进行格式化的新的 DateTime 对象。
date_create()    返回一个新的 DateTime 对象。
date_date_set()    设置一个新的日期。
date_default_timezone_get()    返回默认时区,被所有的 Date/Time 函数使用。
date_default_timezone_set()    设置默认时区,被所有的 Date/Time 函数使用。
date_diff()    返回两个日期间的差值。
date_format()    返回根据指定格式进行格式化的日期。
date_get_last_errors()    返回日期字符串中的警告/错误。
date_interval_create_from_date_string()    从字符串的相关部分建立一个 DateInterval。
date_interval_format()    格式化时间间隔。
date_isodate_set()    设置 ISO 日期。
date_modify()    修改时间戳。
date_offset_get()    返回时区偏移。
date_parse_from_format()    根据指定的格式返回一个带有指定日期的详细信息的关联数组。
date_parse()    返回一个带有指定日期的详细信息的关联数组。
date_sub()    从指定日期减去日、月、年、时、分和秒。
date_sun_info()    返回一个包含有关指定日期与地点的日出/日落和黄昏开始/黄昏结束的信息的数组。
date_sunrise()    返回指定日期与地点的日出时间。
date_sunset()    返回指定日期与地点的日落时间。
date_time_set()    设置时间。
date_timestamp_get()    返回 Unix 时间戳。
date_timestamp_set()    设置基于 Unix 时间戳的日期和时间。
date_timezone_get()    返回给定 DateTime 对象的时区。
date_timezone_set()    设置 DateTime 对象的时区。
date()    格式化本地日期和时间。
getdate()    返回某个时间戳或者当前本地的日期/时间的日期/时间信息。
gettimeofday()    返回当前时间。
gmdate()    格式化 GMT/UTC 日期和时间。
gmmktime()    返回 GMT 日期的 UNIX 时间戳。
gmstrftime()    根据区域设置格式化 GMT/UTC 日期和时间。
idate()    格式化本地时间/日期为整数。
localtime()    返回本地时间。
microtime()    返回当前 Unix 时间戳的微秒数。
mktime()    返回一个日期的 Unix 时间戳。
strftime()    根据区域设置格式化本地时间/日期。
strptime()    解析由 strftime() 生成的时间/日期。
strtotime()    将任何英文文本的日期或时间描述解析为 Unix 时间戳。
time()    返回当前时间的 Unix 时间戳。
timezone_abbreviations_list()    返回包含夏令时、偏移量和时区名称的关联数组。
timezone_identifiers_list()    返回带有所有时区标识符的数值数组。
timezone_location_get()    返回指定时区的位置信息。
timezone_name_from_ abbr()    根据时区缩略语返回时区名称。
timezone_name_get()    返回时区的名称。
timezone_offset_get()    返回相对于 GMT 的时区偏移。
timezone_open()    创建一个新的 DateTimeZone 对象。
timezone_transitions_get()    返回时区的所有转换。
timezone_version_get()    返回时区数据库的版本。

常量

常量    描述
DATE_ATOM    Atom (例如:2005-08-15T16:13:03+0000)
DATE_COOKIE    HTTP Cookies (例如:Sun, 14 Aug 2005 16:13:03 UTC)
DATE_ISO8601    ISO-8601 (例如:2005-08-14T16:13:03+0000)
DATE_RFC822    RFC 822 (例如:Sun, 14 Aug 2005 16:13:03 UTC)
DATE_RFC850    RFC 850 (例如:Sunday, 14-Aug-05 16:13:03 UTC)
DATE_RFC1036    RFC 1036 (例如:Sunday, 14-Aug-05 16:13:03 UTC)
DATE_RFC1123    RFC 1123 (例如:Sun, 14 Aug 2005 16:13:03 UTC)
DATE_RFC2822    RFC 2822 (例如:Sun, 14 Aug 2005 16:13:03 +0000)
DATE_RSS    RSS (例如:Sun, 14 Aug 2005 16:13:03 UTC)
DATE_W3C    万维网联盟 (例如:2005-08-14T16:13:03+0000)
Directory 目录

[TOC]

函数

函数    描述
chdir()    改变当前的目录。
chroot()    改变根目录。
closedir()    关闭目录句柄。
dir()    返回 Directory 类的实例。
getcwd()    返回当前工作目录。
opendir()    打开目录句柄。
readdir()    返回目录句柄中的条目。
rewinddir()    重置目录句柄。
scandir()    返回指定目录中的文件和目录的数组。
Error&Logging

[TOC]

PHP Error 和 Logging 简介

Error 和 Logging 函数允许您对错误进行处理和记录。
Error 函数允许用户定义错误处理规则,并修改记录错误的方式。
Logging 函数允许用户对应用程序进行日志记录,并把日志消息发送到电子邮件、系统日志或其他的机器。

执行配置

error 函数受 php.ini 配置文件影响。

错误和日志配置选项:

参数默认值描述可修改范围
error_reportingNULL设置 PHP 的报错级别并返回当前级别(数字或常量)。PHP_INI_ALL
display_errors"1"该选项设置是否将错误信息作为输出的一部分显示到屏幕,或者对用户隐藏而不显示。 注意: 该特性不要在上线生产环境中使用 (在开发测试过程中使用)PHP_INI_ALL
display_startup_errors"0"即使 display_errors 设置为开启, PHP 启动过程中的错误信息也不会被显示。强烈建议除了调试目的以外,将 display_startup_errors 设置为关闭。PHP_INI_ALL
log_errors"0"设置是否将脚本运行的错误信息记录到服务器错误日志或者error_log之中。注意,这是与服务器相关的特定配置项。PHP_INI_ALL
log_errors_max_len"1024"设置 log_errors 的最大字节数. 在 error_log 会添加有关错误源的信息。默认值为1024,如果设置为0表示不限长度。该长度设置对记录的错误,显示的错误,以及 $php_errormsg都会有限制作用。PHP_INI_ALL
ignore_repeated_errors"0"不记录重复的信息。重复的错误必须出现在同一个文件中的同一行代码上,除非 ignore_repeated_source 设置为true。PHP_INI_ALL
ignore_repeated_source"0"忽略重复消息时,也忽略消息的来源。当该设置开启时,重复信息将不会记录它是由不同的文件还是不同的源代码行产生的。PHP_INI_ALL
report_memleaks"1"如果这个参数设置为Off,则内存泄露信息不会显示 (在 stdout 或者日志中)。PHP_INI_ALL
track_errors"0"如果开启,最后的一个错误将永远存在于变量 $php_errormsg 中。PHP_INI_ALL
html_errors"1"在错误信息中关闭HTML标签。PHP_INI_ALLPHP_INI_SYSTEM in PHP <= 4.2.3.
xmlrpc_errors"0"关闭正常的错误报告,并将错误的格式设置为XML-RPC错误信息的格式。PHP_INI_SYSTEM
xmlrpc_error_number"0"用作 XML-RPC faultCode 元素的值。PHP_INI_ALL
docref_root""新的错误信息格式包含了对应的参考页面,该页面对错误进行具体描述,或者描述了导致该错误发生的函数。为了提供手册的页面,你可以在PHP官方站点下载对应语言的手册,并在ini中设置网址到本地对应的地址。如果你的本地手册拷贝可以使用"/manual/" 访问,你就可以简单的设置 docref_root=/manual/。另外你还需要设置 docref_ext 匹配你本地文件的后缀名 docref_ext=.html。当然也可以设置一个外部的参考地址。 例如你可以设置 docref_root=http://manual/en/ 或者 docref_root="http://landonize.it/how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F"PHP_INI_ALL
docref_ext""参见 docref_root.PHP_INI_ALL
error_prepend_stringNULL错误信息之前输出的内容。PHP_INI_ALL
error_append_stringNULL错误信息之后输出的内容。PHP_INI_ALL
error_logNULL设置脚本错误将被记录到的文件。该文件必须是web服务器用户可写的。PHP_INI_ALL

函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
debug_backtrace()生成 backtrace。4
debug_print_backtrace()打印 backtrace。5
error_get_last()获得最后发生的错误。5
error_log()向服务器错误记录、文件或远程目标发送一个错误。4
error_reporting()规定报告哪个错误。4
restore_error_handler()恢复之前的错误处理程序。4
restore_exception_handler()恢复之前的异常处理程序。5
set_error_handler()设置用户自定义的错误处理函数。4
set_exception_handler()设置用户自定义的异常处理函数。5
trigger_error()创建用户自定义的错误消息。4
user_error()trigger_error() 的别名。4

PHP Error 和 Logging 常量

PHP:指示支持该常量的最早的 PHP 版本。

常量描述PHP
1E_ERROR运行时致命的错误。不能修复的错误。停止执行脚本。
2E_WARNING运行时非致命的错误。没有停止执行脚本。
4E_PARSE编译时的解析错误。解析错误应该只由解析器生成。
8E_NOTICE运行时的通知。脚本发现可能是一个错误,但也可能在正常运行脚本时发生。
16E_CORE_ERRORPHP 启动时的致命错误。这就如同 PHP 核心的 E_ERROR。4
32E_CORE_WARNINGPHP 启动时的非致命错误。这就如同 PHP 核心的 E_WARNING。4
64E_COMPILE_ERROR编译时致命的错误。这就如同由 Zend 脚本引擎生成的 E_ERROR。4
128E_COMPILE_WARNING编译时非致命的错误。这就如同由 Zend 脚本引擎生成的 E_WARNING。4
256E_USER_ERROR用户生成的致命错误。这就如同由程序员使用 PHP 函数 trigger_error() 生成的 E_ERROR。4
512E_USER_WARNING用户生成的非致命错误。这就如同由程序员使用 PHP 函数 trigger_error() 生成的 E_WARNING。4
1024E_USER_NOTICE用户生成的通知。这就如同由程序员使用 PHP 函数 trigger_error() 生成的 E_NOTICE。4
2048E_STRICT运行时的通知。PHP 建议您改变代码,以提高代码的互用性和兼容性。5
4096E_RECOVERABLE_ERROR可捕获的致命错误。这就如同一个可以由用户定义的句柄捕获的 E_ERROR(见 set_error_handler())。5
6143E_ALL所有的错误和警告的级别,除了 E_STRICT(自 PHP 6.0 起,E_STRICT 将作为 E_ALL的一部分)。5
Filesystem 文件

[TOC]

PHP Filesystem 简介

Filesystem 函数允许您访问和操作文件系统。

安装

Filesystem 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

Runtime 配置

Filesystem 函数的行为受到 php.ini 中设置的影响。

Filesystem 配置选项:

名称默认描述可改变
allow_url_fopen"1"允许 fopen()-type 函数使用 URL。(PHP 4.0.4 版以后可用)PHP_INI_SYSTEM
user_agentNULL定义 PHP 发送的用户代理。(PHP 4.3 版以后可用)PHP_INI_ALL
default_socket_timeout"60"设置基于 socket 流的默认的超时时间(秒)。(PHP 4.3 版以后可用)PHP_INI_ALL
from""定义匿名 FTP 的密码(您的 email 地址)。PHP_INI_ALL
auto_detect_line_endings"0"当设置为 "1" 时,PHP 将检查通过 fgets() 和 file() 取得的数据中的行结束符号是符合 Unix、MS-Dos 还是 Mac 的习惯。(PHP 4.3 版以后可用)PHP_INI_ALL

Unix / Windows 兼容性

当在 Unix 平台上规定路径时,正斜杠 (/) 用作目录分隔符。而在 Windows 平台上,正斜杠 (/) 和反斜杠 () 均可使用。

PHP 5 Filesystem 函数

函数描述
basename()返回路径中的文件名部分。
chgrp()改变文件组。
chmod()改变文件模式。
chown()改变文件所有者。
clearstatcache()清除文件状态缓存。
copy()复制文件。
delete()参见 unlink() 或 unset()
dirname()返回路径中的目录名称部分。
disk_free_space()返回目录的可用空间。
disk_total_space()返回一个目录的磁盘总容量。
diskfreespace()disk_free_space() 的别名。
fclose()关闭打开的文件。
feof()测试文件指针是否到了文件末尾。
fflush()向打开的文件刷新缓冲输出。
fgetc()从打开的文件中返回字符。
fgetcsv()从打开的文件中解析一行,校验 <span lang="en-us">CSV 字段</span>。
fgets()从打开的文件中返回一行。
fgetss()从打开的文件中返回一行,并过滤掉 HTML 和 PHP 标签。
file()把文件读入一个数组中。
file_exists()检查文件或目录是否存在。
file_get_contents()把文件读入字符串。
file_put_contents()把字符串写入文件。
fileatime()返回文件的上次访问时间。
filectime()返回文件的上次修改时间。
filegroup()返回文件的组 ID。
fileinode()返回文件的 inode 编号。
filemtime()返回文件内容的上次修改时间。
fileowner()返回文件的用户 ID (所有者)。
fileperms()返回文件的权限。
filesize()返回文件大小。
filetype()返回文件类型。
flock()锁定或释放文件。
fnmatch()根据指定的模式来匹配文件名或字符串。
fopen()打开一个文件或 URL。
fpassthru()从打开的文件中读数据,直到文件末尾(EOF),并向输出缓冲写结果。
fputcsv()把行格式化为 CSV 并写入一个打开的文件中。
fputs()fwrite() 的别名。
fread()读取打开的文件。
fscanf()根据指定的格式对输入进行解析。
fseek()在打开的文件中定位。
fstat()返回关于一个打开的文件的信息。
ftell()返回在打开文件中的当前位置。
ftruncate()把打开文件截断到指定的长度。
fwrite()写入打开的文件。
glob()返回一个包含匹配指定模式的文件名/目录的数组。
is_dir()判断文件是否是一个目录。
is_executable()判断文件是否可执行。
is_file()判断文件是否是常规的文件。
is_link()判断文件是否是连接。
is_readable()判断文件是否可读。
is_uploaded_file()判断文件是否是通过 HTTP POST 上传的。
is_writable()判断文件是否可写。
is_writeable()is_writable() 的别名。
lchgrp()改变符号连接的组所有权。
lchown()改变符号连接的用户所有权。
link()创建一个硬连接。
linkinfo()返回有关一个硬连接的信息。
lstat()返回关于文件或符号连接的信息。
mkdir()创建目录。
move_uploaded_file()把上传的文件移动到新位置。
parse_ini_file()解析一个配置文件。
parse_ini_string()解析一个配置字符串。
pathinfo()返回关于文件路径的信息。
pclose()关闭由 popen() 打开的进程。
popen()打开一个进程。
readfile()读取一个文件,并写入到输出缓冲。
readlink()返回符号连接的目标。
realpath()返回绝对路径名。
realpath_cache_get()返回高速缓存条目。
realpath_cache_size()返回高速缓存大小。
rename()重命名文件或目录。
rewind()倒回文件指针的位置。
rmdir()删除空的目录。
set_file_buffer()设置已打开文件的缓冲大小。
stat()返回关于文件的信息。
symlink()创建符号连接。
tempnam()创建唯一的临时文件。
tmpfile()创建唯一的临时文件。
touch()设置文件的访问和修改时间。
umask()改变文件的文件权限。
unlink()删除文件。
Filter 过滤

[TOC]

PHP Filter 简介

PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤。

安装

Filter 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

PHP Filter 函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
filter_has_var()检查是否存在指定输入类型的变量。5
filter_id()返回指定过滤器的 ID 号。5
filter_input()从脚本外部获取输入,并进行过滤。5
filter_input_array()从脚本外部获取多项输入,并进行过滤。5
filter_list()返回包含所有得到支持的过滤器的一个数组。5
filter_var_array()获取多个变量,并进行过滤。5
filter_var()获取一个变量,并进行过滤。5

PHP Filters

名称描述
FILTER_CALLBACK调用用户自定义函数来过滤数据。
FILTER_SANITIZE_STRING去除标签,去除或编码特殊字符。
FILTER_SANITIZE_STRIPPED"string" 过滤器的别名。
FILTER_SANITIZE_ENCODEDURL-encode 字符串,去除或编码特殊字符。
FILTER_SANITIZE_SPECIAL_CHARSHTML 转义字符 '"<>& 以及 ASCII 值小于 32 的字符。
FILTER_SANITIZE_EMAIL删除所有字符,除了字母、数字以及 !#$%&'*+-/=?^_`{|}~@.[]
FILTER_SANITIZE_URL删除所有字符,除了字母、数字以及 $-_.+!*'(),{}|^~[]`<>#%";/?:@&=
FILTER_SANITIZE_NUMBER_INT删除所有字符,除了数字和 +-
FILTER_SANITIZE_NUMBER_FLOAT删除所有字符,除了数字、+- 以及 .,eE
FILTER_SANITIZE_MAGIC_QUOTES应用 addslashes()。
FILTER_UNSAFE_RAW不进行任何过滤,去除或编码特殊字符。
FILTER_VALIDATE_INT把值作为整数来验证。
FILTER_VALIDATE_BOOLEAN把值作为布尔选项来验证。如果是 "1"、"true"、"on" 和 "yes",则返回 TRUE。如果是 "0"、"false"、"off"、"no" 和 "",则返回 FALSE。否则返回 NULL。
FILTER_VALIDATE_FLOAT把值作为浮点数来验证。
FILTER_VALIDATE_REGEXP根据 regexp(一种兼容 Perl 的正则表达式)来验证值。
FILTER_VALIDATE_URL把值作为 URL 来验证。
FILTER_VALIDATE_EMAIL把值作为 e-mail 地址来验证。
FILTER_VALIDATE_IP把值作为 IP 地址来验证,只限 IPv4 或 IPv6 或 不是来自私有或者保留的范围。
FTP

[TOC]

PHP FTP 简介

FTP 函数通过文件传输协议 (FTP) 提供对文件服务器的客户端访问。
FTP 函数用于打开、登录以及关闭连接,同时用于上传、下载、重命名、删除及获取文件服务器上的文件信息。不是所有的 FTP 函数对每个服务器都起作用或返回相同的结果。自 PHP 3 起,FTP 函数可用。
这些函数用于对 FTP 服务器进行细致的访问。如果您仅仅需要对 FTP 服务器进行读写操作,建议使用 Filesystem 函数中的 ftp:// wrapper。

安装

PHP 的 Windows 版本内置了对 FTP 扩展的支持。无需加载任何附加扩展库即可使用 FTP 函数。
然而,如果您运行的是 PHP 的 Linux 版本,在编译 PHP 的时候请添加 --enable-ftp 选项(PHP4 或以上版本)或者 --with-ftp 选项(PHP3 版本)。

PHP FTP 函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
ftp_alloc()为要上传到 FTP 服务器的文件分配空间。5
ftp_cdup()把当前目录改变为 FTP 服务器上的父目录。3
ftp_chdir()改变 FTP 服务器上的当前目录。3
ftp_chmod()通过 FTP 设置文件上的权限。5
ftp_close()关闭 FTP 连接。4
ftp_connect()打开 FTP 连接。3
ftp_delete()删除 FTP 服务器上的一个文件。3
ftp_exec()在 FTP 服务器上执行一个程序/命令。4
ftp_fget()从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中。3
ftp_fput()上传一个已经打开的文件,并在 FTP 服务器上把它保存为一个文件。3
ftp_get_option()返回 FTP 连接的各种运行时选项。4
ftp_get()从 FTP 服务器上下载文件。3
ftp_login()登录 FTP 服务器。3
ftp_mdtm()返回指定文件的最后修改时间。3
ftp_mkdir()在 FTP 服务器上创建一个新目录。3
ftp_nb_continue()连续获取/发送文件。(无阻塞)4
ftp_nb_fget()从 FTP 服务器上下载一个文件并保存到本地一个已经打开的文件中。(无阻塞)4
ftp_nb_fput()上传一个已经打开的文件,并在 FTP 服务器上把它保存为一个文件。(无阻塞)4
ftp_nb_get()从 FTP 服务器上下载文件。(无阻塞)4
ftp_nb_put()把文件上传到 FTP 服务器上。(无阻塞)4
ftp_nlist()返回 FTP 服务器上指定目录的文件列表。3
ftp_pasv()把被动模式设置为打开或关闭。3
ftp_put()把文件上传到 FTP 服务器上。3
ftp_pwd()返回当前目录名称。3
ftp_quit()ftp_close() 的别名。3
ftp_raw()向 FTP 服务器发送一个 raw 命令。5
ftp_rawlist()返回指定目录中文件的详细列表。3
ftp_rename()重命名 FTP 服务器上的文件或目录。3
ftp_rmdir()删除 FTP 服务器上的一个目录。3
ftp_set_option()设置 FTP 连接的各种运行时选项。4
ftp_site()向服务器发送 SITE 命令。3
ftp_size()返回指定文件的大小。3
ftp_ssl_connect()打开一个安全的 SSL-FTP 连接。4
ftp_systype()返回 FTP 服务器的系统类型标识符。3

PHP FTP 常量

PHP:指示支持该常量的最早的 PHP 版本。

常量描述PHP
FTP_ASCII 3
FTP_TEXT 3
FTP_BINARY 3
FTP_IMAGE 3
FTP_TIMEOUT_SEC 3
FTP_AUTOSEEK 4
FTP_AUTORESUME为 GET 和 PUT 请求自动决定恢复和开始的位置4
FTP_FAILED异步传输失败4
FTP_FINISHED异步传输成功4
FTP_MOREDATA异步传输是活动状态的4
http

[TOC]

PHP HTTP 简介

HTTP 函数允许您在其他输出被发送之前,对由 Web 服务器发送到浏览器的信息进行操作。

安装

HTTP 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

PHP HTTP 函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
header()向客户端发送原始的 HTTP 报头。3
headers_list()返回已发送的(或待发送的)响应头部的一个列表。5
headers_sent()检查 HTTP 报头是否发送/已发送到何处。3
setcookie()向客户端发送一个 HTTP cookie。3
setrawcookie()不对 cookie 值进行 URL 编码,发送一个 HTTP cookie。5
Math 数学

[TOC]

PHP Math 简介

Math 函数能处理 integer 和 float 范围内的值。

安装

PHP Math 函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

PHP 5 Math 函数

函数描述
abs()返回一个数的绝对值。
acos()返回一个数的反余弦。
acosh()返回一个数的反双曲余弦。
asin()返回一个数的反正弦。
asinh()返回一个数的反双曲正弦。
atan()返回一个数的反正切。
atan2()返回两个变量 x 和 y 的反正切。
atanh()返回一个数的反双曲正切。
base_convert()在任意进制之间转换数字。
bindec()把二进制数转换为十进制数。
ceil()向上舍入为最接近的整数。
cos()返回一个数的余弦。
cosh()返回一个数的双曲余弦。
decbin()把十进制数转换为二进制数。
dechex()把十进制数转换为十六进制数。
decoct()把十进制数转换为八进制数。
deg2rad()将角度值转换为弧度值。
exp()返回 Ex 的值。
expm1()返回 Ex - 1 的值。
floor()向下舍入为最接近的整数。
fmod()返回 x/y 的浮点数余数。
getrandmax()返回通过调用 rand() 函数显示的随机数的最大可能值。
hexdec()把十六进制数转换为十进制数。
hypot()计算直角三角形的斜边长度。
is_finite()判断是否为有限值。
is_infinite()判断是否为无限值。
is_nan()判断是否为非数值。
lcg_value()返回范围为 (0, 1) 的一个伪随机数。
log()返回一个数的自然对数(以 E 为底)。
log10()返回一个数的以 10 为底的对数。
log1p()返回 log(1+number)
max()返回一个数组中的最大值,或者几个指定值中的最大值。
min()返回一个数组中的最小值,或者几个指定值中的最小值。
mt_getrandmax()返回通过调用 mt_rand() 函数显示的随机数的最大可能值。
mt_rand()使用 Mersenne Twister 算法生成随机整数。
mt_srand()播种 Mersenne Twister 随机数生成器。
octdec()把八进制数转换为十进制数。
pi()返回圆周率 PI 的值。
pow()返回 x 的 y 次方。
rad2deg()把弧度值转换为角度值。
rand()返回随机整数。
round()对浮点数进行四舍五入。
sin()返回一个数的正弦。
sinh()返回一个数的双曲正弦。
sqrt()返回一个数的平方根。
srand()播种随机数生成器。
tan()返回一个数的正切。
tanh()返回一个数的双曲正切。

PHP 5 预定义的 Math 常量

常量描述PHP 版本
INFINF无限PHP 4
M_E2.7182818284590452354返回 ePHP 4
M_EULER0.57721566490153286061返回 Euler 常量PHP 4
M_LNPI1.14472988584940017414返回圆周率 PI 的自然对数:log_e(pi)PHP 5.2
M_LN20.69314718055994530942返回 2 的自然对数:log_e 2PHP 4
M_LN102.30258509299404568402返回 10 的自然对数:log_e 10PHP 4
M_LOG2E1.4426950408889634074返回 E 的以 2 为底的对数:log_2 ePHP 4
M_LOG10E0.43429448190325182765返回 E 的以 10 为底的对数:log_10 ePHP 4
M_PI3.14159265358979323846返回 PiPHP 4
M_PI_21.57079632679489661923返回 Pi/2PHP 4
M_PI_40.78539816339744830962返回 Pi/4PHP 4
M_1_PI0.31830988618379067154返回 1/PiPHP 4
M_2_PI0.63661977236758134308返回 2/PiPHP 4
M_SQRTPI1.77245385090551602729返回圆周率 PI 的平方根:sqrt(pi)PHP 5.2
M_2_SQRTPI1.12837916709551257390返回圆周率 PI 的 2/平方根:2/sqrt(pi)PHP 4
M_SQRT1_20.70710678118654752440返回 1/2 的平方根:1/sqrt(2)PHP 4
M_SQRT21.41421356237309504880返回 2 的平方根:sqrt(2)PHP 4
M_SQRT31.73205080756887729352返回 3 的平方根:sqrt(3)PHP 5.2
NANNAN不是一个数字PHP 4
PHP_ROUND_HALF_UP1遇到 .5 的情况时向上舍入PHP 5.3
PHP_ROUND_HALF_DOWN2遇到 .5 的情况时向下舍入PHP 5.3
PHP_ROUND_HALF_EVEN3遇到 .5 的情况时取偶数舍入PHP 5.3
PHP_ROUND_HALF_ODD4遇到 .5 的情况时取奇数舍入PHP 5.3
其它

[TOC]

PHP 杂项函数简介

我们把不属于其他类别的函数归纳到杂项函数类别。

安装

杂项函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

Runtime 配置

杂项函数的行为受 php.ini 文件中的设置的影响。

杂项配置选项:

名称默认描述可更改
ignore_user_abort"0"FALSE 指示只要脚本在客户机终止连接后尝试进行输出,脚本将被终止。PHP_INI_ALL
highlight.string"#DD0000"供突出显示符合 PHP 语法的字符串而使用的颜色。PHP_INI_ALL
highlight.comment"#FF8000"供突出显示 PHP 注释而使用的颜色。PHP_INI_ALL
highlight.keyword"#007700"供语法高亮显示 PHP 关键词而使用的颜色(比如圆括号和分号)。PHP_INI_ALL
highlight.bg"#FFFFFF"背景颜色。PHP_INI_ALL
highlight.default"#0000BB"PHP 语法的默认颜色。PHP_INI_ALL
highlight.html"#000000"HTML 代码的颜色。PHP_INI_ALL
browscapNULL浏览器性能文件(例如:browscap.ini)的名称和位置。PHP_INI_SYSTEM

PHP 杂项函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
connection_aborted()检查是否断开客户机。3
connection_status()返回当前的连接状态。3
connection_timeout()在 PHP 4.0.5 中不赞成使用。检查脚本是否超时。3
constant()返回一个常量的值。4
define()定义一个常量。3
defined()检查某常量是否存在。3
die()输出一条消息,并退出当前脚本。3
eval()把字符串当成 PHP 代码来计算。3
exit()输出一条消息,并退出当前脚本。3
get_browser()返回用户浏览器的性能。3
highlight_file()对文件进行 PHP 语法高亮显示。4
highlight_string()对字符串进行 PHP 语法高亮显示。4
ignore_user_abort()设置与远程客户机断开是否会终止脚本的执行。3
pack()把数据装入一个二进制字符串。3
php_check_syntax()在 PHP 5.0.5 中不赞成使用。5
php_strip_whitespace()返回已删除 PHP 注释以及空白字符的源代码文件。5
show_source()highlight_file() 的别名。4
sleep()延迟代码执行若干秒。3
time_nanosleep()延迟代码执行若干秒和纳秒。5
time_sleep_until()延迟代码执行直到指定的时间。5
uniqid()生成唯一的 ID。3
unpack()从二进制字符串对数据进行解包。3
usleep()延迟代码执行若干微秒。3

PHP 杂项常量

PHP:指示支持该常量的最早的 PHP 版本。

常量描述PHP
CONNECTION_ABORTED
CONNECTION_NORMAL
CONNECTION_TIMEOUT
COMPILER_HALT_OFFSET 5
PDO

[TOC]

PHP 杂项函数简介

我们把不属于其他类别的函数归纳到杂项函数类别。

安装

杂项函数是 PHP 核心的组成部分。无需安装即可使用这些函数。

Runtime 配置

杂项函数的行为受 php.ini 文件中的设置的影响。

杂项配置选项:

名称默认描述可更改
ignore_user_abort"0"FALSE 指示只要脚本在客户机终止连接后尝试进行输出,脚本将被终止。PHP_INI_ALL
highlight.string"#DD0000"供突出显示符合 PHP 语法的字符串而使用的颜色。PHP_INI_ALL
highlight.comment"#FF8000"供突出显示 PHP 注释而使用的颜色。PHP_INI_ALL
highlight.keyword"#007700"供语法高亮显示 PHP 关键词而使用的颜色(比如圆括号和分号)。PHP_INI_ALL
highlight.bg"#FFFFFF"背景颜色。PHP_INI_ALL
highlight.default"#0000BB"PHP 语法的默认颜色。PHP_INI_ALL
highlight.html"#000000"HTML 代码的颜色。PHP_INI_ALL
browscapNULL浏览器性能文件(例如:browscap.ini)的名称和位置。PHP_INI_SYSTEM

PHP 杂项函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
connection_aborted()检查是否断开客户机。3
connection_status()返回当前的连接状态。3
connection_timeout()在 PHP 4.0.5 中不赞成使用。检查脚本是否超时。3
constant()返回一个常量的值。4
define()定义一个常量。3
defined()检查某常量是否存在。3
die()输出一条消息,并退出当前脚本。3
eval()把字符串当成 PHP 代码来计算。3
exit()输出一条消息,并退出当前脚本。3
get_browser()返回用户浏览器的性能。3
highlight_file()对文件进行 PHP 语法高亮

PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。

PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

PDO随PHP5.1发行,在PHP5.0的PECL扩展中也可以使用,无法运行于之前的PHP版本。

PDO 安装

你可以通过 PHP 的 phpinfo() 函数来查看是否安装了PDO扩展。

在 Unix 系统上安装 PDO

在Unix上或Linux上你需要添加以下扩展:

extension=pdo.so

Windows 用户

PDO 和所有主要的驱动作为共享扩展随 PHP 一起发布,要激活它们只需简单地编辑 php.ini 文件,并添加以下扩展:

extension=php_pdo.dll

除此之外还有以下对应的各种数据库扩展:

;extension=php_pdo_firebird.dll
;extension=php_pdo_informix.dll
;extension=php_pdo_mssql.dll
;extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_oci8.dll
;extension=php_pdo_odbc.dll
;extension=php_pdo_pgsql.dll
;extension=php_pdo_sqlite.dll


在设定好这些配置后,我们需要重启PHP 或 Web服务器。

接下来我们们来看下具体的实例,以下为使用PDO连接MySql数据库的实例:

<?php
$dbms='mysql';     //数据库类型
$host='localhost'; //数据库主机名
$dbName='test';    //使用的数据库
$user='root';      //数据库连接用户名
$pass='';          //对应的密码
$dsn="$dbms:host=$host;dbname=$dbName";
 
 
try {
    $dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象
    echo "连接成功<br/>";
    /*你还可以进行一次搜索操作
    foreach ($dbh->query('SELECT * from FOO') as $row) {
        print_r($row); //你可以用 echo($GLOBAL); 来看到这些值
    }
    */
    $dbh = null;
} catch (PDOException $e) {
    die ("Error!: " . $e->getMessage() . "<br/>");
}
//默认这个不是长连接,如果需要数据库长连接,需要最后加一个参数:array(PDO::ATTR_PERSISTENT => true) 变成这样:
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
 
?>


很简单吧,接下来就让我们来具体看下PHP PDO具体说明:

  • PDO 类:

    *   PDO::beginTransaction — 启动一个事务
    *   PDO::commit — 提交一个事务
    *   PDO::__construct — 创建一个表示数据库连接的 PDO 实例
    *   PDO::errorCode — 获取跟数据库句柄上一次操作相关的 SQLSTATE
    *   PDO::errorInfo — 返回最后一次操作数据库的错误信息
    *   PDO::exec — 执行一条 SQL 语句,并返回受影响的行数
    *   PDO::getAttribute — 取回一个数据库连接的属性
    *   PDO::getAvailableDrivers — 返回一个可用驱动的数组
    *   PDO::inTransaction — 检查是否在一个事务内
    *   PDO::lastInsertId — 返回最后插入行的ID或序列值
    *   PDO::prepare — 备要执行的SQL语句并返回一个 PDOStatement 对象
    *   PDO::query — 执行 SQL 语句,返回PDOStatement对象,可以理解为结果集
    *   PDO::quote — 为SQL语句中的字符串添加引号。
    *   PDO::rollBack — 回滚一个事务
    *   PDO::setAttribute — 设置属性
  • PDOStatement 类:

    *   PDOStatement::bindColumn — 绑定一列到一个 PHP 变量
    *   PDOStatement::bindParam — 绑定一个参数到指定的变量名
    *   PDOStatement::bindValue — 把一个值绑定到一个参数
    *   PDOStatement::closeCursor — 关闭游标,使语句能再次被执行。
    *   PDOStatement::columnCount — 返回结果集中的列数
    *   PDOStatement::debugDumpParams — 打印一条 SQL 预处理命令
    *   PDOStatement::errorCode — 获取跟上一次语句句柄操作相关的 SQLSTATE
    *   PDOStatement::errorInfo — 获取跟上一次语句句柄操作相关的扩展错误信息
    *   PDOStatement::execute — 执行一条预处理语句
    *   PDOStatement::fetch — 从结果集中获取下一行
    *   PDOStatement::fetchAll — 返回一个包含结果集中所有行的数组
    *   PDOStatement::fetchColumn — 从结果集中的下一行返回单独的一列。
    *   PDOStatement::fetchObject — 获取下一行并作为一个对象返回。
    *   PDOStatement::getAttribute — 检索一个语句属性
    *   PDOStatement::getColumnMeta — 返回结果集中一列的元数据
    *   PDOStatement::nextRowset — 在一个多行集语句句柄中推进到下一个行集
    *   PDOStatement::rowCount — 返回受上一个 SQL 语句影响的行数
    *   PDOStatement::setAttribute — 设置一个语句属性
    *   PDOStatement::setFetchMode — 为语句设置默认的获取模式。
    
ZIP

PHP Zip File 简介

Zip File 函数允许您读取压缩文件。

安装

如需在服务器上运行 Zip File 函数,必须安装这些库:

  • Guido Draheim 的 ZZIPlib 库: 下载 ZZIPlib 库](//zziplib.sourceforge.net/download.html)
  • Zip PELC 扩展:下载 Zip PELC 扩展](//snaps.php.net/)

在 Linux 系统上安装

PHP 5+:Zip 函数和 Zip 库默认不会启用,必须从上面的链接下载。请使用 --with-zip=DIR 配置选项来包含 Zip 支持。

在 Windows 系统上安装

PHP 5+:Zip 函数默认不会启用,必须从上面的链接下载 php_zip.dll 和 ZZIPlib 库。必须在 php.ini 中启用 php_zip.dll。

如需启用任何 PHP 扩展,PHP extension_dir 设置(在 php.ini 文件中)应该设置为该 PHP 扩展所在的目录。举例 extension_dir 的值可能是 c:\php\ext。

PHP Zip File 函数

PHP:指示支持该函数的最早的 PHP 版本。

函数描述PHP
zip_close()关闭 ZIP 文件。4
zip_entry_close()关闭 ZIP 文件中的一个项目。4
zip_entry_compressedsize()返回 ZIP 文件中的一个项目的被压缩尺寸。4
zip_entry_compressionmethod()返回 ZIP 文件中的一个项目的压缩方法。4
zip_entry_filesize()返回 ZIP 文件中的一个项目的实际文件尺寸。4
zip_entry_name()返回 ZIP 文件中的一个项目的名称。4
zip_entry_open()打开 ZIP 文件中的一个项目以供读取。4
zip_entry_read()读取 ZIP 文件中的一个打开的项目。4
zip_open()打开 ZIP 文件。4
zip_read()读取 ZIP 文件中的下一个项目。4
GD 图像

PHP 提供了丰富的图像处理函数,主要包括:

函数描述
gd_info()取得当前安装的 GD 库的信息
getimagesize()获取图像信息
getimagesizefromstring()获取图像信息
image_type_to_extension()获取图片后缀
image_type_to_mime_type()返回图像的 MIME 类型
image2wbmp()输出WBMP图片
imageaffine()返回经过仿射变换后的图像
imageaffinematrixconcat()连接两个矩阵
imageaffinematrixget()获取矩阵
imagealphablending()设定图像的混色模式
imageantialias()是否使用抗锯齿(antialias)功能
imagearc()画椭圆弧
imagechar()写出横向字符
imagecharup()垂直地画一个字符
imagecolorallocate()为一幅图像分配颜色
imagecolorallocatealpha()为一幅图像分配颜色和透明度
imagecolorat()取得某像素的颜色索引值
imagecolorclosest()取得与指定的颜色最接近的颜色的索引值
imagecolorclosestalpha()取得与指定的颜色加透明度最接近的颜色的索引
imagecolorclosesthwb()取得与指定的颜色最接近的色度的黑白色的索引
imagesx() 、imagesy()获取图像宽度与高度

GD 库

使用 PHP 图像处理函数,需要加载 GD 支持库。请确定 php.ini 加载了 GD 库

PCRE 正则表达式

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

PHP 中我们可以使用 PCRE 扩展来匹配字符串的模式。

PCRE 函数

函数描述
preg_filter执行一个正则表达式搜索和替换
preg_grep返回匹配模式的数组条目
preg_last_error返回最后一个PCRE正则执行产生的错误代码
preg_match_all执行一个全局正则表达式匹配
preg_match执行一个正则表达式匹配
preg_quote转义正则表达式字符
preg_replace_callback_array执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace_callback执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace执行一个正则表达式的搜索和替换
preg_split通过一个正则表达式分隔字符串

PREG 常量

常量描述自哪个版本起
PREG_PATTERN_ORDER结果按照"规则"排序,仅用于preg_match_all(), 即$matches0]是完整规则的匹配结果, $matches1]是第一个子组匹配的结果,等等。since
PREG_SET_ORDER结果按照"集合"排序,仅用于preg_match_all(), 即$matches0]保存第一次匹配结果的所有结果(包含子组)信息, $matches1]保存第二次的结果信息,等等。 
PREG_OFFSET_CAPTURE查看 PREG_SPLIT_OFFSET_CAPTURE 的描述。4.3.0
PREG_SPLIT_NO_EMPTY这个标记告诉 preg_split() 进返回非空部分。 
PREG_SPLIT_DELIM_CAPTURE这个标记告诉 preg_split() 同时捕获括号表达式匹配到的内容。4.0.5
PREG_SPLIT_OFFSET_CAPTURE如果设置了这个标记,每次出现的匹配子串的偏移量也会被返回。注意,这会改变返回数组中的值, 每个元素都是由匹配子串作为第0个元素,它相对目标字符串的偏移量作为第1个元素的数组。这个 标记只能用于 preg_split()。4.3.0
PREG_NO_ERROR没有匹配错误时调用 preg_last_error() 返回。5.2.0
PREG_INTERNAL_ERROR如果有PCRE内部错误时调用 preg_last_error() 返回。5.2.0
PREG_BACKTRACK_LIMIT_ERROR如果调用回溯限制超出,调用preg_last_error()时返回。5.2.0
PREG_RECURSION_LIMIT_ERROR如果递归限制超出,调用preg_last_error()时返回。5.2.0
PREG_BAD_UTF8_ERROR如果最后一个错误时由于异常的utf-8数据(仅在运行在 UTF-8 模式正则表达式下可用)。 导致的,调用preg_last_error()返回。5.2.0
PREG_BAD_UTF8_OFFSET_ERROR如果偏移量与合法的urf-8代码不匹配(仅在运行在 UTF-8 模式正则表达式下可用)。 调用preg_last_error()返回。5.3.0
PCRE_VERSIONPCRE版本号和发布日期(比如: " _7.0 18-Dec-2006_")。
时间

[TOC]

Date()

d - 代表月中的天 (01 - 31)
m - 代表月 (01 - 12)
Y - 代表年 (四位数)

date() 函数的第二个可选参数 timestamp 规定了一个时间戳。如果您没有提供时间戳,将使用当前的日期和时间。

mktime()

函数可为指定的日期返回 Unix 时间戳。

Unix 时间戳包含了 Unix 纪元(1970-01-01 00:00:00 GMT)和指定时间之间的秒数。

cookie&session

[TOC]

cookie

增加

setcookie(name, value, expire, path, domain);

获取

$_COOKIE 变量用于取回 cookie 的值。

删除

当删除 cookie 时,您应当使过期日期变更为过去的时间点。
setcookie("user", "", time()-3600);

##SESSION
在您把用户信息存储到 PHP session 中之前,首先必须启动会话。
session_start()

unset() 函数用于释放指定的 session 变量:
存储和取回 session 变量的正确方法是使用 PHP $_SESSION 变量:

类(待补充)
命名空间(待补充)
errors(待补充)
函数参考(待补充)
影响 PHP 行为的扩展
表达式&运算符

[TOC]

表达式

基本表达式

最基本的表达式形式是常量和变量。
当键入"$a = 5",即将值"5"分配给变量 $a。"5",很明显,其值为 5,换句话说"5"是一个值为 5 的表达式(在这里,"5"是一个整型常量)。

比较表达式

(大于),>=(大于等于),==(等于),!=(不等于),<(小于),<= (小于等于)

三元

$a = $a?$a:$c;

运算符

算术运算符

-$a     取反    $a 的负值。
$a + $b    加法    $a 和 $b 的和。
$a - $b    减法    $a 和 $b 的差。
$a * $b    乘法    $a 和 $b 的积。
$a / $b    除法    $a 除以 $b 的商。
$a % $b    取模    $a 除以 $b 的余数。
$a ** $b    Exponentiation    Result of raising $a to the $b'th power. Introduced in PHP 5.6.(求幂; 取幂)

赋值运算符

基本的赋值运算符

本的赋值运算符是"="。一开始可能会以为它是"等于",其实不是的。它实际上意味着把右边表达式的值赋给左边的运算数。

<?php

$a = ($b = 4) + 5; // $a 现在成了 9,而 $b 成了 4。

?>

二元算术

<?php

$a = 3;
$a += 5; // sets $a to 8, as if we had said: $a = $a + 5;
$b = "Hello ";
$b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!";

?>

引用赋值

<?php
$a = 3;
$b = &$a; // $b 是 $a 的引用

print "$a\n"; // 输出 3
print "$b\n"; // 输出 3

$a = 4; // 修改 $a

print "$a\n"; // 输出 4
print "$b\n"; // 也输出 4,因为 $b 是 $a 的引用,因此也被改变
?>

位运算符

$a & $b    And(按位与)    将把 $a 和 $b 中都为 1 的位设为 1。
$a | $b    Or(按位或)    将把 $a 和 $b 中任何一个为 1 的位设为 1。
$a ^ $b    Xor(按位异或)    将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
~ $a    Not(按位取反)    将 $a 中为 0 的位设为 1,反之亦然。
$a << $b    Shift left(左移)    将 $a 中的位向左移动 $b 次(每一次移动都表示"乘以 2")。
$a >> $b    Shift right(右移)    将 $a 中的位向右移动 $b 次(每一次移动都表示"除以 2")。

比较运算符

$a == $b    等于    TRUE,如果类型转换后 $a 等于 $b。
$a === $b    全等    TRUE,如果 $a 等于 $b,并且它们的类型也相同。
$a != $b    不等    TRUE,如果类型转换后 $a 不等于 $b。
$a <> $b    不等    TRUE,如果类型转换后 $a 不等于 $b。
$a !== $b    不全等    TRUE,如果 $a 不等于 $b,或者它们的类型不同。
$a < $b    小与    TRUE,如果 $a 严格小于 $b。
$a > $b    大于    TRUE,如果 $a 严格大于 $b。
$a <= $b    小于等于    TRUE,如果 $a 小于或者等于 $b。
$a >= $b    大于等于    TRUE,如果 $a 大于或者等于 $b。
$a <=> $b    结合比较运算符    当$a小于、等于、大于than $b时 分别返回一个小于、等于、大于0的integer 值。 PHP7开始提供.
$a ?? $b ?? $c    NULL 合并操作符    从左往右第一个存在且不为 NULL 的操作数。如果都没有定义且不为 NULL,则返回 NULL。PHP7开始提供。

错误控制运算符@

PHP 支持一个错误控制运算符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉

执行运算符

PHP 支持一个执行运算符:反引号(``)。注意这不是单引号!PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符"`"的效果与函数 shell_exec() 相同。
反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。

递增/递减运算符

++$a    前加    $a 的值加一,然后返回 $a。
$a++    后加    返回 $a,然后将 $a 的值加一。
--$a    前减    $a 的值减一, 然后返回 $a。
$a--    后减    返回 $a,然后将 $a 的值减一。

逻辑运算符

$a and $b    And(逻辑与)    TRUE,如果 $a 和 $b 都为 TRUE。
$a or $b    Or(逻辑或)    TRUE,如果 $a 或 $b 任一为 TRUE。
$a xor $b    Xor(逻辑异或)    TRUE,如果 $a 或 $b 任一为 TRUE,但不同时是。
! $a    Not(逻辑非)    TRUE,如果 $a 不为 TRUE。
$a && $b    And(逻辑与)    TRUE,如果 $a 和 $b 都为 TRUE。
$a || $b    Or(逻辑或)    TRUE,如果 $a 或 $b 任一为 TRUE。

字符串运算符

有两个字符串(string)运算符。
第一个是连接运算符("."),它返回其左右参数连接后的字符串。
第二个是连接赋值运算符(".="),它将右边参数附加到左边的参数之后。

数组运算符

    $a + $b    联合    $a 和 $b 的联合。
    $a == $b    相等    如果 $a 和 $b 具有相同的键/值对则为 TRUE。
    $a === $b    全等    如果 $a 和 $b 具有相同的键/值对并且顺序和类型都相同则为 TRUE。
    $a != $b    不等    如果 $a 不等于 $b 则为 TRUE。
    $a <> $b    不等    如果 $a 不等于 $b 则为 TRUE。
    $a !== $b    不全等    如果 $a 不全等于 $b 则为 TRUE。

Explame 1#
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
$c = $a + $b; // Union of $a and $b
var_dump($c);

array(3) { ["a"]=> string(5) "apple" ["b"]=> string(6) "banana" ["c"]=> string(6) "cherry" }

类型运算符

instanceof

1.确定一个 PHP 变量是否属于某一类
2.确定一个变量是不是继承自某一父类的子类的实例

  1. 检查对象不是某个类的实例
  2. 确定一个变量是不是实现了某个接口的对象
对象
Trait

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

个人理解:类似于多继承

<?php
trait trait1{
    public function eat(){
        echo "This is trait1 eat";
    }
    public function drive(){
        echo "This is trait1 drive";
    }
}
trait trait2{
    public function eat(){
        echo "This is trait2 eat";
    }
    public function drive(){
        echo "This is trait2 drive";
    }
}
class cat{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
    }
}
class dog{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
        trait2::eat as eaten;##如果重名,可以用as重命名
        trait2::drive as driven;
    }
}
$cat = new cat();
$cat->eat();
echo "<br/>";
$cat->drive();
echo "<br/>";
echo "<br/>";
echo "<br/>";
$dog = new dog();
$dog->eat();
echo "<br/>";
$dog->drive();
echo "<br/>";
$dog->eaten();
echo "<br/>";
$dog->driven();
?>
匿名类 PHP7

PHP 7 开始支持匿名类。 匿名类很有用,可以创建一次性的简单对象。

<?php

// PHP 7 之前的代码
class Logger
{
    public function log($msg)
    {
        echo $msg;
    }
}

$util->setLogger(new Logger());

// 使用了 PHP 7+ 后的代码
$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});
重载(待补充)
遍历对象(待补充)
魔术方法(待补充)
对象序列化(待补充细化)

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。

序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

为了能够unserialize()一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。 如果要想在另外一个文件中解序列化一个对象,这个对象的类必须在解序列化之前定义,可以通过包含一个定义该类的文件或使用函数spl_autoload_register()来实现。

对象比较

PHP 5 中的对象比较要比 PHP 4 中复杂,所期望的结果更符合一个面向对象语言。

当使用比较运算符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。

而如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)。

类型约束

PHP 5 可以使用类型约束。函数的参数可以指定必须为对象(在函数原型里面指定类的名字),接口,数组(PHP 5.1 起)或者 callable(PHP 5.4 起)。

  1. 如果一个类或接口指定了类型约束,则其所有的子类或实现也都如此。
  2. 类型约束不能用于标量类型如 int 或 string。Traits 也不允许。
  3. 函数调用的参数与定义的参数类型不一致时,会抛出一个可捕获的致命错误。
  4. 类型约束不只是用在类的成员函数里,也能使用在函数里
  5. 类型约束允许 NULL 值,如果使用 NULL 作为参数的默认值,那么在调用函数的时候依然可以使用 NULL 作为实参
<?php
//如下面的类
class MyClass
{
    /**
     * 测试函数
     * 第一个参数必须为 OtherClass 类的一个对象
     */
    public function test(OtherClass $otherclass) {
        echo $otherclass->var;
    }


    /**
     * 另一个测试函数
     * 第一个参数必须为数组 
     */
    public function test_array(array $input_array) {
        print_r($input_array);
    }
}

    /**
     * 第一个参数必须为递归类型
     */
    public function test_interface(Traversable $iterator) {
        echo get_class($iterator);
    }
    
    /**
     * 第一个参数必须为回调类型
     */
    public function test_callable(callable $callback, $data) {
        call_user_func($callback, $data);
    }
}

// OtherClass 类定义
class OtherClass {
    public $var = 'Hello World';
}
?>
    <?php
// 两个类的对象
$myclass = new MyClass;
$otherclass = new OtherClass;

// 致命错误:第一个参数必须是 OtherClass 类的一个对象
$myclass->test('hello');

// 致命错误:第一个参数必须为 OtherClass 类的一个实例
$foo = new stdClass;
$myclass->test($foo);

// 致命错误:第一个参数不能为 null
$myclass->test(null);

// 正确:输出 Hello World 
$myclass->test($otherclass);

// 致命错误:第一个参数必须为数组
$myclass->test_array('a string');

// 正确:输出数组
$myclass->test_array(array('a', 'b', 'c'));

// 正确:输出 ArrayObject
$myclass->test_interface(new ArrayObject(array()));

// 正确:输出 int(1)
$myclass->test_callable('var_dump', 1);
?>
字符串Heredoc&Nowdoc

[TOC]

heredoc 句法结构

heredoc 句法结构:<<<。

  1. 在该运算符之后要提供一个标识符,然后换行。接下来是字符串 string 本身,最后要用前面定义的标识符作为结束标志
    结束时所1. 引用的标识符必须在该行的第一列,而且,标识符的命名也要像其它标签一样遵守 PHP 的规则:只能包含字母、数字和下划线,并且必须以字母和下划线作为开头。

    <<<EOT:学名:定界符
    <?php
        class foo {
            public $bar = <<<EOT
            这里是字符本身
        EOT;
        }
    

Nowdoc 结构

  1. Nowdoc 结构是类似于单引号字符串的。
  2. Nowdoc 结构很象 heredoc 结构,但是 nowdoc 中不进行解析操作。
  3. 这种结构很适合用于嵌入 PHP 代码或其它大段文本而无需对其中的特殊字符进行转义。与 SGML 的 <![CDATA[ ]]> 结构是用来声明大段的不用解析的文本类似,nowdoc 结构也有相同的特征。
  4. 一个 nowdoc 结构也用和 heredocs 结构一样的标记 <<<, 但是跟在后面的标识符要用单引号括起来,即 <<<'EOT'。
  5. Heredoc 结构的所有规则也同样适用于 nowdoc 结构,尤其是结束标识符的规则。

        <?php
         $str = <<<'EOD'
                字符串本身
        EOD;
    
生成器

[TOC]

  1. 一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。
  2. 当一个生成器被调用的时候,它返回一个可以被遍历的对象.当你遍历这个对象的时候(例如通过一个foreach循环),PHP 将会在每次需要值的时候调用生成器函数,并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。
  3. 一旦不再需要产生更多的值,生成器函数可以简单退出,而调用生成器的代码还可以继续执行,就像一个数组已经被遍历完了。

yield

生成器函数的核心是yield关键字。它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并终止函数的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。

    <?php
    function gen_one_to_three() {
        for ($i = 1; $i <= 3; $i++) {
            //注意变量$i的值在不同的yield之间是保持传递的。
            yield $i;
        }
    }
    
    $generator = gen_one_to_three();
    foreach ($generator as $value) {
        echo "$value\n";
    }
    ?>
输出:
1
2
3
Iterator(迭代器)(待补充)

看到 预定义接口

安全
过滤器

[TOC]

什么是 PHP 过滤器?

  1. PHP 过滤器用于验证和过滤来自非安全来源的数据。
  2. 测试、验证和过滤用户输入或自定义数据是任何 Web 应用程序的重要组成部分。
  3. PHP 的过滤器扩展的设计目的是使数据过滤更轻松快捷。

    过滤函数

    filter_var() - 通过一个指定的过滤器来过滤单一的变量

    filter_var_array() - 通过相同的或不同的过滤器来过滤多个变量

    filter_input - 获取一个输入变量,并对它进行过滤

    filter_input_array - 获取多个输入变量,并通过相同的或不同的过滤器对它们进行过滤

交互

session

什么是session

Session直接翻译成中文比较困难,一般都译成时域。在计算机专业术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。以及如果需要的话,可能还有一定的操作空间。
session 是一种存储会话机制

工作原理

session的工作原理
(1)当一个session第一次被启用时,一个唯一的标识被存储于本地的cookie中。
(2)首先使用session_start()函数,PHP从session仓库中加载已经存储的session变量。
(3)当执行PHP脚本时,通过使用session_register()函数注册session变量。
(4)当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。

session 生命周期

  1. 服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效(见PHP垃圾回收机制)。
  2. php unset 方法。
  3. session是依赖COOKIE的,所有有时候,我们也会把它生命周期理解为会话
  4. 注:当禁用cookie时也是不能使用session的.

cookie

什么是cookie

Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。定义于 RFC2109 和 2965 中的都已废弃,最新取代的规范是 RFC6265 [1] 。(可以叫做浏览器缓存)
每个域名下面能够存储的cookie大小为4k

生命周期

如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了

PHP扩展库列表/归类.

Tip
参见 扩展库列表/归类.
具体查看https://cdn.jerryblog.cn/doc/php/res/funcref.html

OOP 变更日志

PHP 5 OOP 模型的变更将被记录在此。功能的描述与其他相关注意事项记录在了 OOP 5 文档之中。

5.5.0    增加: finally 来处理异常。
5.4.0    增加: traits。
5.4.0    已变更:如果一个抽象 类定义了构造函数的签名,它将必须被实现。
5.3.3    已变更: 命名空间 中和类同名的方法不再被作为 构造函数。这个变更不影响非命名空间中的类。
5.3.0    已变更:类实现接口的方法所具有的默认值不再需要和接口的默认值一致。
5.3.0    已变更: 现在它也能够通过一个变量来引用一个类(例如,echo $classname::constant;)。 这个变量的值不能是一个保留关键词(比如,self、parent 或 static)。
5.3.0    已变更: 如果重载方法被定义为 static 将导致一个 E_WARNING 级别的错误。 同时它也需要强制使用 public 的可见性。
5.3.0    已变更: 在 5.3.0 之前的版本,__autoload() 函数里抛出的异常不能被 catch 块结构捕获,并会导致一个致命错误。 现在在一个前提下 catch 块能够捕获 __autoload 函数中抛出的错误。如果抛出一个自定义异常,这个自定义异常的类必须是可用的。否则 __autoload 函数可能递归自动加载这个自定义异常类。
5.3.0    新增: __callStatic 方法。
5.3.0    新增: heredoc 和 nowdoc 支持类的 常量 和属性的定义。 注意:heredoc 值必须和双引号字符串遵循同样的规则(比如,变量将被替换)。
5.3.0    新增: 后期静态绑定。
5.3.0    新增: __invoke 方法。
5.2.0    已变更:__toString 方法仅在直接与 echo 或 print 使用时被调用。但是现在它能在任何字符串上下文被调用(比如在 printf() 中使用 %s ),但不是在其他类型的上下文被调用(例如 %d 修饰符)。 自 PHP 5.2.0 起,将不具有 __toString 方法的对象转化为字符串将导致一个 E_RECOVERABLE_ERROR 级别的错误。
5.1.3    已变更:在 PHP 5 之前的版本,var 的使用已被废弃,并将产生一个 E_STRICT 级别的错误。现在它不再被废弃,因此也不会产生错误。
5.1.0    已变更:现在 __set_state 静态方法在 var_export() 导出类时会被调用。
5.1.0    新增:__isset 和 __unset 方法。

mysql

mysql百万级索引性能优化

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like ‘%abc%’
若要提高效率,可以考虑全文检索。
7. 如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)=’abc’–name以abc开头的id
select id from t where datediff(day,createdate,’2005-11-30′)=0–‘2005-11-30’生成的id
应改为:
select id from t where name like ‘abc%’
select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′
10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
12.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(…)
13.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
15. 索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
27. 与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
29.尽量避免大事务操作,提高系统并发能力。
30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

  建议调整下面几个关键参数以获得较好的性能
1、选择Percona或MariaDB版本的话,强烈建议启用thread pool特性,可使得在高并发的情况下,性能不会发生大幅下降。此外,还有extra_port功能,非常实用, 关键时刻能救命的。还有另外一个重要特色是 QUERY_RESPONSE_TIME 功能,也能使我们对整体的SQL响应时间分布有直观感受;
2、设置default-storage-engine=InnoDB,也就是默认采用InnoDB引擎,强烈建议不要再使用MyISAM引擎了,InnoDB引擎绝对可以满足99%以上的业务场景;
3、调整innodb_buffer_pool_size大小,如果是单实例且绝大多数是InnoDB引擎表的话,可考虑设置为物理内存的50% ~ 70%左右;
4、根据实际需要设置innodb_flush_log_at_trx_commit、sync_binlog的值。如果要求数据不能丢失,那么两个都设为1。如果允许丢失一点数据,则可分别设为2和10。而如果完全不用care数据是否丢失的话(例如在slave上,反正大不了重做一次),则可都设为0。这三种设置值导致数据库的性能受到影响程度分别是:高、中、低,也就是第一个会另数据库最慢,最后一个则相反;
5、设置innodb_file_per_table = 1,使用独立表空间,我实在是想不出来用共享表空间有什么好处了;
6、设置innodb_data_file_path = ibdata1:1G:autoextend,千万不要用默认的10M,否则在有高并发事务时,会受到不小的影响;
7、设置innodb_log_file_size=256M,设置innodb_log_files_in_group=2,基本可满足90%以上的场景;
8、设置long_query_time = 1,而在5.5版本以上,已经可以设置为小于1了,建议设置为0.05(50毫秒),记录那些执行较慢的SQL,用于后续的分析排查;
9、根据业务实际需要,适当调整max_connection(最大连接数)、max_connection_error(最大错误数,建议设置为10万以上,而open_files_limit、innodb_open_files、table_open_cache、table_definition_cache这几个参数则可设为约10倍于max_connection的大小;
10、常见的误区是把tmp_table_size和max_heap_table_size设置的比较大,曾经见过设置为1G的,这2个选项是每个连接会话都会分配的,因此不要设置过大,否则容易导致OOM发生;其他的一些连接会话级选项例如:sort_buffer_size、join_buffer_size、read_buffer_size、read_rnd_buffer_size等,也需要注意不能设置过大;
11、由于已经建议不再使用MyISAM引擎了,因此可以把key_buffer_size设置为32M左右,并且强烈建议关闭query cache功能;



下面列举了几个常见有助于提升MySQL效率的Schema设计规范及SQL使用建议:
1、所有的InnoDB表都设计一个无业务用途的自增列做主键,对于绝大多数场景都是如此,真正纯只读用InnoDB表的并不多,真如此的话还不如用TokuDB来得划算;
2、字段长度满足需求前提下,尽可能选择长度小的。此外,字段属性尽量都加上NOT NULL约束,可一定程度提高性能;
3、尽可能不使用TEXT/BLOB类型,确实需要的话,建议拆分到子表中,不要和主表放在一起,避免SELECT * 的时候读性能太差。
4、读取数据时,只选取所需要的列,不要每次都SELECT *,避免产生严重的随机读问题,尤其是读到一些TEXT/BLOB列;
5、对一个VARCHAR(N)列创建索引时,通常取其50%(甚至更小)左右长度创建前缀索引就足以满足80%以上的查询需求了,没必要创建整列的全长度索引;
6、通常情况下,子查询的性能比较差,建议改造成JOIN写法;
7、多表联接查询时,关联字段类型尽量一致,并且都要有索引;
8、多表连接查询时,把结果集小的表(注意,这里是指过滤后的结果集,不一定是全表数据量小的)作为驱动表;
9、多表联接并且有排序时,排序字段必须是驱动表里的,否则排序列无法用到索引;
10、多用复合索引,少用多个独立索引,尤其是一些基数(Cardinality)太小(比如说,该列的唯一值总数少于255)的列就不要创建独立索引了;
11、类似分页功能的SQL,建议先用主键关联,然后返回结果集,效率会高很多;



关于MySQL的管理维护的其他建议有:
1、通常地,单表物理大小不超过10GB,单表行数不超过1亿条,行平均长度不超过8KB,如果机器性能足够,这些数据量MySQL是完全能处理的过来的,不用担心性能问题,这么建议主要是考虑ONLINE DDL的代价较高;
2、不用太担心mysqld进程占用太多内存,只要不发生OOM kill和用到大量的SWAP都还好;
3、在以往,单机上跑多实例的目的是能最大化利用计算资源,如果单实例已经能耗尽大部分计算资源的话,就没必要再跑多实例了;
4、定期使用pt-duplicate-key-checker检查并删除重复的索引。定期使用pt-index-usage工具检查并删除使用频率很低的索引;
5、定期采集slow query log,用pt-query-digest工具进行分析,可结合Anemometer系统进行slow query管理以便分析slow query并进行后续优化工作;
6、可使用pt-kill杀掉超长时间的SQL请求,Percona版本中有个选项 innodb_kill_idle_transaction 也可实现该功能;
7、使用pt-online-schema-change来完成大表的ONLINE DDL需求;
8、定期使用pt-table-checksum、pt-table-sync来检查并修复mysql主从复制的数据差异;

待补充MYSQL优化

## 常用的一些MYSQL优化

  1. EXPLAIN 你的 SELECT 查询
    使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。
  2. 当只要一行数据时使用 LIMIT 1
  3. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
  4. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
  5. 应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
  6. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描
  7. in 和 not in 也要慎用,否则会导致全表扫描,如
  8. 对于连续的数值,能用 between 就不要用 in 了
  9. 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引
    千万不要 ORDER BY RAND()想打乱返回的数据行?随机挑一个数据?真不知道谁发明了这种用法,但很多新手很喜欢这样用。但你确不了解这样做有多么可怕的性能问题。(php 可以用函数 shuffle()打乱处理)
  10. 避免使用 SELECT *
  11. 选择正确的存储引擎

    在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊
    MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
    InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
  12. 选择数据类型只要遵循小而简单的原则就好,越小的数据类型通常会更快,占用更少的磁盘、内存,处理时需要的CPU周期也更少。越简单的数据类型在计算时需要更少的CPU周期,比如,整型就比字符操作代价低,因而会使用整型来存储ip地址,使用DATETIME来存储时间,而不是使用字符串。
  13. 小心“永久链接” “永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了,它会永远处在连接的状态,就算是数据库操作已经结束了。而且,自从我们的Apache开始重用它的子进程后——也就是说,下一次的HTTP请求会重用Apache的子进程,并重用相同的 MySQL 链接。
  14. 不建议使用%前缀模糊查询,例如LIKE “%name”或者LIKE “%name%”,这种查询会导致索引失效而进行全表扫描。但是可以使用LIKE “name%”。

优化的几个容易理解错误技巧

几个可能容易理解错误的技巧:

  1. 通常来说把可为NULL的列改为NOT NULL不会对性能提升有多少帮助,只是如果计划在列上创建索引,就应该将该列设置为NOT NULL。
  2. 对整数类型指定宽度,比如INT(11),没有任何卵用。INT使用32位(4个字节)存储空间,那么它的表示范围已经确定,所以INT(1)和INT(20)对于存储和计算是相同的。
  3. UNSIGNED表示不允许负值,大致可以使正数的上限提高一倍。比如TINYINT存储范围是-128 ~ 127,而UNSIGNED TINYINT存储的范围却是0 - 255。
  4. 通常来讲,没有太大的必要使用DECIMAL数据类型。即使是在需要存储财务数据时,仍然可以使用BIGINT。比如需要精确到万分之一,那么可以将数据乘以一百万然后使用BIGINT存储。这样可以避免浮点数计算不准确和DECIMAL精确计算代价高的问题。
  5. TIMESTAMP使用4个字节存储空间,DATETIME使用8个字节存储空间。因而,TIMESTAMP只能表示1970 - 2038年,比DATETIME表示的范围小得多,而且TIMESTAMP的值因时区不同而不同。
  6. 大多数情况下没有使用枚举类型的必要,其中一个缺点是枚举的字符串列表是固定的,添加和删除字符串(枚举选项)必须使用ALTER TABLE(如果只只是在列表末尾追加元素,不需要重建表)。
  7. schema的列不要太多。原因是存储引擎的API工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列,这个转换过程的代价是非常高的。如果列太多而实际使用的列又很少的话,有可能会导致CPU占用过高。
  8. 大表ALTER TABLE非常耗时,MySQL执行大部分修改表结果操作的方法是用新的结构创建一个张空表,从旧表中查出所有的数据插入新表,然后再删除旧表。尤其当内存不足而表又很大,而且还有很大索引的情况下,耗时更久。当然有一些奇技淫巧可以解决这个问题,有兴趣可自行查阅。

框架

TP3.2和TP5区别及改变

来源官方手册 https://www.kancloud.cn/thinkphp/thinkphp5_quickstart/499708

5.0版本和之前版本的差异较大,本篇对熟悉3.2版本的用户给出了一些5.0的主要区别。

URL和路由

5.0的URL访问不再支持普通URL模式,路由也不支持正则路由定义,而是全部改为规则路由配合变量规则(正则定义)的方式:

主要改进如下;

  • 增加路由变量规则;
  • 增加组合变量支持;
  • 增加资源路由;
  • 增加路由分组;
  • 增加闭包定义支持;
  • 增加MISS路由定义;
  • 支持URL路由规则反解析;

请求对象和响应对象

5.0新增了请求对象Request和响应对象ResponseRequest统一处理请求和获取请求信息,Response对象负责输出客户端或者浏览器响应。

模块和控制器

控制器的命名空间有所调整,并且可以无需继承任何的控制器类。

  • 应用命名空间统一为app(可定义)而不是模块名;
  • 控制器的类名默认不带Controller后缀,可以配置开启use_controller_suffix参数启用控制器类后缀;
  • 控制器操作方法采用return方式返回数据 而非直接输出;
  • 废除原来的操作前后置方法;
  • 增加beforeActionList属性定义前置操作;
  • 支持任意层次的控制器定义和访问;
  • URL访问支持自动定位控制器;

数据库

5.0的数据库查询功能增强,原先需要通过模型才能使用的链式查询可以直接通过Db类调用,原来的M函数调用可以改用db函数,例如:

3.2版本

M('User')->where(['name'=>'thinkphp'])->find();

5.0版本

db('User')->where('name','thinkphp')->find();

主要改进如下:

  • 支持链式查询操作;
  • 数据查询支持返回对象、数组和PDOStatement对象;
  • 数据集查询支持返回数组和Collection对象;
  • 增加查询构造器,查询语法改变;
  • 支持闭包查询;
  • 支持分块查询;
  • 支持视图查询;
  • 增加SQL监听事件;

模型

5.0的模型变化是最大的,基本上模型是完全面向对象的概念,包括关联模型,模型类的后缀不再带Model,直接由命名空间区分,原来的D函数调用改为model函数,并且必须创建对应的模型类,例如:

3.2版本

D('User')->where(['name'=>'thinkphp'])->find();

5.0版本

model('User')->where('name','thinkphp')->find();

主要改进包括:

  • 重构关联模型;
  • 支持聚合模型;
  • 废除视图模型(改为数据库的视图查询方法);
  • 模型的扩展采用Trait机制;
  • 增加获取器和修改器;
  • 增加时间戳自动写入;
  • 增加类型字段转换;
  • 数组访问支持;
  • JSON序列化支持;

自动验证和自动完成

5.0的数据自动验证和自动完成和3.2版本区别较大,5.0的数据验证采用验证器定义并且通过think\Validate类进行统一的验证。自动完成则通过在模型里面定义修改器来完成。

异常

5.0对错误零容忍,默认情况下会对任何级别的错误抛出异常(但可以在应用公共文件中设置错误级别),并且重新设计了异常页面,展示了详尽的错误信息,便于调试。

调试和日志

5.0的页面Trace强化,支持浏览器控制台查看Trace信息。

5.0的日志驱动增加Socket方式,采用SocketLog支持远程调试。

常量

5.0版本废弃了原来的大部分常量定义,仅仅保留了框架的路径常量定义,其余的常量可以使用App类或者Request类的相关属性或者方法来完成,或者自己重新定义需要的常量。

废除的常量包括:

REQUEST_METHOD IS_GET IS_POST IS_PUT IS_DELETE IS_AJAX __EXT__ COMMON_MODULE MODULE_NAME CONTROLLER_NAME ACTION_NAME APP_NAMESPACE APP_DEBUG MODULE_PATH

函数

5.0版本核心框架不依赖任何自定义函数,但仍然封装了一些常用功能到助手函数,你可以随意重新定义或者增加助手函数。

待补充Laravel和THINKPHP区别
ThinkPHP5开发的正确姿势

安装篇

  1. 使用composer,既然是趋势就早日拥抱,能写PHP的这点工具用不来说不过去(另外官方的所有扩展都会以composer方式提供);
  2. 如果只需要核心单独安装核心框架就行了,应用仓库并非必须;
  3. 如果你安装的是dev-mastercomposer更新的也是开发版,如果安装的是正式版那么更新的也是最新的正式版(就和Chrome的开发版和正式版一样);
  4. 把web根目录指向public目录而不是根目录;
  5. 资源文件不要放到public目录以外;
  6. TP5完美支持PHP7,不要以为基于PHP7写的框架才会支持PHP7;
  7. 如果你的环境是PHP7,你的应用中完全可以使用PHP7的特性;
  8. 不要使用普通URL模式访问;
  9. TP5正常运行需要PHP5.4+,建议版本为PHP5.6+
  10. 每次升级请务必参考官方手册提供的升级指导;

变量篇

  1. 避免直接获取系统变量,用Request对象的相关方法替代;
  2. 不要管get还是post请求,统一用param方法获取当前请求(任何请求类型)变量;
  3. 不要直接操作改变当前请求的系统变量;
  4. 使用操作方法的参数绑定功能,而不是自己手动获取请求参数;
  5. 使用依赖注入(TP5的依赖注入非常的简单);
  6. 对于一些请求用到的公共属性可以使用Request属性注入;
  7. 用Request类的getInput方法替代file_get_contents('php://input')
  8. 模板中输出系统变量使用{$Request.param.name}的方式;
  9. 多使用Request类的onlyexcept方法获取多个请求变量;
  10. 不要直接操作$_SESSION变量;
  11. 任何变量必须事先定义才能操作或者赋值给模板;

路由篇

  1. 用动态注册方法而不是路由配置;
  2. 不要在路由配置文件之外定义路由;
  3. get/post/delete/put等路由注册方法明确指定请求类型;
  4. 保证路由变量和操作方法的参数绑定命名一致(包括可选);
  5. 路由地址保持和实际的控制器名和方法名一致(包括大小写);
  6. 为每个路由变量明确指定变量规则;
  7. 用路由分组简化路由定义和公共参数;
  8. 尽可能使用强制路由并配合MISS路由;
  9. 优先考虑资源路由尤其是API开发的时候;
  10. 考虑在路由后置行为中进行统一的权限检测;
  11. 部署后记得执行路由缓存指令;
  12. 了解下路由的请求缓存对你会有帮助;

控制器篇

  1. 建议开启controller_suffix配置参数,并采用IndexController命名控制器类;
  2. 原则上控制器类不需要继承think\Controller
  3. 给你的控制器类继承一个公共的基类例如Base便于统一调整;
  4. 需要的话在你的基础控制器类中引入traits\controller\Jump
  5. API开发尽量使用资源控制器(命令行php think create:controller 可以快速生成);
  6. 控制器类中避免写太多的业务逻辑,交由模型类完成;
  7. 尽量避免直接操作数据库类,而是在模型类中做好封装;
  8. 可能的话尽量在控制器层完成数据验证;
  9. 不要试图在初始化方法中调用redirect助手函数,而用$this->redirect方法替代;
  10. 始终在控制器方法中return而不是echo以免影响请求缓存;
  11. jsonview以及redirect助手函数进行响应输出;
  12. abort助手函数抛出HTTP异常;
  13. 遵循驼峰法命名你的控制器类和文件名;
  14. 永远不要在操作方法中(事实上是任何代码中)使用exit

数据库篇

  1. 千万不要用驼峰法命名数据表和字段;
  2. 如非必要避免直接操作Db类;
  3. 用Db类的name方法而不是table方法;
  4. 用视图查询view方法替代join方法;
  5. 查询操作尽可能的使用field方法,哪怕是field(true)
  6. 如果要批量执行SQL语句使用batchQuery方法;
  7. value方法获取单个记录的某个字段值;
  8. column方法获多条记录的某个(或者某些)字段值;
  9. 灵活使用cache方法进行查询缓存处理和删除(不仅是查询可以用cache方法);
  10. 使用fetchSql方法直接返回sql语句而不实际执行CURD;
  11. 部署之后记得执行命令行的php think optimize:schema指令;
  12. strict方法可以避免多余的数据字段抛出异常;
  13. 关于日期和时间的查询不妨试试whereTime方法;
  14. 数据库的大多数操作都是自动参数绑定的,一般情况下无需手动使用bind方法;
  15. insert方法返回的是影响的记录数而不是主键;
  16. 使用insertGetId方法插入数据并返回主键;
  17. delete(true)可以无条件的删除数据;
  18. selectfind方法支持闭包,但尽量不要和链式操作混用;
  19. 需要查询大量数据并且分批处理的话使用chunk方法;
  20. 对find方法使用主键查询并且cache(true)的话缓存是自动更新的;

模型篇(上)

  1. 不要以为模型性能比Db差,这点差别还不抵不过一条SQL查询,而带来的便利是可观的;
  2. 模型的好处千言万语抵不过两个字:对象(明白人都会懂);
  3. 模型类一般直接继承think\Model,如有必要也可以继承一个公共模型基类;
  4. 如果你的模型类没有任何的数据库操作的话不需要继承任何类库;
  5. 模型类不需要使用类后缀Model(对应前面的控制器类后缀);
  6. 模型的save方法既可以新增也可以更新(而且是自动识别);
  7. 模型没有链式操作,所有链式操作都是调用的数据库类Db;
  8. 模型支持事件而数据库类的操作不支持事件;
  9. 统一在模型的init方法(静态方法)中注册模型事件;
  10. 模型没有数据表前缀的概念只有对应数据表(完整表名)的概念;
  11. 每个模型对应一个数据库查询对象Query,彼此独立;
  12. 每个模型可以单独定义自己的数据库连接信息;
  13. 模型名不一定就是数据表名,而且可以单独定义数据表名称;
  14. 模型查询的数据返回永远都是当前模型对象实例(而不是数组,Db类查询才是数组);
  15. 模型对象可以直接进行数组操作并不需要使用toArray转换(包括模板输出);

模型篇(下)

  1. 模型的查询操作建议使用getall方法(静态方法);
  2. 要在模型查询中使用链式查询可以定义查询范围或者使用闭包;
  3. save方法新增数据的返回值是影响的记录数而不是主键值,获取主键直接获取当前模型对象的属性值即可;
  4. 如果仅仅是需要主键之外的查询条件的话,可以在get或者all方法的第一个参数使用数组;
  5. 要模型查询后的原始数据可以使用getData方法;
  6. 模型的关联操作可以让你省去很多的关联查询;
  7. 鉴于性能考虑,关联预载入查询绝对是关联查询的首选;
  8. 软删除必须使用模型的delete方法(而不是数据库类的delete)才有效;
  9. 不要在修改器中修改多个属性;
  10. 修改器是模型才有的功能,调用数据库Db类的写入操作方法是不会触发的;
  11. 不要在同一个模型实例中多次调用save新增数据,一旦新增数据成功后,再次save就是更新数据了,除非你显式调用isUpdate(false)
  12. 用模型事件取代自动完成;

其它篇

  1. 开发过程中开启调试模式,部署后记得关闭;
  2. 如果不是API开发的话开启页面Trace显示;
  3. 不要轻易忽视异常页面的任何信息,它们不是摆设;
  4. 开发中一定要严格注意大小写,这是基本素质;
  5. 如果是接口开发尝试使用postman进行调试;
  6. 使用命名空间和自动加载,避免直接requireinclude
  7. 不建议使用importvendor方法;
  8. 应用目录下面的common.php(注意不是command.php)可以添加应用的函数,并且实时生效;
  9. 不要手动下载扩展包放入vendor目录,不支持composer安装的扩展类库直接放入extend
  10. 只要是使用命名空间的第三方类库,都是可以直接在TP5下面使用的;
  11. 尽可能的采用MVVM设计架构来替代MVC架构,充分发挥TP5的API优势;
  12. 如果使用模板,避免在模板中使用过多的数据逻辑;
  13. 模板继承和模板布局是可以配合使用的;
概念篇:ThinkPHP5名词解释

MVC、MVP和MVVM

基本概念参考这篇MVC,MVP 和 MVVM 模式如何选择?,已经说的比较清楚了。

由于ThinkPHP5在整体的架构上是拥抱MVVM的,因此在模板引擎方面并没有特别改进,但同样满足MVCMVP模式开发。

命名空间

命名空间是学习ThinkPHP5的必备基础,用一句话说就是:把类、函数、变量 等放到逻辑子文件夹中去,以避免命名冲突。关于命名空间的解释可以看这篇文章,讲的比较通俗易懂。

Composer

Composer是PHP的依赖关系管理工具,对原有的开发模式和类库扩展机制是一种颠覆。原本你无论是下载还是GIT获取,一般都只能手动更新,而无法做到对依赖类库的自动更新(虽然Git可以很方便更新,但仍然无法完成依赖更新),composer提供了一种全新的安装和更新方式,目前主流框架和类库都已经支持composer安装方式了,使用简单的命令行操作就可以安装和更新类库,需要PHP5.3.2+版本,支持Linux和Windows平台。

Composer还提供了一个自动加载的入口文件,用于实现composer依赖安装的类库自动加载。ThinkPHP5并没有使用Composer的自动加载入口,而是自己封装了对Composer类库的自动加载支持。

由于composer的访问都在国外,因此国内的安装和更新速度有影响,不过可以使用国内镜像。

入口文件

和大多数主流框架一样,ThinkPHP5采用单一入口(一般而言就是我们经常看到的index.php文件,通过URL重写可以隐藏)进行URL或者接口访问,这个文件我们就称之为应用入口文件(在ThinkPHP5中也是唯一开放对外访问的程序文件),但你仍然可以增加新的入口文件,例如admin.phpapi.php等入口文件,主要用于绑定某个模块或者使用特殊的命令行操作等。

模块/控制器/操作

ThinkPHP5的最小访问单元是操作,而每个操作其实就是一个控制器类的公共方法,模块在ThinkPHP5里面并没有实际的意义,仅仅是用于控制器类的命名空间区分,或者说是一些控制器的聚合,并且支持模块单独的配置参数。所以ThinkPHP5是允许单一模块(其实是没有模块的概念了)应用存在的。

路由

路由是用于规划(一般同时也会进行简化)请求的访问地址,在访问地址和实际操作方法之间建立一个路由规则 => 路由地址的映射关系。

ThinkPHP5并非强制使用路由,如果没有定义路由,则可以直接使用“模块/控制器/操作”的方式访问,如果定义了路由,则该路由对应的路由地址就被不能直接访问了。一旦开启强制路由参数,则必须为每个请求定义路由(包括首页)。

使用路由有一定的性能损失,但随之也更加安全,因为每个路由都有自己的生效条件,如果不满足条件的请求是被过滤的。你远比你在控制器的操作中进行各种判断要实用的多。

HTTP协议

HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则。使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求信息和服务,HTTP1.1协议是一种无状态的协议,无状态是指Web浏览器和Web服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后Web服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息,HTTP2.0做了很多的改进,但尚未普及。

HTTP遵循请求(Request)/应答(Response)模型。Web浏览器向Web服务器发送请求,Web服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。

请求(Request

这里的请求是指HTTP请求,一个HTTP请求信息由3部分组成:

  • 第一行是请求方法URI协议/版本
  • 第二部分是请求头(Request Header)
  • 第三部分是请求内容正文

请求头和内容之间用空行隔开,如果是GET或者HEAD请求的话,是不包含请求内容的,在ThinkPHP5中,使用think\Request对象来统一获取请求数据。

响应(Reponse

这里的响应指的是HTTP响应,HTTP响应也由3个部分构成:

  • 第一行是协议状态版本代码描述
  • 第二行开始是响应头(Response Header)
  • 第三部分是响应内容正文

响应头和响应正文之间用空行隔开,在ThinkPHP5中,使用think\Response对象完成请求响应操作。

请求类型

HTTP支持的请求类型有很多,常用的类型及作用如下:

请求类型描述
GET通过请求URI得到资源
POST用于添加新的资源
PUT用于修改某个资源
PATCH修改资源的部分内容
DELETE删除某个资源
OPTIONS询问可以执行哪些方法
HEAD类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据

HTTP状态码

HTTP状态码也称为应答码,它反映了Web服务器处理HTTP请求状态。HTTP应答码由3位数字构成,其中首位数字定义了应答码的类型:

  • 1XX-信息类:表示收到Web浏览器请求,正在进一步的处理中;
  • 2XX-成功类:表示用户请求被正确接收,理解和处理例如:200 OK;
  • 3XX-重定向类:表示请求没有成功,客户必须采取进一步的动作,如 301重定向;
  • 4XX-客户端错误:表示客户端提交的请求有错误 例如:404 NOT Found,意味着请求中所引用的文档不存在;
  • 5XX-服务器错误:表示服务器不能完成对请求的处理:如 500;

对于Web开发人员来说掌握HTTP应答码有助于提高Web应用程序调试的效率和准确性,在接口开发的时候也应该养成返回和判断正确的状态码的习惯。

RESTFul

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

REST (英文:Representational State Transfer,资源表现层转化)指的是一组架构约束条件和原则,满足这些约束条件和原则的应用程序或设计就是 RESTful。

所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。

"资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。

URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。

数据库和模型

ThinkPHP内置实现了数据库抽象访问层,并通过Db类进行统一数据操作。而模型则是基于数据库操作而进行的数据和业务封装,采用对象化的方式更直观和方便进行数据及逻辑操作。

数据库Db类访问的数据类型一般而言是数组类型,而模型操作返回的数据是模型的对象实例,模型比数据库操作增加了更多的数据自动处理操作,包括修改器和获取器等等,并且具备事件和关联机制,完成数据库Db类不能或者较难完成的操作。

ORM

ORM(Object-Relational Mapping 对象关系映射)提供了概念性的、易于理解的模型化数据的方法,用于实现面向对象编程语言里面不同类型系统的数据之间的转换。ORM方法论基于三个核心原则:

  • 简单:以最基本的形式建模数据。
  • 传达性:数据库结构被任何人都能理解的语言文档化。
  • 精确性:基于数据模型创建正确标准化的结构。

ORM提供的不只是描述不同对象间关系的一个简单而直接的方式,还提供了灵活性。使用ORM创建的模型比使用其它方法创建的模型更有能力适应系统的变化,数据模型能自动映射到正确标准化的数据库结构。

ThinkPHP的ORM使得查询数据变得非常的简单。

ActiveRecord

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

Active Record 本身的设计适合非常简单的领域需求,对于复杂的模型尤其是模型关联缺少足够的支持,但ThinkPHP5的模型操作对于模型关联也提供了强有力的支持。

闭包

闭包也就是PHP5.3开始引入的匿名函数,允许创建一个没有名称的函数,并且支持函数参数以及引用外部变量,ThinkPHP5很多功能可以支持闭包功能来简化代码,尤其是在路由定义和数据查询中经常被用到,例如:

return [
    // 使用闭包定义路由
    'hello/[:name]' => function ($name) {
        return 'Hello,' . $name . '!';
    },
];

查询中使用闭包:

$users = User::all(function ($query)  use($id,$name){
    $query->where('name', 'like', $name)
        ->where('id', '>', $id)
        ->limit(10);
});

行为和钩子

ThinkPHP中的行为是一个比较抽象的概念,你可以把行为想象成在应用执行过程中的一个动作。在框架的执行流程中,例如路由检测是一个行为,静态缓存是一个行为,用户权限检测也是行为,大到业务逻辑,小到浏览器检测、多语言检测等等都可以当做是一个行为,甚至说你希望给你的网站用户的第一次访问弹出Hello,world!这些都可以看成是一种行为,把这些行为抽离出来的目的是为了让你无需改动框架和应用,而在外围通过扩展或者配置来改变或者增加一些功能。

而不同的行为之间也具有位置共同性,比如,有些行为的作用位置都是在应用执行前,有些行为都是在模板输出之后,我们把这些行为发生作用的位置称之为钩子,当应用程序运行到这个钩子的时候,就会被拦截下来,统一执行相关的行为,类似于AOP编程中的“切面”的概念,给某一个钩子绑定相关行为就成了一种类AOP编程的思想。

一个钩子可以注册多个行为,执行到某个钩子位置后,会按照注册的顺序依次执行相关的行为。但在某些特殊的情况下,你可以设置某个钩子只能执行一次行为,又或者你可以在一个钩子的某个行为中返回false来强制终止后续的行为执行;一个行为可以同时注册到多个不同的钩子上,完全看应用的需求来设计。

事件

ThinkPHP5中的事件一般是指数据库操作和模型操作在完成数据写入之后的回调机制。

数据库操作的回调也称为查询事件,是针对数据库的CURD操作而设计的回调方法,主要包括:

事件描述
before_selectselect查询前回调
before_findfind查询前回调
after_insertinsert操作成功后回调
after_updateupdate操作成功后回调
after_deletedelete操作成功后回调

模型事件可以看成是模型层的钩子和行为,只不过钩子的位置主要针对模型数据的写入操作,包含下面这些:

钩子对应操作快捷注册方法
before_insert新增前beforeInsert
after_insert新增后afterInsert
before_update更新前beforeUpdate
after_update更新后afterUpdate
before_write写入前beforeWrite
after_write写入后afterWrite
before_delete删除前beforeDelete
after_delete删除后afterDelete

before_writeafter_write表示无论是新增还是更新都会执行的钩子。

依赖注入

在软件工程领域,依赖注入(Dependency Injection,简称DI)是用于实现控制反转(Inversion of Control,简称IoC)的最常见的方式之一,而控制反转的目的是为了更好的解耦。

ThinkPHP5的依赖注入主要指针对访问控制器的依赖注入,实现方式主要包括架构函数注入和操作方法注入,表现方式则是在控制器架构函数和操作方法中一旦对参数进行对象类型约束则会自动触发依赖注入(再通俗点说就是自动实例化该对象),由于访问控制器的参数都来自于URL请求,普通变量就是通过参数绑定自动获取,对象变量则是通过依赖注入生成。

Trait

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

ThinkPHP5中的Trait主要用于模型和控制器功能的扩展和复用。

请求缓存

ThinkPHP5默认内置了请求缓存功能,该功能的设计初衷就是减少频繁的相同请求的服务器开销,提高性能。其原理是一旦开启请求缓存后(可以是单个请求,也可以是全局请求),第一次请求完成后(而且必须是一个成功请求)会把响应数据通过一个唯一的缓存标识缓存起来并发送HTTP缓存,下一次请求的时候如果是相同的缓存标识会判断是否存在HTTP缓存如果存在则直接读取浏览器缓存数据,如果没有HTTP缓存则直接读取响应缓存内容而不需要调用真正的请求,不过请求缓存仅对GET请求有效。

获取器

获取器的作用是对模型的数据对象的(原始)数据做出自动处理。一个获取器对应模型的一个特殊方法,方法格式为:

getFieldNameAttr

FieldName为数据表字段的驼峰转换,定义了获取器之后会在下列情况自动触发:

  • 模型的数据对象取值操作($model->field_name);
  • 模型的序列化输出操作($model->toArray());
  • 显式调用getAttr方法($this->getAttr('field_name'));

获取器的场景包括:

  • 时间日期字段的格式化输出;
  • 集合或枚举类型的输出;
  • 数字状态字段的输出;
  • 组合字段的输出;

修改器

和获取器相反,修改器的主要作用是对模型设置的数据对象值进行处理。修改器也是在模型中定义的一个特殊方法,方法的命名规范为:

setFieldNameAttr

修改器的使用场景和读取器类似:

  • 时间日期字段的转换写入;
  • 集合或枚举类型的写入;
  • 数字状态字段的写入;
  • 某个字段涉及其它字段的条件或者组合写入;

定义了修改器之后会在下列情况下触发:

  • 模型对象赋值;
  • 调用模型的data方法,并且第二个参数传入true
  • 调用模型的save方法,并且传入数据;
  • 显式调用模型的setAttr方法;
  • 定义了该字段的自动完成;

验证器

验证器对于一个验证需求和场景的统一封装,验证的数据字段和验证规则都定义在验证器里面,然后可以在控制器或者模型中调用验证器进行实际的验证,改变验证规则或者增加验证字段不需要修改控制器和模型的验证代码。

待补充PHP5和PHP7区别及特性

以下转载至https://blog.csdn.net/li_xue_zhao/article/details/79800877

1、php标量类型和返回类型声明

#主要分为两种模式,强制性模式和严格模式
declare(strict_types=1)
#1表示严格类型校验模式,作用于函数调用和返回语句;0表示弱类型校验模式。123

2、NULL合并运算符

$site = isset($_GET['site']) ? $_GET['site'] : 'wo';
#简写成
$site = $_GET['site'] ??'wo';123

3、组合预算符

// 整型比较
print( 1 <=> 1);print(PHP_EOL);
print( 1 <=> 2);print(PHP_EOL);
print( 2 <=> 1);print(PHP_EOL);
print(PHP_EOL); // PHP_EOL 为换行符
//结果:
0
-1
1
12345678910

4、常量数组

// 使用 define 函数来定义数组
define('sites', [
   'Google',
   'Jser',
   'Taobao'
]);

print(sites[1]);12345678

5、匿名类

interface Logger { 
   public function log(string $msg); 
} 

class Application { 
   private $logger; 

   public function getLogger(): Logger { 
      return $this->logger; 
   } 

   public function setLogger(Logger $logger) { 
      $this->logger = $logger; 
   }   
} 

$app = new Application; 
// 使用 new class 创建匿名类 
$app->setLogger(new class implements Logger { 
   public function log(string $msg) { 
      print($msg); 
   } 
}); 

$app->getLogger()->log("我的第一条日志"); 12345678910111213141516171819202122232425

6、Closure::call()方法增加,意思向类绑定个匿名函数

<?php 
class A { 
    private $x = 1; 
} 

// PHP 7 之前版本定义闭包函数代码 
$getXCB = function() { 
    return $this->x; 
}; 

// 闭包函数绑定到类 A 上 
$getX = $getXCB->bindTo(new A, 'A');  

echo $getX(); 
print(PHP_EOL); 

// PHP 7+ 代码 
$getX = function() { 
    return $this->x; 
}; 
echo $getX->call(new A); 
?>

7、CSPRNG(伪随机数产生器)。

PHP 7 通过引入几个 CSPRNG 函数提供一种简单的机制来生成密码学上强壮的随机数。

random_bytes() - 加密生存被保护的伪随机字符串。

random_int() - 加密生存被保护的伪随机整数。12345

8、异常

PHP 7 异常用于向下兼容及增强旧的assert()函数。
12

9、use 语句改变

#可以导入同一个namespace下的类简写
use some\namespace\{ClassA, ClassB, ClassC as C};12

10、Session 选项

1.session_start()可以定义数组
<?php
session_start([
   'cache_limiter' => 'private',
   'read_and_close' => true,
]);
?>
2.引入了一个新的php.ini设置(session.lazy_write),默认情况下设置为 true,意味着session数据只在发生变化时才写入。

11、PHP 7 移除的扩展

ereg

mssql

mysql

sybase_ct

123456789

为什么 PHP7 比 PHP5 性能提升了?

1、变量存储字节减小,减少内存占用,提升变量操作速度

2、改善数组结构,数组元素和hash映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率

3、改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率

Composer

开发一套自已的框架!

Composer建立第一个Packagist

[TOC]

中国镜像 https://pkg.phpcomposer.com/
包管理 https://packagist.org/packages/submit

安装参考 composer 官网

新建项目

创建composer.json

$ composer init

  Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [administrator/sys]: framwork/sys
Description []: system core
Author [Jerry <502443279@qq.com>, n to skip]:
Minimum Stability []: dev
Package Type (e.g. library, project, metapackage, composer-plugin) []: project
License []: MIT

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]? no
Would you like to define your dev dependencies (require-dev) interactively [yes]? no

{
    "name": "framwork/sys",
    "description": "system core",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "Jerry",
            "email": "502443279@qq.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {}
}

Do you confirm generation [yes]? yew
 Please answer yes, y, no, or n.
Do you confirm generation [yes]? yes

创建文件

了解,熟悉
laravel

Laravel 作为现在最流行的 PHP 框架,其中的知识较多,所以单独拿出来写一篇。

  • 简述 Laravel 的生命周期

Laravel 采用了单一入口模式,应用的所有请求入口都是 public/index.php 文件。

  1. 注册类文件自动加载器 : Laravel通过 composer 进行依赖管理,无需开发者手动导入各种类文件,而由自动加载器自行导入。
  2. 创建服务容器:从 bootstrap/app.php 文件中取得 Laravel 应用实例 $app (服务容器)
  3. 创建 HTTP / Console 内核:传入的请求会被发送给 HTTP 内核或者 console 内核进行处理
  4. 载入服务提供者至容器:
    在内核引导启动的过程中最重要的动作之一就是载入服务提供者到你的应用,服务提供者负责引导启动框架的全部各种组件,例如数据库、队列、验证器以及路由组件。
  5. 分发请求:一旦应用完成引导和所有服务提供者都注册完成,Request 将会移交给路由进行分发。路由将分发请求给一个路由或控制器,同时运行路由指定的中间件
  • 服务提供者是什么?
服务提供者是所有 Laravel 应用程序引导启动的中心, Laravel 的核心服务器、注册服务容器绑定、事件监听、中间件、路由注册以及我们的应用程序都是由服务提供者引导启动的。
  • IoC 容器是什么?

IoC(Inversion of Control)译为 「控制反转」,也被叫做「依赖注入」(DI)。什么是「控制反转」?对象 A 功能依赖于对象 B,但是控制权由对象 A 来控制,控制权被颠倒,所以叫做「控制反转」,而「依赖注入」是实现 IoC 的方法,就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中。

其作用简单来讲就是利用依赖关系注入的方式,把复杂的应用程序分解为互相合作的对象,从而降低解决问题的复杂度,实现应用程序代码的低耦合、高扩展。

Laravel 中的服务容器是用于管理类的依赖和执行依赖注入的工具。

  • Facades 是什么?
Facades(一种设计模式,通常翻译为外观模式)提供了一个"static"(静态)接口去访问注册到 IoC 容器中的类。提供了简单、易记的语法,而无需记住必须手动注入或配置的长长的类名。此外,由于对 PHP 动态方法的独特用法,也使测试起来非常容易。
  • Contract 是什么?
Contract(契约)是 laravel 定义框架提供的核心服务的接口。Contract 和 Facades 并没有本质意义上的区别,其作用就是使接口低耦合、更简单。
  • 依赖注入的原理?
这个不解释,这是理解 IoC 容器的前提。
  • 谈谈 Laravel 和 YII 框架的区别
  1. 在 YII 框架中的路由是通过书写 Controller、Action 间接定义路由,而 Laravel 中是在 route 路由文件中直接定义路由入口
  2. Laravel 提供 ORM 对象关系映射,使读写数据库的操作更加简单
  3. Laravel 提供更多的 Artisan 命令和脚手架开发
  4. Laravel 的 Composer 扩展包比 Yii 框架更多,开发更加高效
swoole
windows 安装swoole环境
官网有现成的cywin环境包,直接下载来后就可以用。但php版本最新的是7.1 ,很多框架都是7.2+所有要另外搭个
1.在官网下载cywin包
下载地址:http://www.cygwin.com/
2.安装必要的组件 pecl(或者PECL,有时候小写搜索不到),libpcre-devel,autoconf,gcc-obj,gcc-bojc++,gdb,libc++-devl,libpcre-devel,libpcre2-devel,php,php-bz2,php-curl,php-devel,php-json,php-mbstring,php-mysqli,php-pdo_mysql,php-sockets,make,gcc-core,wget
psr代码规范

来源

Psr 0-4 代码规范,来源于 PHP-FIG 网址 :www.php-fig.org3

 介绍

名称介绍
PSR-0 (Autoloading Standard)自动加载标准
PSR-1 (Basic Coding Standard)基础编码标准
PSR-2 (Coding Style Guide)编码风格向导
PSR-3 (Logger Interface)记录器接口(日志接口)
PSR-4 (Improved Autoloading)自动加载的增强版,可以替换掉PSR-0
PSR-0

自动加载标准

地址:https://www.php-fig.org/psr/psr-0/

PSR-0

在2014年10月21日PSR-0已被标记为过时。PSR-4现在推荐作为替代(不推荐使用)。

一个完全合格的namespace和class必须符合这样的结构:“\< Vendor Name>(< Namespace>)*< Class Name>”

文件路径:/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
命名空间:namespace \Doctrine\Common
调用:\Doctrine\Common\IsolatedClassLoader

每个namespace必须有一个顶层的namespace("Vendor Name"提供者名字)

每个namespace可以有多个子namespace

当从文件系统中加载时,每个namespace的分隔符(/)要转换成 DIRECTORY_SEPARATOR(操作系统路径分隔符)

命名空间是 \Doctrine\Common\IsolatedClassLoader
但实际路径是 Doctrine/Common/IsolatedClassLoader.php
分隔符是反过来的

在类名中,每个下划线(_)符号要转换成DIRECTORY_SEPARATOR(操作系统路径分隔符)。在namespace中,下划线(_)符号是没有(特殊)意义的。

\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php

当从文件系统中载入时,合格的namespace和class一定是以 .php 结尾的

还有个.php3的扩展。具体是啥有兴趣的可以查下

verdor name,namespaces,class名可以由大小写字母组合而成(大小写敏感的)

可以用驼峰,但是要区分大小写。windows 下面可能能用,但LINUX 就不行!
PSR-1

基础编码标准

地址:https://www.php-fig.org/psr/psr-1/

PSR-1

PHP源文件必须只使用 <?php 和 <?= 这两种标签。

不要使用短标签 <?=?>
另外,PHP开发有4种开发风格,在php.ini中配置
1.xml风格(标准风格推荐使用)
    <?php
    echo"这是xml风格的标记";
    ?>
2.脚本分格
    <script languange="php">
    echo'这是脚本风格的标记';
    </script>
3.简短风格
    <?这是简短风格的标记;?>
4.asp风格
    <%
    echo'这是asp风格的标记';
    %>

源文件中php代码的编码格式必须是不带字节顺序标记(BOM)的UTF-8。

HTML如果带BOM头,顶部会出现一个高度。。。
php如果带BOM头,也会出现一些奇怪的问题,所以,不要用Windows下的text文本编辑器保存文件。使用专业的IDE开发。

一个源文件建议只用来做声明(类(class),函数(function),常量(constant)等)或者只用来做一些引起副作用的操作(例如:输出信息,修改.ini配置等),但不建议同时做这两件事。

就是配置的文件和CLASS文件分格,不要写在一起 ,代码看起来更简洁,不会看起来乱。后台维护也好维护
ini_set('error_reporting', E_ALL); 这个就是配置文件

class className{
    function fo(){
    
    }

}

命名空间(namespace)和类(class) 必须遵守PSR-0标准。

类名(class name) 必须使用骆驼式(StudlyCaps)写法 (注:驼峰式(cameCase)的一种变种,后文将直接用StudlyCaps表示)。

骆驼式:其实就是大驼峰
驼峰式:小驼峰

类(class)中的常量必须只由大写字母和下划线(_)组成。

define("APP_NAME",'testApp');
常量统一用大写,这个基本好像所有的语言都是这样规定的,没什么好说的!

方法名(method name) 必须使用驼峰式(cameCase)写法。

PSR-2

编码风格向导(约束代码风格)

地址:https://www.php-fig.org/psr/psr-2/

PSR-2

概述

  • 代码必须遵循PSR [ PSR-1 ]。
  • 代码必须使用4个空格来缩进,不能使用制表符。
  • 线长绝不能有硬性限制;软限制必须为120个字符;每行不得超过80个字符。(意思是一行不要太长,如果超过80个字符就应该换行了)
  • namespace声明后必须有一个空白行,use声明块后必须有一个空白行。
  • 类的开括号必须在下一行,闭括号必须在正文之后的下一行。
  • 方法的左括号必须在下一行,而右括号必须在正文之后的下一行。
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{

}
  • 必须在所有属性和方法上声明可见性;abstract并且 final必须在可见性之前声明;static必须在可见性之后声明。
final public static function bar()
    {
        // method body
    }
  • 控制结构关键字必须在其后有一个空格;方法和函数调用绝不能。(eg : if 结构)
  • 控制结构的开括号必须在同一行上,闭括号必须在主体之后的下一行上。
  • 控制结构的开括号必须在其后没有空格,控制结构的闭括号必须在其前没有空格。

            if ($a === $b) {
                bar();
            } elseif ($a > $b) {
                $foo->bar($arg1);
            } else {
                BazClass::bar($arg2, $arg3);
            }
  • PHP 关键字必须小写/PHP常量true,false和null必须小写。
PSR-3

记录器接口(日志接口)

地址:https://www.php-fig.org/psr/psr-3/

PSR-3

基础

  • 该LoggerInterface自曝八种方法来写日志八个 RFC 5424倍的水平(调试,信息,通知,警告,错误,严重警告,紧急)
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}
  • 第九种方法log接受日志级别作为第一个参数。用日志级别常量之一调用此方法必须具有与调用特定于级别的方法相同的结果。Psr\Log\InvalidArgumentException 如果实现不知道该级别,则以该规范未定义的级别调用此方法务必抛出。用户不应在不知道当前实现是否支持的情况下使用自定义级别。
PSR-4

自动加载标准

地址:https://www.php-fig.org/psr/psr-4/

PSR-4

PSR-4规它也是规范 自动加载(autoload)的,是对PSR-0的修改,属于补充规范,

主要有以下几点:

  • 废除了PSR-0中_就是目录分割符的写法,_下划线在完全限定类名中是没有特殊含义了。
  • 类文件名要以 .php 结尾。

    • 类名必须要和对应的文件名要一模一样,大小写也要一模一样。
开发笔记
保存远程图片
/**
 * [save_img 保存远程图片]
 * @Author   Jerry
 * @DateTime 2018-03-19T13:51:02+0800
 * @Example  eg:
 * @return   [type]                   [description]
 */
function save_img($url,$path='/public/uploads/images/'){
    if(empty($url)){  
        return false;  
    }  
          //获取图片信息大小  
    $imgSize = getImageSize($url);  
    if(!in_array($imgSize['mime'],array('image/jpg', 'image/gif', 'image/png', 'image/jpeg'),true)){  
        return false;  
    }  
     //获取后缀名  
    $_mime = explode('/', $imgSize['mime']);  
    $_ext = '.'.end($_mime);  
    $fileName = pathinfo($url, PATHINFO_BASENAME);
      //开始攫取  
    ob_start();  
    readfile($url);  
    $imgInfo = ob_get_contents();  
    ob_end_clean();  
  
    if(!file_exists($path)){  
        mkdir($path,0777,true);  
    }  
    $fp = fopen($path.$fileName, 'a');  
    $imgLen = strlen($imgInfo);    //计算图片源码大小  
    $_inx = 1024;   //每次写入1k  
    $_time = ceil($imgLen/$_inx);  
    for($i=0; $i<$_time; $i++){  
        fwrite($fp,substr($imgInfo, $i*$_inx, $_inx));  
    }  
    fclose($fp);  
  
    return array($path.$fileName);  
}
php 判断http还是https,以及获得当前url的方法
php 奇葩问题 ob_clean() MARK一下(输出的JSON数据前面有个小红点)

今天,做做接口交互 的时,遇到了一个奇葩问题。两段一样的JSON文件,一个是可以执行的,另一个就是没办法执。Json报 Unexpected token

两段JSON如下:

##返出有问题的JSON{    "test": "test",    "msg": "test",    "data": "str"}##手动输出的JSON{    "test": "test",    "msg": "test",    "data": "str"}

测试了好久。后面在输出前加ob_clean()解决此问题 ,特别MARK一下

PHP开发过程,常见问题和解决方法

<p>======PHP开发过程,常见问题和解决方法,留给自已===</p>

<p> </p>

<p>1,操作SQL时报“General error: 2006 MySQL server has gone away”错</p>

<p>    SET GLOBAL  max_allowed_packet=67108864; (临时解决方法)</p>

<p>    长久更改,需要更改SQL配置项my.cnf</p>

<p> </p>

<p> </p>

CTRL+ENTER提交数据
PHP打印常量
<?php// PHP打印所有常量print_r(get_defined_constants());/输出类似Array(    [E_ERROR] => 1    [E_RECOVERABLE_ERROR] => 4096    [E_WARNING] => 2    [E_PARSE] => 4    [E_NOTICE] => 8    [E_STRICT] => 2048    [E_DEPRECATED] => 8192    [E_CORE_ERROR] => 16    [E_CORE_WARNING] => 32    [E_COMPILE_ERROR] => 64    [E_COMPILE_WARNING] => 128    [E_USER_ERROR] => 256    [E_USER_WARNING] => 512    [E_USER_NOTICE] => 1024    [E_USER_DEPRECATED] => 16384    [E_ALL] => 30719    … …)/?>

get_defined_constants() e.g #2:
打印用户自定义常量:

<?php// 打印用户自定义常量define("CONSTANTS","php-print-constants");$user_constants = get_defined_constants(TRUE);print_r($user_constants[‘user’]);/输出类似Array(    [CONSTANTS] => php-print-constants    [PATH] => /home/qiufeng/)/?>
php结合redis实现高并发下的抢购、秒杀功能

<p>抢购、秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:
1 高并发对数据库产生的压力
2 竞争状态下如何解决库存的正确减少("超卖"问题)
对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis。
重点在于第二个问题
 </p>
<p>常规写法:</p>
<p>查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数</p>
<p> </p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre><?<span style="color:#000000">php
</span><span style="color:#800080">$conn</span>=<span style="color:#008080">mysql_connect</span>("localhost","big","123456"<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#800080">$conn</span><span style="color:#000000">){

</span><span style="color:#0000ff">echo</span> "connect failed"<span style="color:#000000">;  
</span><span style="color:#0000ff">exit</span><span style="color:#000000">;  

}
</span><span style="color:#008080">mysql_select_db</span>("big",<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#008080">mysql_query</span>("set names utf8"<span style="color:#000000">);

</span><span style="color:#800080">$price</span>=10<span style="color:#000000">;
</span><span style="color:#800080">$user_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$goods_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$sku_id</span>=11<span style="color:#000000">;
</span><span style="color:#800080">$number</span>=1<span style="color:#000000">;

</span><span style="color:#008000">//</span><span style="color:#008000">生成唯一订单</span>
<span style="color:#0000ff">function</span><span style="color:#000000"> build_order_no(){

</span><span style="color:#0000ff">return</span> <span style="color:#008080">date</span>('ymd').<span style="color:#008080">substr</span>(<span style="color:#008080">implode</span>(<span style="color:#0000ff">NULL</span>, <span style="color:#008080">array_map</span>('ord', <span style="color:#008080">str_split</span>(<span style="color:#008080">substr</span>(<span style="color:#008080">uniqid</span>(), 7, 13), 1))), 0, 8<span style="color:#000000">);

}
</span><span style="color:#008000">//</span><span style="color:#008000">记录日志</span>
<span style="color:#0000ff">function</span> insertLog(<span style="color:#800080">$event</span>,<span style="color:#800080">$type</span>=0<span style="color:#000000">){

</span><span style="color:#0000ff">global</span> <span style="color:#800080">$conn</span><span style="color:#000000">;
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_log(event,type) 
values('</span><span style="color:#800080">$event</span>','<span style="color:#800080">$type</span>')"<span style="color:#000000">;  
</span><span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  

}

</span><span style="color:#008000">//</span><span style="color:#008000">模拟下单操作
//库存是否大于0</span>
<span style="color:#800080">$sql</span>="select number from ih_store where goods_id='<span style="color:#800080">$goods_id</span>' and sku_id='<span style="color:#800080">$sku_id</span>'";<span style="color:#008000">//</span><span style="color:#008000">解锁 此时ih_store数据中goods_id='$goods_id' and sku_id='$sku_id' 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行</span>
<span style="color:#800080">$rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#800080">$row</span>=<span style="color:#008080">mysql_fetch_assoc</span>(<span style="color:#800080">$rs</span><span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(<span style="color:#800080">$row</span>['number']>0){<span style="color:#008000">//</span><span style="color:#008000">高并发下会导致超卖</span>

<span style="color:#800080">$order_sn</span>=<span style="color:#000000">build_order_no();
</span><span style="color:#008000">//</span><span style="color:#008000">生成订单  </span>
<span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
values('</span><span style="color:#800080">$order_sn</span>','<span style="color:#800080">$user_id</span>','<span style="color:#800080">$goods_id</span>','<span style="color:#800080">$sku_id</span>','<span style="color:#800080">$price</span>')"<span style="color:#000000">;  
</span><span style="color:#800080">$order_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">); 

</span><span style="color:#008000">//</span><span style="color:#008000">库存减少</span>
<span style="color:#800080">$sql</span>="update ih_store set number=number-{<span style="color:#800080">$number</span>} where sku_id='<span style="color:#800080">$sku_id</span>'"<span style="color:#000000">;
</span><span style="color:#800080">$store_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  
</span><span style="color:#0000ff">if</span>(<span style="color:#008080">mysql_affected_rows</span><span style="color:#000000">()){  
    insertLog(</span>'库存减少成功'<span style="color:#000000">);
}</span><span style="color:#0000ff">else</span><span style="color:#000000">{  
    insertLog(</span>'库存减少失败'<span style="color:#000000">);
} 

}</span><span style="color:#0000ff">else</span><span style="color:#000000">{

insertLog(</span>'库存不够'<span style="color:#000000">);

}
</span>?></pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<p>优化方案1:将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false</p>
<pre><span style="color:#008000">//</span><span style="color:#008000">库存减少</span>
<span style="color:#800080">$sql</span>="update ih_store set number=number-{<span style="color:#800080">$number</span>} where sku_id='<span style="color:#800080">$sku_id</span>' and number>0"<span style="color:#000000">;
</span><span style="color:#800080">$store_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(<span style="color:#008080">mysql_affected_rows</span><span style="color:#000000">()){

insertLog(</span>'库存减少成功'<span style="color:#000000">);

}</span></pre>
<p>优化方案2:使用mysql的事务,锁住操作的行</p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre><?<span style="color:#000000">php
</span><span style="color:#800080">$conn</span>=<span style="color:#008080">mysql_connect</span>("localhost","big","123456"<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#800080">$conn</span><span style="color:#000000">){

</span><span style="color:#0000ff">echo</span> "connect failed"<span style="color:#000000">;  
</span><span style="color:#0000ff">exit</span><span style="color:#000000">;  

}
</span><span style="color:#008080">mysql_select_db</span>("big",<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#008080">mysql_query</span>("set names utf8"<span style="color:#000000">);

</span><span style="color:#800080">$price</span>=10<span style="color:#000000">;
</span><span style="color:#800080">$user_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$goods_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$sku_id</span>=11<span style="color:#000000">;
</span><span style="color:#800080">$number</span>=1<span style="color:#000000">;

</span><span style="color:#008000">//</span><span style="color:#008000">生成唯一订单号</span>
<span style="color:#0000ff">function</span><span style="color:#000000"> build_order_no(){

</span><span style="color:#0000ff">return</span> <span style="color:#008080">date</span>('ymd').<span style="color:#008080">substr</span>(<span style="color:#008080">implode</span>(<span style="color:#0000ff">NULL</span>, <span style="color:#008080">array_map</span>('ord', <span style="color:#008080">str_split</span>(<span style="color:#008080">substr</span>(<span style="color:#008080">uniqid</span>(), 7, 13), 1))), 0, 8<span style="color:#000000">);

}
</span><span style="color:#008000">//</span><span style="color:#008000">记录日志</span>
<span style="color:#0000ff">function</span> insertLog(<span style="color:#800080">$event</span>,<span style="color:#800080">$type</span>=0<span style="color:#000000">){

</span><span style="color:#0000ff">global</span> <span style="color:#800080">$conn</span><span style="color:#000000">;
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_log(event,type) 
values('</span><span style="color:#800080">$event</span>','<span style="color:#800080">$type</span>')"<span style="color:#000000">;  
</span><span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  

}

</span><span style="color:#008000">//</span><span style="color:#008000">模拟下单操作
//库存是否大于0</span>
<span style="color:#008080">mysql_query</span>("BEGIN"); <span style="color:#008000">//</span><span style="color:#008000">开始事务</span>
<span style="color:#800080">$sql</span>="select number from ih_store where goods_id='<span style="color:#800080">$goods_id</span>' and sku_id='<span style="color:#800080">$sku_id</span>' FOR UPDATE";<span style="color:#008000">//</span><span style="color:#008000">此时这条记录被锁住,其它事务必须等待此次事务提交后才能执行</span>
<span style="color:#800080">$rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#800080">$row</span>=<span style="color:#008080">mysql_fetch_assoc</span>(<span style="color:#800080">$rs</span><span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(<span style="color:#800080">$row</span>['number']>0<span style="color:#000000">){

</span><span style="color:#008000">//</span><span style="color:#008000">生成订单 </span>
<span style="color:#800080">$order_sn</span>=<span style="color:#000000">build_order_no();    
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
values('</span><span style="color:#800080">$order_sn</span>','<span style="color:#800080">$user_id</span>','<span style="color:#800080">$goods_id</span>','<span style="color:#800080">$sku_id</span>','<span style="color:#800080">$price</span>')"<span style="color:#000000">;  
</span><span style="color:#800080">$order_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">); 

</span><span style="color:#008000">//</span><span style="color:#008000">库存减少</span>
<span style="color:#800080">$sql</span>="update ih_store set number=number-{<span style="color:#800080">$number</span>} where sku_id='<span style="color:#800080">$sku_id</span>'"<span style="color:#000000">;
</span><span style="color:#800080">$store_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  
</span><span style="color:#0000ff">if</span>(<span style="color:#008080">mysql_affected_rows</span><span style="color:#000000">()){  
    insertLog(</span>'库存减少成功'<span style="color:#000000">);
    </span><span style="color:#008080">mysql_query</span>("COMMIT");<span style="color:#008000">//</span><span style="color:#008000">事务提交即解锁</span>
}<span style="color:#0000ff">else</span><span style="color:#000000">{  
    insertLog(</span>'库存减少失败'<span style="color:#000000">);
}

}</span><span style="color:#0000ff">else</span><span style="color:#000000">{

insertLog(</span>'库存不够'<span style="color:#000000">);
</span><span style="color:#008080">mysql_query</span>("ROLLBACK"<span style="color:#000000">);

}
</span>?></pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<p>优化方案3:使用非阻塞的文件排他锁</p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre><?<span style="color:#000000">php
</span><span style="color:#800080">$conn</span>=<span style="color:#008080">mysql_connect</span>("localhost","root","123456"<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#800080">$conn</span><span style="color:#000000">){

</span><span style="color:#0000ff">echo</span> "connect failed"<span style="color:#000000">;  
</span><span style="color:#0000ff">exit</span><span style="color:#000000">;  

}
</span><span style="color:#008080">mysql_select_db</span>("big-bak",<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#008080">mysql_query</span>("set names utf8"<span style="color:#000000">);

</span><span style="color:#800080">$price</span>=10<span style="color:#000000">;
</span><span style="color:#800080">$user_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$goods_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$sku_id</span>=11<span style="color:#000000">;
</span><span style="color:#800080">$number</span>=1<span style="color:#000000">;

</span><span style="color:#008000">//</span><span style="color:#008000">生成唯一订单号</span>
<span style="color:#0000ff">function</span><span style="color:#000000"> build_order_no(){

</span><span style="color:#0000ff">return</span> <span style="color:#008080">date</span>('ymd').<span style="color:#008080">substr</span>(<span style="color:#008080">implode</span>(<span style="color:#0000ff">NULL</span>, <span style="color:#008080">array_map</span>('ord', <span style="color:#008080">str_split</span>(<span style="color:#008080">substr</span>(<span style="color:#008080">uniqid</span>(), 7, 13), 1))), 0, 8<span style="color:#000000">);

}
</span><span style="color:#008000">//</span><span style="color:#008000">记录日志</span>
<span style="color:#0000ff">function</span> insertLog(<span style="color:#800080">$event</span>,<span style="color:#800080">$type</span>=0<span style="color:#000000">){

</span><span style="color:#0000ff">global</span> <span style="color:#800080">$conn</span><span style="color:#000000">;
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_log(event,type) 
values('</span><span style="color:#800080">$event</span>','<span style="color:#800080">$type</span>')"<span style="color:#000000">;  
</span><span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  

}

</span><span style="color:#800080">$fp</span> = <span style="color:#008080">fopen</span>("lock.txt", "w+"<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#008080">flock</span>(<span style="color:#800080">$fp</span>,LOCK_EX |<span style="color:#000000"> LOCK_NB)){

</span><span style="color:#0000ff">echo</span> "系统繁忙,请稍后再试"<span style="color:#000000">;
</span><span style="color:#0000ff">return</span><span style="color:#000000">;

}
</span><span style="color:#008000">//</span><span style="color:#008000">下单</span>
<span style="color:#800080">$sql</span>="select number from ih_store where goods_id='<span style="color:#800080">$goods_id</span>' and sku_id='<span style="color:#800080">$sku_id</span>'"<span style="color:#000000">;
</span><span style="color:#800080">$rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#800080">$row</span>=<span style="color:#008080">mysql_fetch_assoc</span>(<span style="color:#800080">$rs</span><span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(<span style="color:#800080">$row</span>['number']>0){<span style="color:#008000">//</span><span style="color:#008000">库存是否大于0

//模拟下单操作 </span>
<span style="color:#800080">$order_sn</span>=<span style="color:#000000">build_order_no();    
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_order(order_sn,user_id,goods_id,sku_id,price) 
values('</span><span style="color:#800080">$order_sn</span>','<span style="color:#800080">$user_id</span>','<span style="color:#800080">$goods_id</span>','<span style="color:#800080">$sku_id</span>','<span style="color:#800080">$price</span>')"<span style="color:#000000">;  
</span><span style="color:#800080">$order_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">); 

</span><span style="color:#008000">//</span><span style="color:#008000">库存减少</span>
<span style="color:#800080">$sql</span>="update ih_store set number=number-{<span style="color:#800080">$number</span>} where sku_id='<span style="color:#800080">$sku_id</span>'"<span style="color:#000000">;
</span><span style="color:#800080">$store_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  
</span><span style="color:#0000ff">if</span>(<span style="color:#008080">mysql_affected_rows</span><span style="color:#000000">()){  
    insertLog(</span>'库存减少成功'<span style="color:#000000">);
    </span><span style="color:#008080">flock</span>(<span style="color:#800080">$fp</span>,LOCK_UN);<span style="color:#008000">//</span><span style="color:#008000">释放锁</span>
}<span style="color:#0000ff">else</span><span style="color:#000000">{  
    insertLog(</span>'库存减少失败'<span style="color:#000000">);
} 

}</span><span style="color:#0000ff">else</span><span style="color:#000000">{

insertLog(</span>'库存不够'<span style="color:#000000">);

}
</span><span style="color:#008080">fclose</span>(<span style="color:#800080">$fp</span>);</pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<p>优化方案4:使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是)</p>
<p> </p>
<p>先将商品库存如队列</p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre><?<span style="color:#000000">php
</span><span style="color:#800080">$store</span>=1000<span style="color:#000000">;
</span><span style="color:#800080">$redis</span>=<span style="color:#0000ff">new</span><span style="color:#000000"> Redis();
</span><span style="color:#800080">$result</span>=<span style="color:#800080">$redis</span>->connect('127.0.0.1',6379<span style="color:#000000">);
</span><span style="color:#800080">$res</span>=<span style="color:#800080">$redis</span>->llen('goods_store'<span style="color:#000000">);
</span><span style="color:#0000ff">echo</span> <span style="color:#800080">$res</span><span style="color:#000000">;
</span><span style="color:#800080">$count</span>=<span style="color:#800080">$store</span>-<span style="color:#800080">$res</span><span style="color:#000000">;
</span><span style="color:#0000ff">for</span>(<span style="color:#800080">$i</span>=0;<span style="color:#800080">$i</span><<span style="color:#800080">$count</span>;<span style="color:#800080">$i</span>++<span style="color:#000000">){

</span><span style="color:#800080">$redis</span>-&gt;lpush('goods_store',1<span style="color:#000000">);

}
</span><span style="color:#0000ff">echo</span> <span style="color:#800080">$redis</span>->llen('goods_store'<span style="color:#000000">);
</span>?></pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<p>抢购、描述逻辑</p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre><?<span style="color:#000000">php
</span><span style="color:#800080">$conn</span>=<span style="color:#008080">mysql_connect</span>("localhost","big","123456"<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#800080">$conn</span><span style="color:#000000">){

</span><span style="color:#0000ff">echo</span> "connect failed"<span style="color:#000000">;  
</span><span style="color:#0000ff">exit</span><span style="color:#000000">;  

}
</span><span style="color:#008080">mysql_select_db</span>("big",<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#008080">mysql_query</span>("set names utf8"<span style="color:#000000">);

</span><span style="color:#800080">$price</span>=10<span style="color:#000000">;
</span><span style="color:#800080">$user_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$goods_id</span>=1<span style="color:#000000">;
</span><span style="color:#800080">$sku_id</span>=11<span style="color:#000000">;
</span><span style="color:#800080">$number</span>=1<span style="color:#000000">;

</span><span style="color:#008000">//</span><span style="color:#008000">生成唯一订单号</span>
<span style="color:#0000ff">function</span><span style="color:#000000"> build_order_no(){

</span><span style="color:#0000ff">return</span> <span style="color:#008080">date</span>('ymd').<span style="color:#008080">substr</span>(<span style="color:#008080">implode</span>(<span style="color:#0000ff">NULL</span>, <span style="color:#008080">array_map</span>('ord', <span style="color:#008080">str_split</span>(<span style="color:#008080">substr</span>(<span style="color:#008080">uniqid</span>(), 7, 13), 1))), 0, 8<span style="color:#000000">);

}
</span><span style="color:#008000">//</span><span style="color:#008000">记录日志</span>
<span style="color:#0000ff">function</span> insertLog(<span style="color:#800080">$event</span>,<span style="color:#800080">$type</span>=0<span style="color:#000000">){

</span><span style="color:#0000ff">global</span> <span style="color:#800080">$conn</span><span style="color:#000000">;
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_log(event,type) 
values('</span><span style="color:#800080">$event</span>','<span style="color:#800080">$type</span>')"<span style="color:#000000">;  
</span><span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);  

}

</span><span style="color:#008000">//</span><span style="color:#008000">模拟下单操作
//下单前判断redis队列库存量</span>
<span style="color:#800080">$redis</span>=<span style="color:#0000ff">new</span><span style="color:#000000"> Redis();
</span><span style="color:#800080">$result</span>=<span style="color:#800080">$redis</span>->connect('127.0.0.1',6379<span style="color:#000000">);
</span><span style="color:#800080">$count</span>=<span style="color:#800080">$redis</span>->lpop('goods_store'<span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(!<span style="color:#800080">$count</span><span style="color:#000000">){

insertLog(</span>'error:no store redis'<span style="color:#000000">);
</span><span style="color:#0000ff">return</span><span style="color:#000000">;

}

</span><span style="color:#008000">//</span><span style="color:#008000">生成订单 </span>
<span style="color:#800080">$order_sn</span>=<span style="color:#000000">build_order_no();
</span><span style="color:#800080">$sql</span>="<span style="color:#000000">insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
values('</span><span style="color:#800080">$order_sn</span>','<span style="color:#800080">$user_id</span>','<span style="color:#800080">$goods_id</span>','<span style="color:#800080">$sku_id</span>','<span style="color:#800080">$price</span>')"<span style="color:#000000">;
</span><span style="color:#800080">$order_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);

</span><span style="color:#008000">//</span><span style="color:#008000">库存减少</span>
<span style="color:#800080">$sql</span>="update ih_store set number=number-{<span style="color:#800080">$number</span>} where sku_id='<span style="color:#800080">$sku_id</span>'"<span style="color:#000000">;
</span><span style="color:#800080">$store_rs</span>=<span style="color:#008080">mysql_query</span>(<span style="color:#800080">$sql</span>,<span style="color:#800080">$conn</span><span style="color:#000000">);
</span><span style="color:#0000ff">if</span>(<span style="color:#008080">mysql_affected_rows</span><span style="color:#000000">()){

insertLog(</span>'库存减少成功'<span style="color:#000000">);

}</span><span style="color:#0000ff">else</span><span style="color:#000000">{

insertLog(</span>'库存减少失败'<span style="color:#000000">);

} </span></pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<p>模拟5000高并发测试
webbench -c 5000 -t 60 http://192.168.1.198/big/index.php
ab -r -n 6000 -c 5000  http://192.168.1.198/big/index.php</p>
<p> </p>
<p> </p>
<p>上述只是简单模拟高并发下的抢购,真实场景要比这复杂很多,很多注意的地方
如抢购页面做成静态的,通过ajax调用接口
再如上面的会导致一个用户抢多个,思路:
需要一个排队队列和抢购结果队列及库存队列。高并发情况,先将用户进入排队队列,用一个线程循环处理从排队队列取出一个用户,判断用户是否已在抢购结果队列,如果在,则已抢购,否则未抢购,库存减1,写数据库,将用户入结果队列。</p>
<p> </p>
<p>测试数据表</p>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>
<pre>--
-- 数据库:<span style="color:#000000"> big
</span>--


--
--<span style="color:#000000"> 表的结构 ih_goods
</span>--<span style="color:#000000">

CREATE TABLE </span><span style="color:#0000ff">IF</span><span style="color:#000000"> NOT EXISTS ih_goods (
  goods_id int(</span>10) unsigned NOT <span style="color:#0000ff">NULL</span> AUTO_INCREMENT,<span style="color:#000000">
  cat_id int(</span>11) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
  goods_name varchar(</span>255) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
  PRIMARY </span><span style="color:#008080">KEY</span><span style="color:#000000"> (goods_id)
) ENGINE</span>=MyISAM  <span style="color:#0000ff">DEFAULT</span> CHARSET=utf8 AUTO_INCREMENT=2<span style="color:#000000"> ;

</span>--
--<span style="color:#000000"> 转存表中的数据 ih_goods
</span>--<span style="color:#000000">

INSERT INTO ih_goods (goods_id</span>, cat_id,<span style="color:#000000"> goods_name) VALUES
(</span>1, 0, '小米手机'<span style="color:#000000">);

</span>-- --------------------------------------------------------

--
--<span style="color:#000000"> 表的结构 ih_log
</span>--<span style="color:#000000">

CREATE TABLE </span><span style="color:#0000ff">IF</span><span style="color:#000000"> NOT EXISTS ih_log (
id int(</span>11) NOT <span style="color:#0000ff">NULL</span> AUTO_INCREMENT,<span style="color:#000000">
event varchar(</span>255) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
type tinyint(</span>4) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
addtime timestamp NOT </span><span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> CURRENT_TIMESTAMP,<span style="color:#000000">
PRIMARY </span><span style="color:#008080">KEY</span><span style="color:#000000"> (id)
) ENGINE</span>=MyISAM <span style="color:#0000ff">DEFAULT</span> CHARSET=utf8 AUTO_INCREMENT=1<span style="color:#000000"> ;

</span>--
--<span style="color:#000000"> 转存表中的数据 ih_log
</span>--


--
--<span style="color:#000000"> 表的结构 ih_order
</span>--<span style="color:#000000">

CREATE TABLE </span><span style="color:#0000ff">IF</span><span style="color:#000000"> NOT EXISTS ih_order (
id int(</span>11) NOT <span style="color:#0000ff">NULL</span> AUTO_INCREMENT,<span style="color:#000000">
order_sn char(</span>32) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
user_id int(</span>11) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
status int(</span>11) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
goods_id int(</span>11) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
sku_id int(</span>11) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
price </span><span style="color:#0000ff">float</span> NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
addtime timestamp NOT </span><span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> CURRENT_TIMESTAMP,<span style="color:#000000">
PRIMARY </span><span style="color:#008080">KEY</span><span style="color:#000000"> (id)
) ENGINE</span>=InnoDB <span style="color:#0000ff">DEFAULT</span> CHARSET=utf8 COMMENT='订单表' AUTO_INCREMENT=1<span style="color:#000000"> ;

</span>--
--<span style="color:#000000"> 转存表中的数据 ih_order
</span>--


--
--<span style="color:#000000"> 表的结构 ih_store
</span>--<span style="color:#000000">

CREATE TABLE </span><span style="color:#0000ff">IF</span><span style="color:#000000"> NOT EXISTS ih_store (
id int(</span>11) NOT <span style="color:#0000ff">NULL</span> AUTO_INCREMENT,<span style="color:#000000">
goods_id int(</span>11) NOT <span style="color:#0000ff">NULL</span>,<span style="color:#000000">
sku_id int(</span>10) unsigned NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
</span><span style="color:#0000ff">number</span> int(10) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0',<span style="color:#000000">
freez int(</span>11) NOT <span style="color:#0000ff">NULL</span> <span style="color:#0000ff">DEFAULT</span> '0' COMMENT '虚拟库存',<span style="color:#000000">
PRIMARY </span><span style="color:#008080">KEY</span><span style="color:#000000"> (id)
) ENGINE</span>=InnoDB <span style="color:#0000ff">DEFAULT</span> CHARSET=utf8 COMMENT='库存' AUTO_INCREMENT=2<span style="color:#000000"> ;

</span>--
--<span style="color:#000000"> 转存表中的数据 ih_store
</span>--<span style="color:#000000">

INSERT INTO ih_store (id</span>, goods_id, sku_id, <span style="color:#0000ff">number</span>,<span style="color:#000000"> freez) VALUES
(</span>1, 1, 11, 500, 0);</pre>
<p><img alt="复制代码" src="https://static.oschina.net/uploads/img/201703/22181016_VK18.gif"></p>

php系统类函数

<p><span style="color:#3366ff">PHP系统类函数</span></p>

<p><span style="color:#000000">assert函数:检查assertion声明是否错误

extension_loaded函数:检查PHP扩展是否加载

get_cfg_var函数:获取PHP配置选项的值

get_current_user函数:获取当前PHP脚本的所有者的名称

get_defined_constants函数:返回一个包含PHP预定义常量信息的数组

get_extension_funcs函数:返回一个包含指定模块中的所有函数名称的数组

get_include_path函数:返回当前配置的文件包含路径的信息

get_included_files函数:返回一个关于文件包含信息的数组

get_loaded_extensions函数:返回一个包含所有装载模块信息的数组

get_magic_quotes_gpc函数:获取magic_quotes_gpc的状态信息

get_magic_quotes_runtime函数:获取magic_quotes_ runtime的状态信息

get_required_files函数:返回一个关于文件包含信息的数组

getenv函数:获取PHP环境变量的值</span></p>

<p><span style="color:#3366ff">PHP系统类函数</span></p>

<p>getlastmod函数:获取当前PHP页面文件的最后修改时间

getmygid函数:获取当前PHP脚本页面所有者的GID号码

getmyinode函数:获取当前PHP脚本页面的INODE号码

getmypid函数:获取PHP的PID

getmyuid函数:获取PHP脚本页面所有者的UID号码

getopt函数:从命令行参数列表获取设置

getrusage函数:获取当前的资源语法

ini_get_all函数:获取所有配置选项

ini_get函数:获取配置选项的值

memory_get_usage函数:返回PHP脚本占用的内存空间

php_ini_scanned_files函数:返回配置文件目录下的配置文件列表

php_logo_guid函数:获取LOGO图片的GUID

php_sapi_name函数:获取PHP和Web服务器之间的接口类型

php_uname函数:获取PHP脚本运行的操作系统信息

phpcredits函数:打印credits列表

phpinfo函数:输出PHP的信息

phpversion函数:获取PHP版本

zend_logo_guid函数:获取ZEND的LOGO图片的GUID

zend_version函数:获取ZEND引擎的版本</p>

<p><span style="color:#3366ff">PHP配置类函数</span></p>

<p>assert_options函数:设置或者获取不同的声明标记

ini_alter函数:设置PHP配置选项的值

ini_restore函数:恢复配置选项的值

ini_set函数:设置PHP配置选项的值

putenv函数:设置环境变量

restore_include_path函数:恢复文件包含路径配置信息

set_include_path函数:设置文件包含路径配置选项

set_magic_quotes_runtime函数:设置magic_quotes运行时间

set_time_limit函数:设置最大执行时间</p>

<p><span style="color:#3366ff">其他类函数</span></p>

<p>dl函数:加载PHP的扩展模块

main函数:只是一个挂名的main()函数

version_compare函数:比较PHP两个版本值</p>

php高并发秒杀解决方案 {思路}

<p>在秒杀、抢火车票等地方,我们通常用遇到这样高并发的问题,下面我提供了四种解决方案:</p>
<p>1、使用文件锁
 </p>
<pre>$fp = fopen("order.lock", "r");
if(flock($fp,LOCK_EX)){

//..处理订单的代码
flock($fp,LOCK_UN);

}
fclose($fp);

</pre>
<p> </p>
<p>2、使用消息队列</p>
<p>我们常用到Memcacheq、Radis。</p>
<p>比如:有100张票可供用户抢,那么就可以把这100张票放到缓存中,读写时不要加锁。 当并发量大的时候,可能有500人左右抢票成功,这样对于500后面的请求可以直接转到活动结束的静态页面。进去的500个人中有400个人是不可能获得商品的。所以可以根据进入队列的先后顺序只能前100个人购买成功。后面400个人就直接转到活动结束页面。当然进去500个人只是举个例子,至于多少可以自己调整。而活动结束页面一定要用静态页面,不要用数据库。这样就减轻了数据库的压力。</p>
<p><span style="color:#FF6666">—————————————————————————————————————————————————————————</span></p>
<p> 3、如果是分布式集群服务器,就需要一个或多个队列服务器</p>
<p>       小米和淘宝的抢购还是有稍许不同的,小米重在抢的那瞬间,抢到了名额,就是你的,你就可以下单结算。而淘宝则重在付款的时候的过滤,做了多层过滤,比如要卖10件商品,他会让大于10的用户抢到,在付款的时候再进行并发过滤,一层层的减少一瞬间的并发量。</p>
<p><span style="color:#FF6666">—————————————————————————————————————————————————————————</span></p>
<p>4、使用Memcache锁</p>
<p> </p>
<p>product_lock_key 为票锁key</p>
<p>当product_key存在于memcached中时,所有用户都可以进入下单流程。</p>
<p>当进入支付流程时,首先往memcached存放add(product_lock_key, “1″),如果返回成功,进入支付流程。如果不成,则说明已经有人进入支付流程,则线程等待N秒,递归执行add操作。</p>

PHP解决网站大数据大流量与高并发

<p>1:硬件方面</p>

<p>普通的一个p4的服务器每天最多能支持大约10万左右的IP,如果访问量超过10W那么需要专用的服务器才能解决,如果硬件不给力 软件怎么优化都是于事无补的。主要影响服务器的速度</p>

<p>有:网络-硬盘读写速度-内存大小-cpu处理速度。</p>

<p>2:软件方面</p>

<p>第一个要说的就是数据库,首先要有一个很好的架构,查询尽量不用* 避免相关子查询 给经常查询的添加索引 用排序来取代非顺序存取,如果条件允许 ,一般MySQL服务器最好安装</p>

<p>在Linux操作系统中 。关于apache和nginx在高并发的情况下推荐使用nginx,ginx是Apache服务器不错的替代品。nginx内存消耗少 官方测试能够支撑5万并发连接,在实际生产环境中跑</p>

<p>到2~3万并发连接数。php方面不需要的模块尽量关闭,使用memcached,Memcached 是一个高性能的分布式内存对象缓存系统,不使用数据库直接从内存当中调数据,这样大大提升了速</p>

<p>度,iiS或Apache启用GZIP压缩优化网站,压缩网站内容大大节省网站流量。</p>

<p>第二,禁止外部的盗链。</p>

<p>外部网站的图片或者文件盗链往往会带来大量的负载压力,因此应该严格限制外部对

于自身的图片或者文件盗链,好在目前可以简单地通过refer来控制盗链,Apache自

己就可以通过配置来禁止盗链,IIS也有一些第三方的ISAPI可以实现同样的功能。当

然,伪造refer也可以通过代码来实现盗链,不过目前蓄意伪造refer盗链的还不多,

可以先不去考虑,或者使用非技术手段来解决,比如在图片上增加水印。</p>

<p>第三,控制大文件的下载。</p>

<p>大文件的下载会占用很大的流量,并且对于非SCSI硬盘来说,大量文件下载会消耗

CPU,使得网站响应能力下降。因此,尽量不要提供超过2M的大文件下载,如果需要

提供,建议将大文件放在另外一台服务器上。</p>

<p>第四,使用不同主机分流主要流量</p>

<p>将文件放在不同的主机上,提供不同的镜像供用户下载。比如如果觉得RSS文件占用

流量大,那么使用FeedBurner或者FeedSky等服务将RSS输出放在其他主机上,这

样别人访问的流量压力就大多集中在FeedBurner的主机上,RSS就不占用太多资源了</p>

<p>第五,使用不同主机分流主要流量

将文件放在不同的主机上,提供不同的镜像供用户下载。比如如果觉得RSS文件占用流量大,那么使用FeedBurner或者FeedSky等服务将RSS输出放在其他主机上,这样别人访问的流量压力就大多集中在FeedBurner的主机上,RSS就不占用太多资源了。</p>

<p>第六,使用流量分析统计软件。

在网站上安装一个流量分析统计软件,可以即时知道哪些地方耗费了大量流量,哪些页面需要再进行优化,因此,解决流量问题还需要进行精确的统计分析才可以。比如:Google Analytics(Google分析)。</p>

<p>高并发和高负载的约束条件:硬件、部署、操作系统、Web 服务器、PHP、MySQL、测试</p>

<p>部署:服务器分离、数据库集群和库表散列、镜像、负载均衡</p>

<p>负载均衡分类: 1)、DNS轮循 2)代理服务器负载均衡 3)地址转换网关负载均衡 4)NAT负载均衡 5)反向代理负载均衡 6)混合型负载均衡</p>

<p>部署方案1:</p>

<p>适用范围:静态内容为主体的网站和应用系统;对系统安全要求较高的网站和应用系统。</p>

<p>Main Server:主服务器</p>

<p>承载程序的主体运行压力,处理网站或应用系统中的动态请求;</p>

<p>将静态页面推送至多个发布服务器;</p>

<p>将附件文件推送至文件服务器;</p>

<p>安全要求较高,以静态为主的网站,可将服务器置于内网屏蔽外网的访问。</p>

<p>DB Server:数据库服务器</p>

<p>承载数据库读写压力;</p>

<p>只与主服务器进行数据量交换,屏蔽外网访问。</p>

<p>File/Video Server:文件/视频服务器</p>

<p>承载系统中占用系统资源和带宽资源较大的数据流;</p>

<p>作为大附件的存储和读写仓库;</p>

<p>作为视频服务器将具备视频自动处理能力。</p>

<p>发布服务器组:</p>

<p>只负责静态页面的发布,承载绝大多数的Web请求;</p>

<p>通过Nginx进行负载均衡部署。</p>

<p>部署方案2:</p>

<p>适用范围:以动态交互内容为主体的网站或应用系统;负载压力较大,且预算比较充足的网站或应用系统;</p>

<p>Web服务器组:</p>

<p>Web服务无主从关系,属平行冗余设计;</p>

<p>通过前端负载均衡设备或Nginx反向代理实现负载均衡;</p>

<p>划分专用文件服务器/视频服务器有效分离轻/重总线;</p>

<p>每台Web服务器可通过DEC可实现连接所有数据库,同时划分主从。</p>

<p>数据库服务器组:</p>

<p>相对均衡的承载数据库读写压力;</p>

<p>通过数据库物理文件的映射实现多数据库的数据同步。</p>

<p>共享磁盘/磁盘阵列</p>

<p>将用于数据物理文件的统一读写</p>

<p>用于大型附件的存储仓库</p>

<p>通过自身物理磁盘的均衡和冗余,确保整体系统的IO效率和数据安全;</p>

<p>方案特性:</p>

<p>通过前端负载均衡,合理分配Web压力;</p>

<p>通过文件/视频服务器与常规Web服务器的分离,合理分配轻重数据流;</p>

<p>通过数据库服务器组,合理分配数据库IO压力;</p>

<p>每台Web服务器通常只连接一台数据库服务器,通过DEC的心跳检测,可在极短时间内自动切换至冗余数据库服务器;</p>

<p>磁盘阵列的引入,大幅提升系统IO效率的同时,极大增强了数据安全性。</p>

<p>Web服务器:</p>

<p>Web服务器很大一部分资源占用来自于处理Web请求,通常情况下这也就是Apache产生的压力,在高并发连接的情况下,Nginx是Apache服务器不错的替代品。Nginx (“engine x”) 是俄罗斯人编写的一款高性能的 HTTP 和反向代理服务器。在国内,已经有新浪、搜狐通行证、网易新闻、网易博客、金山逍遥网、金山爱词霸、校内网、YUPOO相册、豆瓣、迅雷看看等多家网站、 频道使用 Nginx 服务器。</p>

<p>Nginx的优势:</p>

<p>高并发连接:官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。</p>

<p>内存消耗少:在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)。</p>

<p>内置的健康检查功能:如果 Nginx Proxy 后端的某台 Web 服务器宕机了,不会影响前端访问。</p>

<p>策略:相对于老牌的Apache,我们选择Lighttpd和Nginx这些具有更小的资源占用率和更高的负载能力的web服务器。</p>

<p>Mysql:</p>

<p>MySQL本身具备了很强的负载能力,MySQL优化是一项很复杂的工作,因为这最终需要对系统优化的很好理解。大家都知道数据库工作就是大量的、 短时的查询和读写,除了程序开发时需要注意建立索引、提高查询效率等软件开发技巧之外,从硬件设施的角度影响MySQL执行效率最主要来自于磁盘搜索、磁盘IO水平、CPU周期、内存带宽。</p>

<p>  根据服务器上的硬件和软件条件进行MySQl优化。MySQL优化的核心在于系统资源的分配,这不等于无限制的给MySQL分配更多的资源。在MySQL配置文件中我们介绍几个最值得关注的参数:</p>

<p>改变索引缓冲区长度(key_buffer)</p>

<p>改变表长(read_buffer_size)</p>

<p>设定打开表的数目的最大值(table_cache)</p>

<p>对缓长查询设定一个时间限制(long_query_time)</p>

<p>如果条件允许 ,一般MySQL服务器最好安装在Linux操作系统中,而不是安装在FreeBSD中。

策略: MySQL优化需要根据业务系统的数据库读写特性和服务器硬件配置,制定不同的优化方案,并且可以根据需要部署MySQL的主从结构。</p>

<p>PHP:</p>

<p>1、加载尽可能少的模块;</p>

<p>2、如果是在windows平台下,尽可能使用IIS或者Nginx来替代我们平常用的Apache;</p>

<p>3、安装加速器(都是通过缓存php代码预编译的结果和数据库结果来提高php代码的执行速度)

eAccelerator,eAccelerator是一个自由开放源码php加速器,优化和动态内容缓存,提高了性能php脚本的缓存性能,使得PHP脚本在编译的状态下,对服务器的开销几乎完全消除。</p>

<p>Apc:Alternative PHP Cache(APC)是 PHP 的一个免费公开的优化代码缓存。它用来提供免费,公开并且强健的架构来缓存和优化 PHP 的中间代码。</p>

<p>memcache:memcache是由Danga Interactive开发的,高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。主要机制是通过在内存里维护一个统 一的巨大的hash表,Memcache能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等</p>

<p>Xcache:国人开发的缓存器,</p>

<p>策略: 为PHP安装加速器。</p>

<p>代理服务器(缓存服务器):</p>

<p>Squid Cache(简称为Squid)是一个流行的自由软件(GNU通用公共许可证)的代理服务器和Web缓存服务器。Squid有广泛的用途,从作为网页服务器的前置cache服务器缓存相关请求来提高Web服务器的速度,到为一组人共享网络资源而缓存万维网,域名系统和其他网络搜索,到通过过滤流量帮助网络安全,到局域网通过代理网。Squid主要设计用于在Unix一类系统运行。</p>

<p>策略:安装Squid 反向代理服务器,能够大幅度提高服务器效率。</p>

<p>压力测试:压力测试是一种基本的质量保证行为,它是每个重要软件测试工作的一部分。压力测试的基本思路很简单:不是在常规条件下运行手动或自动测试,而是在计算机数量较少或系统资源匮乏的条件下运行测试。通常要进行压力测试的资源包括内部内存、CPU 可用性、磁盘空间和网络带宽等。一般用并发来做压力测试。

压力测试工具:webbench,ApacheBench等</p>

<p>漏洞测试:在我们的系统中漏洞主要包括:sql注入漏洞,xss跨站脚本攻击等。安全方面还包括系统软件,如操作系统漏洞,mysql、apache等的漏洞,一般可以通过升级来解决。</p>

<p>漏洞测试工具:Acunetix Web Vulnerability Scanner</p>

<p>No related content found.</p>

websocket demo

<pre class="brush:html;toolbar:false">
<script type="text/javascript">

  var  wsServer = 'ws://local:8888/hqsr'; 
 var  websocket = new WebSocket(wsServer); 
 websocket.onopen = function (evt) { onOpen(evt) }; 
 websocket.onclose = function (evt) { onClose(evt) }; 
 websocket.onmessage = function (evt) { onMessage(evt) }; 
 websocket.onerror = function (evt) { onError(evt) }; 
 function onOpen(evt) { 
  //心跳开始
  heartCheck.start();
 console.log("Connected to WebSocket server."); 
 } 
 function onClose(evt) { 
  reconnect();
 } 
 function onMessage(evt) {
 //发送心跳 
  heartCheck.reset();
 console.log('Retrieved data from server: ' + evt.data); 
 } 
 function onError(evt) { 
  reconnect();
 }
var heartCheck = {
    timeout: 60000,//60ms
    timeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
     this.start();
    },
    start: function(){
        this.timeoutObj = setTimeout(function(){
            ws.send("HeartBeat", "beat");
        }, this.timeout)
    }
}
</script>
</body>
</html></pre>

websocket心跳重连

<p>心跳重连缘由

在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时性关闭,这时候websocket的连接已经断开,

而浏览器不会执行websocket 的 onclose方法,我们无法知道是否断开连接,也就无法进行重连操作。

如果当前发送websocket数据到后端,一旦请求超时,onclose便会执行,这时候便可进行绑定好的重连操作。</p><p>因此websocket心跳重连就应运而生。

如何实现

在websocket实例化的时候,我们会绑定一些事件:</p><pre class="brush:js;toolbar:false">复制代码

var ws = new WebSocket(url);
ws.onclose = function () {
    //something
};
ws.onerror = function () {
    //something
};
        
ws.onopen = function () {
   //something
};
ws.onmessage = function (event) {
   //something
}

复制代码

如果希望websocket连接一直保持,我们会在close或者error上绑定重新连接方法。
复制代码

ws.onclose = function () {
    reconnect();
};
ws.onerror = function () {
    reconnect();
};
    

复制代码

这样一般正常情况下失去连接时,触发onclose方法,我们就能执行重连了。

 

那么针对断网的情况的心跳重连,怎么实现呢。

简单的实现:
复制代码

var heartCheck = {
    timeout: 60000,//60ms
    timeoutObj: null,
    reset: function(){
        clearTimeout(this.timeoutObj);
     this.start();
    },
    start: function(){
        this.timeoutObj = setTimeout(function(){
            ws.send("HeartBeat", "beat");
        }, this.timeout)
    }
}

ws.onopen = function () {
   heartCheck.start();
};

ws.onmessage = function (event) {
    heartCheck.reset();
}

复制代码

如上代码,heartCheck 的 reset和start方法主要用来控制心跳的定时。

当onopen也就是连接上时,我们便开始start计时,如果在定时时间范围内,onmessage获取到了服务器的消息,我们就重置倒计时,

所以在距离上次从服务器获取到消息,闲置60秒之后我们才会心跳检测,这个检测时间可以自己根据自身情况设定。

当心跳检测send执行之后,如果当前websocket是断开状态,发送超时之后,onclose方法便会被执行,重连也执行了。

如此一来,我们的心跳检测就实现了。

 

后来,我本想测试websocket超时时间,又发现了一些新的问题

1. 在chrome中,如果心跳检测 也就是websocket实例执行send之后,15秒内没发送到另一接收端,onclose便会执行。那么超时时间是15秒。

2. 我又打开了Firefox ,Firefox在断网7秒之后,直接执行onclose。说明在Firefox中不需要心跳检测便能自动onclose。

3.  同一代码, reconnect方法 在chrome 执行了一次,Firefox执行了两次。当然我们在几处地方(代码逻辑处和websocket事件处)绑定了reconnect(),

所以保险起见,我们还是给reconnect()方法加上一个锁,保证只执行一次

 

目前来看不同的浏览器,有不同的机制,无论浏览器websocket自身会不会在断网情况下执行onclose,加上心跳重连后,已经能保证onclose的正常触发。</pre><p><br/></p>

workerman启动失败解决方法

<p>工作中碰到workerman启动失败最常见的就是由于启动脚本找不到主进程pid文件导致的,workerman 3.2.2之前的版本主进程pid文件默认存储在/tmp/下,有些系统会定时清理/tmp/目录,导致无法启动。





解决方法:

方法1:升级workerman到3.2.2或以上版本,workerman3.2.2 版本不在将pid文件存储在/tmp/下,另外提供了PHP xxx.php kill 命令,方便强行杀死workerman进程。</p>

<p>

方法2:可以运行 ps aux | grep start.php | awk '{print $2}' | xargs kill -9 强行杀死进程。然后参考手册pidFile将pid文件存储在安全的地方。</p>

PHP两个函数参考 call_user_method call_user_function

<pre class="brush:php;toolbar:false">今天在写一个功能时,遇到了一个,把文本转换成方法,或者转换成功能的问题,之前有用过这两个函数,但今天怎么想也想不起来。MARK一下,方便后面用(太少会用到了)。

call_user_method ( string $method_name&nbsp;,&nbsp;object&nbsp;&amp;$obj [, mixed $parameter&nbsp;[,&nbsp;mixed&nbsp;$... ]] )
 
call_user_func ( callable $callback&nbsp;[,&nbsp;mixed&nbsp;$parameter [, mixed $... ]] )</pre><p><br/></p>

thinkphp 图形验证码 小程序中使用,总是验证失败(sessionid设置)

<p>前端同事在开发接口中,在注册页面,使用图形验证码时,图形验证一直没通过,但是APP验证没问题所有跑过来问我原因。一开始我以为是她代码的问题,于是,自已在本地测试了下,发现也不行。只能一步步排</p><p>1,首先,图形验证码是用的TP的captcha,APP有使用过,代码应该没有问题,那就只能找差异,首先想到的是SESSION。因为验证值是加密存到SESSION中</p><p>    小程序设置相关代码如下</p><pre class="brush:js;toolbar:false"> if (session_id != "" && session_id != null) {
    var header = { 'content-type': 'application/x-www-form-urlencoded', 'Cookie': 'PHPSESSID=' + session_id }
  } else {
    var header = { 'content-type': 'application/x-www-form-urlencoded' }
  }
  
  然后把header加到请求头中</pre><p>2,加完以后发现,在API请求中,SESSION数据打印没问题,但是在captcha图相生成中SESSION并没有生效。没有数据打印,后面发现,图形验证码的地址为https://xxx.cn/api.php/captcha/729765.html?也就是直的网页另外再写的图片,会不会是这块,没有用到我HEDER头中的SESSION?<br/></p><p>改造后代码 PHP:<br/></p><pre class="brush:php;toolbar:false">$sessionId = session_id();##当前的SESSION,返出去让前端保存,方便拿后面的数据和数据比对
returnJson(0,'',['captcha'=>captcha_src($id).&#39;?&#39;.$id.'&sessionId='.$sessionId,&#39;sessionId&#39;=&gt;$sessionId]);##把参数传到图片生成类</pre><pre class="brush:php;toolbar:false">##图片生成类成加入,使用当前的SESSID  
if(input('sessionId')) session_id(input('sessionId'));
 $captcha = new Captcha((array)Config::get('captcha'));
 return $captcha-&gt;entry($id);</pre><p>解决,如果你有其它更好的方法,欢迎留言<br/></p>

oss 数据迁移(DISCUZ OSS图片处理)

<p>公益系统很多没有更新了,随着人越来越来。系统也越来越慢。系统还是2013年搭的,所有在系统方面也进行了调整。</p><p>之前的服务器架构  1核1G+3M带宽</p><p>现在架构                2核+4G +5M 带宽  <br/></p><p>恩,速度快很多</p><p>公益系统很大,现在在做的JAVA那套就先不管了,现在有两大块管理系统和社区,社区是大头,所有先把社区的先更新了。</p><p>这次更新后的架构   LNMP+REDIS+OSS(图片分离)+CDN分发</p><p>=====================================================</p><p>LNMP和REDIS就没什么好说的,说下DISCUZ的OSS图片这块。这块,搞得有点头大</p><p>1,系统的图片是10W+的附件 这么大的资源,要怎么处理呢。</p><p>2,目前DISCUZ的附件只有FTP这块 ,另外开发一来是没有这么多精力,二来周期太长</p><p><br/></p><p>=====================================================</p><p>解决办法:</p><p>DISCUZ附件上传这块的处理办法</p><p>##要PYTHON支持<br/></p><p>1,服务器中安装OSSFTP  <br/></p><p> 也可以参照官方的文档:https://help.aliyun.com/document_detail/32190.html?spm=a2c4g.11186623.6.1063.xZjQs8</p><pre class="brush:bash;toolbar:false">##地址可能会变
wget http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/32190/cn_zh/1523340041580/ossftp-1.0.3-linux-mac.zip
unzip  ossftp-1.0.3-linux-mac.zip</pre><p>因为我只需要OSSFTP的服务所有只运行了FTP服务,没有使用WEB的服务</p><pre class="brush:bash;toolbar:false">##如果没有安装python需要安装python

yum -y install python

python ossftp/ftpserver.py &</pre><p>ossftp搭建完成后,设置后台地址</p><p>全局--》上传设置--》远程附件</p><p>有几个参数需要处理</p><pre class="brush:bash;toolbar:false">启用远程附件:  是
启用 SSL 连接:  否 
FTP 服务器地址:  127.0.0.1  (分布架构可以填服务器的IP)
FTP 服务器端口:  2048(默认为2048,可以更改)    
FTP 帐号:   Access Key ID/BukcetName
FTP 密码:   AceessKeySecrete 
基于安全考虑将只显示 FTP 密码的第一位和最后一位,中间显示八个 * 号    
被动模式(pasv)连接:    是 
远程附件目录:    .(不用更新)
远程访问 URL  :访问的地址,如http://static.xx.com</pre><p>设置完成后,就可以去前台测试下是否成功了。</p><p>=============================================</p><p>CDN分发  CDN分发,最头痛的问题就是文件太多不知道怎么搬到OSS</p><p>OSS 有个  ossutil  官方文档https://help.aliyun.com/document_detail/50452.html?spm=a2c4g.11186623.6.1057.mU8oVK<br/></p><pre class="brush:bash;toolbar:false">./ossutil config -L CH 设置配置方件
./ossutil help cp  ##查看官方文档,官方建立用CP

./ossutil cp /home/backup/ oss://bucket-name/subfolder-name/ -r    ##操作上传</pre><p>=============================================<br/></p><p><br/></p><p><br/></p>

解决VUE请求PHP后台,跨域的问题

<pre class="brush:php;toolbar:false">    ##添加头部信息
    header('Access-Control-Allow-Origin:http://localhost:8080');  
    Header('Access-Control-Allow-Headers:Content-Type');  
    header('Access-Control-Allow-Credentials:true');//是否支持cookie跨域</pre><p><br/></p>

常用的PHP方法整理(持续更新)

<pre class="brush:php;toolbar:false"><?php 
if (!function_exists('clear_js')) {
    /**
     * 过滤js内容
     * @param string $str 要过滤的字符串
     * @author 
     * @return mixed|string
     */
    function clear_js($str = '')
    {
        $search ="/<script1?>.?</script>/si";
        $str&nbsp;=&nbsp;preg_replace($search, '', $str);
        return $str;
    }
}
/**
 * 删除网页上看不见的隐藏字符串, 如 Java\0script
 *
 * @param   string
 */
function remove_invisible_characters(&$str,&nbsp;$url_encoded = TRUE)
{
    $non_displayables = array();
    
    // every control character except newline (dec 10)
    // carriage return (dec 13), and horizontal tab (dec 09)
    
    if ($url_encoded)
    {
        $non_displayables[] = '/%0[0-8bcef]/';  // url encoded 00-08, 11, 12, 14, 15
        $non_displayables[] = '/%1[0-9a-f]/';   // url encoded 16-31
    }
    
    $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';   // 00-08, 11, 12, 14-31, 127

    do
    {
        $str&nbsp;=&nbsp;preg_replace($non_displayables, '', $str,&nbsp;-1,&nbsp;$count);
    }
    while ($count);
}
/**
 * 对数组或字符串进行转义处理,数据可以是字符串或数组及对象
 * @param void $data
 * @return type
 */
function addslashes_d($data) {
    if (is_string($data)) {
        return htmlspecialchars(addslashes($data));
    }
    if (is_numeric($data)) {
        return $data;
    }
    if (is_array($data)) {
        $var = array();
        foreach ($data&nbsp;as&nbsp;$k => $v) {
            if (is_array($v)) {
                $var[$k] = addslashes_d($v);
                continue;
            } else {
                $var[$k] = htmlspecialchars(addslashes($v));
            }
        }
        return $var;
    }
}
/**
 * 去除转义
 * @param type $data
 * @return type
 */
function stripslashes_d($data) {
    if (empty($data)) {
        return $data;
    } elseif (is_string($data)) {
        return htmlspecialchars_decode(stripslashes($data));
    } elseif (is_array($data)) {
        $var = array();
        foreach ($data&nbsp;as&nbsp;$k => $v) {
            if (is_array($v)) {
                $var[$k] = stripslashes_d($v);
                continue;
            } else {
                $var[$k] = htmlspecialchars_decode(stripslashes($v));
            
            }
        }
        return $var;
    }
}
/**
 * 将数组转为字符串表示形式
 * @param array $array 数组
 * @param int $level 等级不要传参数
 * @return string
 */
function array_to_String($array,&nbsp;$level = 0) {
    if (!is_array($array)) {
        return "'" . $array . "'";
    }
    $space = '';
    //空白
    for ($i&nbsp;=&nbsp;0;&nbsp;$i <= $level;&nbsp;$i++) {
        $space .= "\t";
    }
    $arr&nbsp;=&nbsp;&quot;Array\n$space(\n";
    $c&nbsp;=&nbsp;$space;
    foreach ($array&nbsp;as&nbsp;$k => $v) {
        $k&nbsp;=&nbsp;is_string($k) ? '\&#39;' . addcslashes($k,&nbsp;&#39;\&#39;\\&#39;)&nbsp;.&nbsp;&#39;\&#39;&#39;&nbsp;:&nbsp;$k;
        $v&nbsp;=&nbsp;!is_array($v) && (!preg_match("/^-?[1-9]\d*$/&quot;,&nbsp;$v) || strlen($v)&nbsp;&gt;&nbsp;12)&nbsp;?&nbsp;&#39;\&#39;&#39;&nbsp;.&nbsp;addcslashes($v, '\&#39;\') . '\&#39;' : $v;
        if (is_array($v)) {
            $arr&nbsp;.=&nbsp;&quot;$c$k=&gt;&quot;&nbsp;.&nbsp;array_to_String($v, $level + 1);
        } else {
            $arr&nbsp;.=&nbsp;&quot;$c$k=&gt;$v";
        }
        $c&nbsp;=&nbsp;&quot;,\n$space";
    }
    $arr&nbsp;.=&nbsp;&quot;\n$space)";
    return $arr;
}

/**
 * 产生随机字串,可用来自动生成密码 默认长度6位 字母和数字混合
 * @param string $len 长度
 * @param string $type 字串类型
 * 0 字母 1 数字 其它 混合
 * @param string $addChars 额外字符
 * @return string
 */
function rand_string($len=6,$type='',$addChars='') {
    $str ='';
    switch($type) {
        case 0:
            $chars=&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#39;.$addChars;
            break;
        case 1:
            $chars= str_repeat('0123456789',3);
            break;
        case 2:
            $chars=&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ&#39;.$addChars;
            break;
        case 3:
            $chars=&#39;abcdefghijklmnopqrstuvwxyz&#39;.$addChars;
            break;
        case 4:
            $chars&nbsp;=&nbsp;&quot;们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借&quot;.$addChars;
            break;
        default :
            // 默认去掉了容易混淆的字符oOLl和数字01,要添加请使用addChars参数
            $chars=&#39;ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789&#39;.$addChars;
            break;
    }
    if($len>10 ) {//位数过长重复字符串一定次数
        $chars=&nbsp;$type==1? str_repeat($chars,$len) : str_repeat($chars,5);
    }
    if($type!=4) {
        $chars&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;str_shuffle($chars);
        $str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;substr($chars,0,$len);
    }else{
        // 中文随机字
        for($i=0;$i<$len;$i++){
          $str.=&nbsp;msubstr($chars, floor(mt_rand(0,mb_strlen($chars,'utf-8')-1)),1);
        }
    }
    return $str;
}
// 随机生成一组字符串
function build_count_rand ($number,$length=4,$mode=1) {
    if($mode==1&nbsp;&amp;&amp;&nbsp;$length<strlen($number) ) {
        //不足以生成一定数量的不重复数字
        return false;
    }
    $rand   =  array();
    for($i=0;&nbsp;$i<$number;&nbsp;$i++) {
        $rand[]&nbsp;=&nbsp;&nbsp;&nbsp;rand_string($length,$mode);
    }
    $unqiue&nbsp;=&nbsp;array_unique($rand);
    if(count($unqiue)==count($rand)) {
        return $rand;
    }
    $count&nbsp;&nbsp;&nbsp;=&nbsp;count($rand)-count($unqiue);
    for($i=0;&nbsp;$i<$count*3;&nbsp;$i++) {
        $rand[]&nbsp;=&nbsp;&nbsp;&nbsp;rand_string($length,$mode);
    }
    $rand&nbsp;=&nbsp;array_slice(array_unique&nbsp;($rand),0,$number);
    return $rand;
}
function rand_email(){
    $postfix =['qq.com','sina.com','sina.com.cn','163.cn','wanli.com','163.com','aliyun.com','qqcs.com','gmail.com','arcs.com','qq.com.cn','vip.qq.com','vip.sina.cn','exrs.com','disre.net','sraxw.net','saraxw.org.cn','szp.org.cn','hqds.org.cn','huwei.cn','ares.cc'];
    return rand_string(rand(5,10),rand(0,3))."@".$postfix[rand(0,count($postfix)-1)];
}
function rand_phone(){
    $prefix = [133,138,152,177,182,192,150,131,130,134,137,139,151,153,155,156,158,159,170,171,172,173,174,175,177,179,160,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197];
    return $prefix[rand(0,count($postfix)-1)].rand_string(8,1);
}
function rand_user(){
    return rand_string(rand(3,7),rand(0,3));
}
/**
 * 检查字符串是否是UTF8编码
 * @param string $string 字符串
 * @return Boolean
 */
function is_utf8($string) {
    return preg_match('%^(?:
         [\x09\x0A\x0D\x20-\x7E]            # ASCII
       | \xC2-\xDF             # non-overlong 2-byte
       |  \xE0\xA0-\xBF        # excluding overlongs
       | \xE1-\xEC\xEE\xEF{2}  # straight 3-byte
       |  \xED\x80-\x9F        # excluding surrogates
       |  \xF0\x90-\xBF{2}     # planes 1-3
       | \xF1-\xF3{3}          # planes 4-15
       |  \xF4\x80-\x8F{2}     # plane 16
    )*$%xs&#39;,&nbsp;$string);
}
/**
 * php 获取一定范围内不重复的随机数字,在1-10间随机产生5个不重复的值
 * @param int $begin
 * @param int $end
 * @param int $limit
 * @return array
 */
function getRand($begin=0,$end=10,$limit=5){
    $rand_array=range($begin,$end);//把$begin到$end列成一个数组
    shuffle($rand_array);//将数组顺序随机打乱,shuffle是系统的数组随机排列函数
return array_slice($rand_array,0,$limit);//array_slice取该数组中的某一段,这里截取0到$limit个,即前$limit个
}
/**
 * [machUrl 是否为URL]
 * @Author   Jerry
 * @DateTime 2017-11-04T01:16:49+0800
 * @Example  eg:
 * @param    [type]                   $str [description]
 * @return   [type]                        [description]
 */
function matchUrl($str){
    $pattern = '/http://[0-9a-z./-]+/[0-9a-z./-]+.([0-9a-z./-]+)/';
    preg_match_all($pattern,$str,$match); 
    return $match;
}
/**
 * [matchImage 检查字符串中是否有图片]
 * @Author   Jerry
 * @DateTime 2017-11-04T01:09:58+0800
 * @Example  eg:
 * @param    [type]                   $str [description]
 * @return   [type]                        [description]
 */
function matchImage($str){
    $pattern="/<[img|IMG].?src=\&#39;|\&quot;)[\&#39;|\&quot;].?[/]?>/"; 
    preg_match_all($pattern,$str,$match); 
    return $match;
}
/**
 * [GrabImage 保存远程图片至本地]
 * @param [type] $url      [远程图片地址]
 * @param string $filename [保存图片名]
 */
function GrabImage($url,$filename="") {
    if($url=="") return false;

    if($filename=="") {
    $ext=strrchr($url,".");
    if($ext!=&quot;.gif&quot;&nbsp;&amp;&amp;&nbsp;$ext!=".jpg" && $ext!=".png") return false;
    $filename=date(&quot;YmdHis&quot;).$ext;
    }

    ob_start();
    readfile($url);
    $img = ob_get_contents();
    ob_end_clean();
    $size&nbsp;=&nbsp;strlen($img);

    $fp2=@fopen($filename, "a");
    fwrite($fp2,$img);
    fclose($fp2);

    return $filename;
}
/**
 * 获取url
 * @return [type] [description]
 */
function getUrl(){
  $pageURL = 'http';
  if (isset($_SERVER[&quot;HTTPS&quot;])&nbsp;&amp;&amp;&nbsp;$_SERVER["HTTPS"] == "on") {
    $pageURL .= "s";
  }
  $pageURL .= "://";
  if ($_SERVER["SERVER_PORT"] != "80") {
    $pageURL&nbsp;.=&nbsp;$_SERVER["HTTP_HOST"] . ":" . $_SERVER[&quot;SERVER_PORT&quot;]&nbsp;.&nbsp;$_SERVER["REQUEST_URI"];
  } else {
    $pageURL&nbsp;.=&nbsp;$_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
  }
  return $pageURL;
}
/**
 * 下载
 * @param  [type] $filename [description]
 * @param  string $dir      [description]
 * @return [type]           [description]
 */
function downloads($filename,$dir='./'){
    $filepath&nbsp;=&nbsp;$dir.$filename;
    if (!file_exists($filepath)){
        header("Content-type: text/html; charset=utf-8");
        echo "File not found!";
        exit;
    } else {
        $file&nbsp;=&nbsp;fopen($filepath,"r");
        Header("Content-type: application/octet-stream");
        Header("Accept-Ranges: bytes");
        Header("Accept-Length: ".filesize($filepath));
        Header("Content-Disposition: attachment; filename=".$filename);
        echo fread($file,&nbsp;filesize($filepath));
        fclose($file);
    }
}

/**
 * 打印输出数据
 * @param void $var
 */
function show($var) {
    if (is_bool($var)) {
        var_dump($var);
    } else if (is_null($var)) {
        var_dump(NULL);
    } else {
        echo "<pre style='padding:10px;border-radius:5px;background:#F5F5F5;border:1px solid #aaa;font-size:14px;line-height:18px;'>" . print_r($var, true) . "</pre>";
    }
}

if (!function_exists('load_static')) {
    /**
     * 加载静态资源
     * @param string $static 资源名称
     * @param string $type 资源类型
     * @author 
     * @return string
     */
    function load_static($static&nbsp;=&nbsp;&#39;&#39;,&nbsp;$type = 'css',$minify='true')
    {
         
        ##开启minify
        $minify&nbsp;=&nbsp;$minify=="false"?false:true;

        ##*因为开启CDN,强制不开启MINIFY 
        $minify = false;

        
        $assets_list&nbsp;=&nbsp;config($static);
        if($minify){
            $assets_list&nbsp;=&nbsp;!is_array($assets_list) ? $assets_list&nbsp;:&nbsp;implode(&#39;,&#39;,&nbsp;$assets_list);
            $url   = '/public/min/?f=';
            $result&nbsp;=&nbsp;$type=='css'?'<link rel="stylesheet" href="'.$url.$assets_list.'">':'<script src="'.$url.$assets_list.'"></script>';
            $result&nbsp;=&nbsp;$result."\n";
        }else{
        $result = '';
         ##如果设置了CDN域名,
        $pre = getset('cdn_domain');
            foreach ($assets_list&nbsp;as&nbsp;$item) {
                if ($type == 'css') {
                    $result&nbsp;.=&nbsp;&#39;&lt;link&nbsp;rel=&quot;stylesheet&quot;&nbsp;href=&quot;&#39;.$pre.$item.'">'."\n";
                } else {
                    $result&nbsp;.=&nbsp;&#39;&lt;script&nbsp;src=&quot;&#39;.$pre.$item.'"></script>'."\n";
                }
            } 
        }
       
        return $result;
    }
}

if (!function_exists('minify')) {
    /**
     * 合并输出js代码或css代码 需要minify插件支付
     * @param string $type 类型:group-分组,file-单个文件,base-基础目录
     * @param string $files 文件名或分组名
     * @author 
     */
    function minify($type&nbsp;=&nbsp;&#39;&#39;,$files = '')
    {
        $files&nbsp;=&nbsp;!is_array($files) ? $files&nbsp;:&nbsp;implode(&#39;,&#39;,&nbsp;$files);
        $url   = '/public/min/?';

        switch ($type) {
            case 'group':
                $url&nbsp;.=&nbsp;&#39;g=&#39;&nbsp;.&nbsp;$files;
                break;
            case 'file':
                $url&nbsp;.=&nbsp;&#39;f=&#39;&nbsp;.&nbsp;$files;
                break;
            case 'base':
                $url&nbsp;.=&nbsp;&#39;b=&#39;&nbsp;.&nbsp;$files;
                break;
        }
        return  $url;
    }
}
if (!function_exists('get_browser_type')) {
    /**
     * 获取浏览器类型
     * @return string
     */
    function get_browser_type(){
        $agent&nbsp;=&nbsp;$_SERVER["HTTP_USER_AGENT"];
        if(strpos($agent,&#39;MSIE&#39;)&nbsp;!==&nbsp;false&nbsp;||&nbsp;strpos($agent,'rv:11.0')) return "ie";
        if(strpos($agent,'Firefox') !== false) return "firefox";
        if(strpos($agent,'Chrome') !== false) return "chrome";
        if(strpos($agent,'Opera') !== false) return 'opera';
        if((strpos($agent,&#39;Chrome&#39;)&nbsp;==&nbsp;false)&nbsp;&amp;&amp;&nbsp;strpos($agent,'Safari') !== false) return 'safari';
        if(false!==strpos($_SERVER['HTTP_USER_AGENT'],'360SE')) return '360SE';
        return 'unknown';
    }
}
/**
 * 判断是否是合格的手机客户端
 * 
 * @return boolean
 */
function is_mobile()
{
    $user_agent&nbsp;=&nbsp;strtolower($_SERVER['HTTP_USER_AGENT']);
    
    if (preg_match('/playstation/i', $user_agent)&nbsp;OR&nbsp;preg_match(&#39;/ipad/i&#39;,&nbsp;$user_agent) OR preg_match('/ucweb/i', $user_agent))
    {
        return false;
    }
    
    if (preg_match('/iemobile/i', $user_agent)&nbsp;OR&nbsp;preg_match(&#39;/mobile\ssafari/i&#39;,&nbsp;$user_agent) OR preg_match('/iphone\sos/i', $user_agent)&nbsp;OR&nbsp;preg_match(&#39;/android/i&#39;,&nbsp;$user_agent) OR preg_match('/symbian/i', $user_agent)&nbsp;OR&nbsp;preg_match(&#39;/series40/i&#39;,&nbsp;$user_agent))
    {
        return true;
    }
    
    return false;
    // return true;
}
/**
 * 判断是否处于微信内置浏览器中
 * 
 * @return boolean
 */
function in_weixin()
{
    $user_agent&nbsp;=&nbsp;strtolower($_SERVER['HTTP_USER_AGENT']);
    
    if (preg_match('/micromessenger/i', $user_agent))
    {
        return true;
    }
    
    return false;
}
if (!function_exists('generate_rand_str')) {
    /**
     * 生成随机字符串
     * @param int $length 生成长度
     * @param int $type 生成类型:0-小写字母+数字,1-小写字母,2-大写字母,3-数字,4-小写+大写字母,5-小写+大写+数字
     * @author 蔡伟明 <314013107@qq.com>
     * @return string
     */
    function generate_rand_str($length&nbsp;=&nbsp;8,&nbsp;$type = 0) {
        $a = 'abcdefghijklmnopqrstuvwxyz';
        $A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $n = '0123456789';

        switch ($type) {
            case 1: $chars&nbsp;=&nbsp;$a; break;
            case 2: $chars&nbsp;=&nbsp;$A; break;
            case 3: $chars&nbsp;=&nbsp;$n; break;
            case 4: $chars&nbsp;=&nbsp;$a.$A; break;
            case 5: $chars&nbsp;=&nbsp;$a.$A.$n; break;
            default: $chars&nbsp;=&nbsp;$a.$n;
        }

        $str = '';
        for ($i&nbsp;=&nbsp;0;&nbsp;$i < $length;&nbsp;$i++) {
            $str&nbsp;.=&nbsp;$chars[ mt_rand(0, strlen($chars) - 1) ];
        }
        return $str;
    }
}
if (!function_exists('get_server_ip')) {
    /**
     * 获取服务器端IP地址
     * @return array|false|string
     */
    function get_server_ip(){
        if(isset($_SERVER)){
            if($_SERVER['SERVER_ADDR']){
                $server_ip&nbsp;=&nbsp;$_SERVER['SERVER_ADDR'];
            }else{
                $server_ip&nbsp;=&nbsp;$_SERVER['LOCAL_ADDR'];
            }
        }else{
            $server_ip = getenv('SERVER_ADDR');
        }
        return $server_ip;
    }
}
/**
 * [getIp 此方法相对比较好]
 * @return [type] [description]
 */
function fetch_ip(){  
  $realip = '';  
  $unknown = 'unknown';  
  if (isset($_SERVER)){  
      if(isset($_SERVER[&#39;HTTP_X_FORWARDED_FOR&#39;])&nbsp;&amp;&amp;&nbsp;!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && strcasecmp($_SERVER[&#39;HTTP_X_FORWARDED_FOR&#39;],&nbsp;$unknown)){  
          $arr&nbsp;=&nbsp;explode(&#39;,&#39;,&nbsp;$_SERVER['HTTP_X_FORWARDED_FOR']);  
          foreach($arr&nbsp;as&nbsp;$ip){  
              $ip&nbsp;=&nbsp;trim($ip);  
              if ($ip != 'unknown'){  
                  $realip&nbsp;=&nbsp;$ip;  
                  break;  
              }  
          }  
      }else if(isset($_SERVER[&#39;HTTP_CLIENT_IP&#39;])&nbsp;&amp;&amp;&nbsp;!empty($_SERVER['HTTP_CLIENT_IP']) && strcasecmp($_SERVER[&#39;HTTP_CLIENT_IP&#39;],&nbsp;$unknown)){  
          $realip&nbsp;=&nbsp;$_SERVER['HTTP_CLIENT_IP'];  
      }else if(isset($_SERVER[&#39;REMOTE_ADDR&#39;])&nbsp;&amp;&amp;&nbsp;!empty($_SERVER['REMOTE_ADDR']) && strcasecmp($_SERVER[&#39;REMOTE_ADDR&#39;],&nbsp;$unknown)){  
          $realip&nbsp;=&nbsp;$_SERVER['REMOTE_ADDR'];  
      }else{  
          $realip&nbsp;=&nbsp;$unknown;  
      }  
  }else{  
      if(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), $unknown)){  
          $realip = getenv("HTTP_X_FORWARDED_FOR");  
      }else if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), $unknown)){  
          $realip = getenv("HTTP_CLIENT_IP");  
      }else if(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), $unknown)){  
          $realip = getenv("REMOTE_ADDR");  
      }else{  
          $realip&nbsp;=&nbsp;$unknown;  
      }  
  }  
  $realip&nbsp;=&nbsp;preg_match(&quot;/[\d\.]{7,15}/&quot;,&nbsp;$realip, $matches)&nbsp;?&nbsp;$matches[0] : $unknown;  
  return $realip;  
}  
/**
 * 验证 IP 地址是否为内网 IP
 * 
 * @param string
 * @return string
 */
function valid_internal_ip($ip)

    $ip_address&nbsp;=&nbsp;explode(&#39;.&#39;,&nbsp;$ip);
    
    if ($ip_address[0] == 10)
    {
        return true;
    }
    
    if ($ip_address[0]&nbsp;==&nbsp;172&nbsp;and&nbsp;$ip_address[1] > 15 and $ip_address[1] < 32)
    {
        return true;
    }
    
    if ($ip_address[0]&nbsp;==&nbsp;192&nbsp;and&nbsp;$ip_address[1] == 168)
    {
        return true;
    } 
    
    return false;
}
/**
 * 兼容性转码
 * 
 * 系统转换编码调用此函数, 会自动根据当前环境采用 iconv 或 MB String 处理
 * 
 * @param  string
 * @param  string
 * @param  string 
 * @return string
 */
function convert_encoding($string,&nbsp;$from_encoding = 'GBK', $target_encoding = 'UTF-8')
{
    if (function_exists('mb_convert_encoding'))
    {
        return mb_convert_encoding($string,&nbsp;str_replace(&#39;//IGNORE&#39;,&nbsp;&#39;&#39;,&nbsp;strtoupper($target_encoding)), $from_encoding);
    }
    else
    {
        if (strtoupper($from_encoding) == 'UTF-16')
        {
            $from_encoding = 'UTF-16BE';
        }
        
        if (strtoupper($target_encoding) == 'UTF-16')
        {
            $target_encoding = 'UTF-16BE';
        }
        
        if (strtoupper($target_encoding)&nbsp;==&nbsp;&#39;GB2312&#39;&nbsp;or&nbsp;strtoupper($target_encoding) == 'GBK')
        {
            $target_encoding .= '//IGNORE';
        }
        
        return iconv($from_encoding,&nbsp;$target_encoding, $string);
    }
}
/**
 * 兼容性转码 (数组)
 * 
 * 系统转换编码调用此函数, 会自动根据当前环境采用 iconv 或 MB String 处理, 支持多维数组转码
 * 
 * @param  array
 * @param  string
 * @param  string 
 * @return array
 */
function convert_encoding_array($data,&nbsp;$from_encoding = 'GBK', $target_encoding = 'UTF-8')
{
    return eval('return ' . convert_encoding(var_export($data,&nbsp;true)&nbsp;.&nbsp;&#39;;&#39;,&nbsp;$from_encoding, $target_encoding));    
}
/**
 * 字符串截取,支持中文和其他编码
 * @param  [string]  $str     [字符串]
 * @param  integer $start   [起始位置]
 * @param  integer $length  [截取长度]
 * @param  string  $charset [字符串编码]
 * @param  boolean $suffix  [是否有省略号]
 * @return [type]           [description]
 */
function msubstr($str,&nbsp;$start=0, $length=50,&nbsp;$charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr")) {
          if($suffix&amp;&amp;mb_strlen($str,'UTF-8')>$length){
            return mb_substr($str,&nbsp;$start, $length,&nbsp;$charset)."...";
          }else{
            return mb_substr($str,&nbsp;$start, $length,&nbsp;$charset);
          }
        
    } elseif(function_exists('iconv_substr')) {
        return iconv_substr($str,$start,$length,$charset);
    }
    $re['utf-8']   = "/[\x01-\x7f]|\xc2-\xdf|\xe0-\xef{2}|\xf0-\xff{3}/";
    $re['gb2312'] = "/[\x01-\x7f]|\xb0-\xf7/";
    $re['gbk']    = "/[\x01-\x7f]|\x81-\xfe/";
    $re['big5']   = "/[\x01-\x7f]|\x81-\xfe/";
    preg_match_all($re[$charset], $str,&nbsp;$match);
    $slice&nbsp;=&nbsp;join(&quot;&quot;,array_slice($match[0], $start,&nbsp;$length));

    if($suffix) {
        return $slice."......";
    }
    return $slice;
}
/**
 * 递归创建目录
 * 
 * 与 mkdir 不同之处在于支持一次性多级创建, 比如 /dir/sub/dir/
 * 
 * @param  string
 * @param  int
 * @return boolean
 */
function make_dir($dir,&nbsp;$permission = 0777)
{
    $dir&nbsp;=&nbsp;rtrim($dir, '/') . '/';
    
    if (is_dir($dir))
    {
        return TRUE;
    }
    
    if (! make_dir(dirname($dir),&nbsp;$permission))
    {
        return FALSE;
    }
    
    return @mkdir($dir,&nbsp;$permission);
}
/**
 * jQuery jsonp 调用函数
 * 
 * 用法同 json_encode
 * 
 * @param  array
 * @param  string
 * @return string
 */
function jsonp_encode($json&nbsp;=&nbsp;array(),&nbsp;$callback = 'jsoncallback')
{
    if ($_GET[$callback])
    {
        return $_GET[$callback] . '(' . json_encode($json) . ')';
    }
    
    return json_encode($json);
}
/**
 * 时间友好型提示风格化(即微博中的XXX小时前、昨天等等)
 * 
 * 即微博中的 XXX 小时前、昨天等等, 时间超过 $time_limit 后返回按 out_format 的设定风格化时间戳
 * 
 * @param  int
 * @param  int
 * @param  string
 * @param  array
 * @param  int
 * @return string
 */
function date_friendly($timestamp,&nbsp;$time_limit = 604800, $out_format&nbsp;=&nbsp;&#39;Y-m-d&nbsp;H:i&#39;,&nbsp;$formats = null, $time_now = null)
{
    // if (get_setting('time_style') == 'N')
    // {
    //  return date($out_format,&nbsp;$timestamp);
    // }
    
    if ($formats == null)
    {
        $formats = array('YEAR' => '%s 年前', 'MONTH' => '%s 月前', 'DAY' => '%s 天前', 'HOUR' => '%s 小时前', 'MINUTE' => '%s 分钟前', 'SECOND' => '%s 秒前');
    }
    
    $time_now&nbsp;=&nbsp;$time_now == null ? time() : $time_now;
    $seconds&nbsp;=&nbsp;$time_now - $timestamp;
    
    if ($seconds == 0)
    {
        $seconds = 1;
    }
    
    if ($time_limit&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;$seconds > $time_limit)
    {
        return date($out_format,&nbsp;$timestamp);
    }
    
    $minutes&nbsp;=&nbsp;floor($seconds / 60);
    $hours&nbsp;=&nbsp;floor($minutes / 60);
    $days&nbsp;=&nbsp;floor($hours / 24);
    $months&nbsp;=&nbsp;floor($days / 30);
    $years&nbsp;=&nbsp;floor($months / 12);
    
    if ($years > 0)
    {
        $diffFormat = 'YEAR';
    }
    else
    {
        if ($months > 0)
        {
            $diffFormat = 'MONTH';
        }
        else
        {
            if ($days > 0)
            {
                $diffFormat = 'DAY';
            }
            else
            {
                if ($hours > 0)
                {
                    $diffFormat = 'HOUR';
                }
                else
                {
                    $diffFormat&nbsp;=&nbsp;($minutes > 0) ? 'MINUTE' : 'SECOND';
                }
            }
        }
    }
    
    $dateDiff = null;
    
    switch ($diffFormat)
    {
        case 'YEAR' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$years);
            break;
        case 'MONTH' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$months);
            break;
        case 'DAY' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$days);
            break;
        case 'HOUR' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$hours);
            break;
        case 'MINUTE' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$minutes);
            break;
        case 'SECOND' :
            $dateDiff&nbsp;=&nbsp;sprintf($formats[$diffFormat],&nbsp;$seconds);
            break;
    }
    
    return $dateDiff;
}
/**
 * 时间差计算
 *
 * @param Timestamp $time
 * @return String Time Elapsed
 * @author Shelley Shyan
 * @copyright http://phparch.cn (Professional PHP Architecture)
 */
function time2Units ($time)
{
   $year&nbsp;&nbsp;&nbsp;=&nbsp;floor($time / 60 / 60 / 24 / 365);
   $time&nbsp;&nbsp;-=&nbsp;$year  60  60  24  365;
   $month&nbsp;&nbsp;=&nbsp;floor($time / 60 / 60 / 24 / 30);
   $time&nbsp;&nbsp;-=&nbsp;$month  60  60  24  30;
   $week&nbsp;&nbsp;&nbsp;=&nbsp;floor($time / 60 / 60 / 24 / 7);
   $time&nbsp;&nbsp;-=&nbsp;$week  60  60  24  7;
   $day&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;floor($time / 60 / 60 / 24);
   $time&nbsp;&nbsp;-=&nbsp;$day  60  60 * 24;
   $hour&nbsp;&nbsp;&nbsp;=&nbsp;floor($time / 60 / 60);
   $time&nbsp;&nbsp;-=&nbsp;$hour  60  60;
   $minute&nbsp;=&nbsp;floor($time / 60);
   $time&nbsp;&nbsp;-=&nbsp;$minute * 60;
   $second&nbsp;=&nbsp;$time;
   $elapse = '';

   $unitArr = array('年'  =>'year', '个月'=>'month',  '周'=>'week', '天'=>'day',
                    '小时'=>'hour', '分钟'=>'minute', '秒'=>'second'
                    );

   foreach ( $unitArr&nbsp;as&nbsp;$cn => $u )
   {
       if ( $$u > 0 )
       {
           $elapse&nbsp;=&nbsp;$$u . $cn;
           break;
       }
   }

   return $elapse;
}

/**
 * 获得几天前,几小时前,几月前
 * @param int $time 时间戳
 * @param array $unit 时间单位
 * @return bool|string
 */
function date_before($time,&nbsp;$unit = null) {
    $time&nbsp;=&nbsp;intval($time);
    $unit&nbsp;=&nbsp;is_null($unit) ? array("年", "月", "星期", "天", "小时", "分钟", "秒") : $unit;
    switch (true) {
        case $time < (NOW - 31536000) :
            return floor((NOW - $time)&nbsp;/&nbsp;31536000)&nbsp;.&nbsp;$unit[0] . '前';
        case $time < (NOW - 2592000) :
            return floor((NOW - $time)&nbsp;/&nbsp;2592000)&nbsp;.&nbsp;$unit[1] . '前';
        case $time < (NOW - 604800) :
            return floor((NOW - $time)&nbsp;/&nbsp;604800)&nbsp;.&nbsp;$unit[2] . '前';
        case $time < (NOW - 86400) :
            return floor((NOW - $time)&nbsp;/&nbsp;86400)&nbsp;.&nbsp;$unit[3] . '前';
        case $time < (NOW - 3600) :
            return floor((NOW - $time)&nbsp;/&nbsp;3600)&nbsp;.&nbsp;$unit[4] . '前';
        case $time < (NOW - 60) :
            return floor((NOW - $time)&nbsp;/&nbsp;60)&nbsp;.&nbsp;$unit[5] . '前';
        default :
            return floor(NOW - $time)&nbsp;.&nbsp;$unit[6] . '前';
    }
}
/**
 * 根据一个时间戳得到详细信息
 * @param  [type] $time [时间戳]
 * @return [type]      
 * @author [yangsheng@yahoo.com]
 */
function getDateInfo($time){
    $day_of_week_cn=array("日","一","二","三","四","五","六"); //中文星期
    $week_of_month_cn = array('','第1周','第2周','第3周','第4周','第5周','第6周');#本月第几周
    $tenDays=&nbsp;getTenDays(date(&#39;j&#39;,$time)); #获得旬
    $quarter&nbsp;=&nbsp;getQuarter(date(&#39;n&#39;,$time),date('Y',$time));# 获取季度
     
    $dimDate = array(
        'date_key' => strtotime(date('Y-m-d',$time)), #日期时间戳
        'date_day' => date('Y-m-d',$time), #日期YYYY-MM-DD
        'current_year' => date('Y',$time),#数字年
        'current_quarter' => $quarter['current_quarter'], #季度
        'quarter_cn' =>$quarter['quarter_cn'],
        'current_month' =>date('n',$time),#月
        'month_cn' =>date('Y-m',$time), #月份
        'tenday_of_month' =>$tenDays['tenday_of_month'],#数字旬
        'tenday_cn' =>$tenDays['tenday_cn'],#中文旬
        'week_of_month' =>ceil(date('j',$time)/7), #本月第几周
        'week_of_month_cn' =>$week_of_month_cn[ceil(date(&#39;j&#39;,$time)/7)],#中文当月第几周
        'day_of_year' =>date('z',$time)+1,  #年份中的第几天
        'day_of_month' =>date('j',$time),#得到几号
        'day_of_week' =>date('w',$time)&gt;0&nbsp;?&nbsp;date(&#39;w&#39;,$time):7,#星期几
        'day_of_week_cn' =>'星期'.$day_of_week_cn[date(&#39;w&#39;,$time)],
     );
    return $dimDate;
}
/**
 * 获得日期是上中下旬
 * @param  [int] $j [几号]
 * @return [array]    [description]
 * @author [yangsheng@yahoo.com]
 */
function getTenDays($j)
{  
    $j&nbsp;=&nbsp;intval($j);
     if($j&nbsp;&lt;&nbsp;1&nbsp;||&nbsp;$j > 31){
        return false;#不是日期
    }
   $tenDays&nbsp;=&nbsp;ceil($j/10);
    switch ($tenDays) {
        case 1:#上旬
            return array('tenday_of_month'=>1,'tenday_cn'=>'上旬',);
            break;
        case 2:#中旬
             return array('tenday_of_month'=>2,'tenday_cn'=>'中旬',);
            break;       
        default:#下旬
            return array('tenday_of_month'=>3,'tenday_cn'=>'下旬',);
            break;
    }
    return false;
}
/**
 * 根据月份获得当前第几季度
 * @param  [int] $n [月份]
 * @param  [int] $y [年]
 * @return [array]    [description]
 */
function getQuarter($n,$y=null){
     $n&nbsp;=&nbsp;intval($n);
    if($n&nbsp;&lt;&nbsp;1&nbsp;||&nbsp;$n > 12){
        return false;   #不是月份
    }
    $quarter&nbsp;=&nbsp;ceil($n/3);
    switch ($quarter) {
        case 1: #第一季度
            return array('current_quarter' => 1, 'quarter_cn'=>$y?$y.'-Q1':'Q1');
            break;
        case 2: #第二季度
            return array('current_quarter' => 2, 'quarter_cn'=>$y?$y.'-Q2':'Q2');
            break;
         case 3: #第三季度
            return array('current_quarter' => 3, 'quarter_cn'=>$y?$y.'-Q3':'Q3');
            break;
         case 4: #第四季度
            return array('current_quarter' => 4, 'quarter_cn'=>$y?$y.'-Q4':'Q4');
            break;
    }
     return false;
}

/**
 * 判断文件或目录是否可写
 * 
 * @param  string
 * @return boolean
 */
function is_really_writable($file)
{
    // If we're on a Unix server with safe_mode off we call is_writable
    if (DIRECTORY_SEPARATOR == '/' and @ini_get('safe_mode') == FALSE)
    {
        return is_writable($file);
    }
    
    // For windows servers and safe_mode "on" installations we'll actually
    // write a file then read it.  Bah...
    if (is_dir($file))
    {
        $file&nbsp;=&nbsp;rtrim($file, '/') . '/is_really_writable_' . md5(rand(1, 100));
        
        if (! @file_put_contents($file, 'is_really_writable() test file'))
        {
            return FALSE;
        }
        else
        {
            @unlink($file);
        }
        
        return TRUE;
    }
    else if (($fp&nbsp;=&nbsp;@fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
    {
        return FALSE;
    }
    
    return TRUE;
}

/**
 * 生成密码种子
 * 
 * @param  integer
 * @return string
 */
function fetch_salt($length = 4)
{
    for ($i&nbsp;=&nbsp;0;&nbsp;$i < $length;&nbsp;$i++)
    {
        $salt .= chr(rand(97, 122));
    }
    
    return $salt;
}

/**
 * 根据 salt 混淆密码
 *
 * @param  string
 * @param  string
 * @return string
 */
function compile_password($password,&nbsp;$salt)
{
    // md5 password...
    if (strlen($password) == 32)
    {
        return md5($password&nbsp;.&nbsp;$salt);
    }
    
    $password&nbsp;=&nbsp;md5(md5($password) . $salt);
    
    return $password;
}
/**
 * 获取数组中随机一条数据
 * 
 * @param  array
 * @return mixed
 */
function array_random($arr)
{
    shuffle($arr);
    
    return end($arr);
}
/**
 * 递归读取文件夹的文件列表
 * 
 * 读取的目录路径可以是相对路径, 也可以是绝对路径, $file_type 为指定读取的文件后缀, 不设置则读取文件夹内所有的文件
 * 
 * @param  string
 * @param  string
 * @return array
 */
function fetch_file_lists($dir,&nbsp;$file_type = null)
{
    if ($file_type)
    {
        if (substr($file_type, 0, 1) == '.')
        {
            $file_type&nbsp;=&nbsp;substr($file_type, 1);
        }
    }
    
    $base_dir&nbsp;=&nbsp;realpath($dir);
    $dir_handle&nbsp;=&nbsp;opendir($base_dir);
    
    $files_list = array();
    
    while (($file&nbsp;=&nbsp;readdir($dir_handle)) !== false)
    {       
        if (substr($file,&nbsp;0,&nbsp;1)&nbsp;!=&nbsp;&#39;.&#39;&nbsp;AND&nbsp;!is_dir($base_dir . '/' . $file))
        {
            if (($file_type&nbsp;AND&nbsp;H::get_file_ext($file, false) == $file_type)&nbsp;OR&nbsp;!$file_type)
            {
                $files_list[]&nbsp;=&nbsp;$base_dir . '/' . $file;
            }
        }
        else if (substr($file,&nbsp;0,&nbsp;1)&nbsp;!=&nbsp;&#39;.&#39;&nbsp;AND&nbsp;is_dir($base_dir . '/' . $file))
        {
            if ($sub_dir_lists&nbsp;=&nbsp;fetch_file_lists($base_dir . '/' . $file,&nbsp;$file_type))
            {
                $files_list&nbsp;=&nbsp;array_merge($files_list, $sub_dir_lists);
            }   
        } 
    }
    
    return $files_list;
}
/**
 * CURL 获取文件内容
 * 
 * 用法同 file_get_contents
 * 
 * @param string
 * @param integerr
 * @return string
 */
function curl_get_contents($url,&nbsp;$timeout = 10)
{
    if (!function_exists('curl_init'))
    {
        throw new Zend_Exception('CURL not support');
    }

    $curl = curl_init();
    
    curl_setopt($curl,&nbsp;CURLOPT_URL,&nbsp;$url);
    curl_setopt($curl,&nbsp;CURLOPT_TIMEOUT,&nbsp;$timeout);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

    if (substr($url, 0, 8) == 'https://')
    {
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    }
    
    $result&nbsp;=&nbsp;curl_exec($curl);
    
    curl_close($curl);
    
    return $result;
}

/**
 * CURL 获取文件内容
 * 
 * 用法同 curl_post_contents
 *  $url = "http://localhost/web_services.php";
 *  $post_data = array ("username" => "bob","key" => "12345");
 * @param string
 * @param integerr
 * @return string
 */
function curl_post_contents($url&nbsp;=&nbsp;&#39;&#39;,&nbsp;$param = ''){
        if (empty($url)&nbsp;||&nbsp;empty($param)) {
            return false;
        }
        $postUrl&nbsp;=&nbsp;$url;
        $curlPost&nbsp;=&nbsp;$param;
        $ch = curl_init(); //初始化curl
        curl_setopt($ch,&nbsp;CURLOPT_URL,&nbsp;$postUrl); //抓取指定网页
        curl_setopt($ch, CURLOPT_HEADER, 0); //设置header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
        curl_setopt($ch,&nbsp;CURLOPT_POSTFIELDS,&nbsp;$curlPost);
        $data&nbsp;=&nbsp;curl_exec($ch); //运行curl
        curl_close($ch);
        show($data);
       // print_r($output);
}
function curl_multi($url){
     if (!is_array($urls)&nbsp;or&nbsp;count($urls) == 0) {
        return false;
    }
    $curl&nbsp;=&nbsp;$text = array();
    $handle = curl_multi_init();
    foreach($urls&nbsp;as&nbsp;$k => $v) {
        $nurl[$k]= preg_replace('~(2+)~ei', "rawurlencode('\1')", $v);
        $curl[$k] = curl_init($nurl[$k]);
        curl_setopt($curl[$k], CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl[$k], CURLOPT_HEADER, 0);
        curl_multi_add_handle ($handle,&nbsp;$curl[$k]);
    }
    $active = null;
    do {
        $mrc&nbsp;=&nbsp;curl_multi_exec($handle, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    while ($active&nbsp;&amp;&amp;&nbsp;$mrc == CURLM_OK) {
        if (curl_multi_select($handle) != -1) {
            do {
                $mrc&nbsp;=&nbsp;curl_multi_exec($handle, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
    }
    foreach ($curl&nbsp;as&nbsp;$k => $v) {
        if (curl_error($curl[$k]) == "") {
        $text[$k] = (string) curl_multi_getcontent($curl[$k]);
        }
        curl_multi_remove_handle($handle,&nbsp;$curl[$k]);
        curl_close($curl[$k]);
    }
    curl_multi_close($handle);
    return $text;

}
/**
 * “抽奖”函数
 *
 * @param integer $first    起始编号
 * @param integer $last     结束编号
 * @param integer $total    获奖人数
 *
 * @return string
 *
*/
function isWinner($first,&nbsp;$last, $total)
{
    $winner = array();
    for ($i=0;;$i++)
    {
        $number&nbsp;=&nbsp;mt_rand($first, $last);
        if (!in_array($number,&nbsp;$winner))
            $winner[]&nbsp;=&nbsp;$number;    // 如果数组中没有该数,将其加入到数组
        if (count($winner)&nbsp;==&nbsp;$total)   break;
    }
    return implode(' ', $winner);
}
 /*
    $token&nbsp;=&nbsp;encrypt($id, 'E', 'qingdou');
    echo '加密:'.encrypt($id, 'E', 'qingdou');
    echo '<br />';
    echo '解密:'.encrypt($token, 'D', 'qingdou');
    函数名称:encrypt
    函数作用:加密解密字符串
    使用方法:
    加密     :encrypt('str','E','qingdou');
    解密     :encrypt('被加密过的字符串','D','qingdou');
    参数说明:
    $string   :需要加密解密的字符串
    $operation:判断是加密还是解密:E:加密   D:解密
    $key      :加密的钥匙(密匙);
    */
    function encrypt($string,$operation,$key='')
    {
        $src  = array("/","+","=");
        $dist = array("_a","_b","_c");
        if($operation==&#39;D&#39;){$string  = str_replace($dist,$src,$string);}
        $key=md5($key);
        $key_length=strlen($key);
        $string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string;
        $string_length=strlen($string);
        $rndkey=$box=array();
        $result='';
        for($i=0;$i<=255;$i++)
        {
            $rndkey[$i]=ord($key[$i%$key_length]);
            $box[$i]=$i;
        }
        for($j=$i=0;$i&lt;256;$i++)
        {
            $j=($j+$box[$i]+$rndkey[$i])%256;
            $tmp=$box[$i];
            $box[$i]=$box[$j];
            $box[$j]=$tmp;
        }
        for($a=$j=$i=0;$i<$string_length;$i++)
        {
            $a=($a+1)%256;
            $j=($j+$box[$a])%256;
            $tmp=$box[$a];
            $box[$a]=$box[$j];
            $box[$j]=$tmp;
            $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256]));
        }
        if($operation=='D')
        {
            if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8))
            {
                return substr($result,8);
            }
            else
            {
                return'';
            }
        }
        else
        {
            $rdate&nbsp;&nbsp;=&nbsp;str_replace(&#39;=&#39;,&#39;&#39;,base64_encode($result));
            $rdate&nbsp;&nbsp;=&nbsp;str_replace($src,$dist,$rdate);
            return $rdate;
        }
    }

/**
 * 简单对称加密算法之加密
 * @param String $string 需要加密的字串
 * @param String $skey 加密EKY
 * @return String 加密后的字符串
 * @author Anyon Zou <cxphp@qq.com>
 */
function encode($string&nbsp;=&nbsp;&#39;&#39;,&nbsp;$skey = '6f918e') {
    $skey&nbsp;=&nbsp;str_split(base64_encode($skey));
    $strArr&nbsp;=&nbsp;str_split(base64_encode($string));
    $strCount&nbsp;=&nbsp;count($strArr);
    foreach ($skey&nbsp;as&nbsp;$key => $value) {
        $key&nbsp;&lt;&nbsp;$strCount && $strArr[$key].=$value;
    }
    return str_replace('=', '6f918e', join('', $strArr));
}

/**
 * 简单对称加密算法之解密
 * @param String $string 需要解密的字串
 * @param String $skey 解密KEY
 * @return String 解密后的字符串
 * @author Anyon Zou <cxphp@qq.com>
 */
function decode($string&nbsp;=&nbsp;&#39;&#39;,&nbsp;$skey = '6f918e') {
    $skey&nbsp;=&nbsp;str_split(base64_encode($skey));
    $strArr&nbsp;=&nbsp;str_split(str_replace(&#39;6f918e&#39;,&nbsp;&#39;=&#39;,&nbsp;$string), 2);
    $strCount&nbsp;=&nbsp;count($strArr);
    foreach ($skey&nbsp;as&nbsp;$key => $value) {
        if ($key&nbsp;&lt;&nbsp;$strCount && $strArr[$key][1] === $value) {
            $strArr[$key] = $strArr[$key][0];
        } else {
            break;
        }
    }
    return base64_decode(join('', $strArr));
}
//=============================插件类 核心方法=====================================
/**
 * 1、电信手机访问,HTTP头会有手机号码值,移动、联通则无。
 *2、文中所提到的插入代码即可获取,纯属子虚乌有,文中的功能是一些做移动网络服务的公司,先向电信、移动、联通官方购买查询接口,该接口是以类似统计代码形式插入到你的网站,然后会有个后台统计系统。最后向其他公司贩卖会员,按数据条数收钱(重复也算),奇贵无比,每次最少续费三万。
 *3、只有移动网络有效(电信手机、移动、联通),其他方式访问无效。
 *(2013-8-16 10:43:10 核总补充:手机型号则是使用 HTTP 头 User-Agent 判断的,非常简单的“技术”,和普通网站程序判断浏览器型号及系统类型的方法一摸一样。)
 *该思路、系统最出自于医疗行业,未来移动互联网是发展方向,估计会扩展到其他行业。
 * [getPhoneNumber 获取访问的手机号码]
 * @return [type] [description]
 */
function getPhoneNumber()

{
       if (isset($_SERVER['HTTP_X_NETWORK_INFO']))
       {
         $str1&nbsp;=&nbsp;$_SERVER['HTTP_X_NETWORK_INFO'];
         $getstr1&nbsp;=&nbsp;preg_replace(&#39;/(.*,)(13[\d]{9})(,.*)/i&#39;,&#39;\\2&#39;,$str1);
         return $getstr1;
       }
       elseif (isset($_SERVER['HTTP_X_UP_CALLING_LINE_ID']))
       {
         $getstr2&nbsp;=&nbsp;$_SERVER['HTTP_X_UP_CALLING_LINE_ID'];
         return $getstr2;
       }
       elseif (isset($_SERVER['HTTP_X_UP_SUBNO']))
       {
         $str3&nbsp;=&nbsp;$_SERVER['HTTP_X_UP_SUBNO'];
         $getstr3&nbsp;=&nbsp;preg_replace(&#39;/(.*)(13[\d]{9})(.*)/i&#39;,&#39;\\2&#39;,$str3);
         return $getstr3;
       }
       elseif (isset($_SERVER['DEVICEID']))
       {
         return $_SERVER['DEVICEID'];
       }
       else
       {
         return false;

       }

}

/**
 * 字节格式化 把字节数格式为 B K M G T 描述的大小
 * @return string
 */
function byte_format($size,&nbsp;$dec=2) {
    $a = array("B", "KB", "MB", "GB", "TB", "PB");
    $pos = 0;
    while ($size >= 1024) {
         $size /= 1024;
           $pos++;
    }
    return round($size,$dec)." ".$a[$pos];
}

/**
 * [get_csv_contents 读取CSV文件,EXCEL处理]
 * @param  [type] $file_target [description]
 * @return [type]              [description]
 */
function get_csv_contents( $file_target ){
    $zou = array();
    $ExcelArr = array();
    $handle&nbsp;&nbsp;=&nbsp;fopen(&nbsp;$file_target, 'r');
  fwrite($handle,chr(0xEF).chr(0xBB).chr(0xBF));
 while ($data&nbsp;=&nbsp;fgetcsv($handle, "", ",")) {
 
  $num&nbsp;=&nbsp;count($data);
  $str = "";
  $row++;
  for ($c=0;&nbsp;$c < $num;&nbsp;$c++) {
        $str&nbsp;.=&nbsp;iconv(&quot;GBK&quot;,&nbsp;&#39;UTF-8&#39;,&nbsp;$data[$c]) .',';
        if($c==2){
            include_once(COMMON_LIB_PATH."Ip/IpLocation.class.php");

            $Ip = new \IpLocation(); // 实例化类
            $location&nbsp;=&nbsp;$Ip->getlocation(trim($data[$c])); // 获取某个IP地址所在的位置
          $str&nbsp;.=&nbsp;&quot;,&quot;.$location['country'].$location['area'].",";
        }

  }

    return $str

 }

 fclose($handle);
}
/**
 * [outputCsv 导出CSV]
 * @param  [type] $data [字符型]
 * @return [type]       [description]
 * $data&nbsp;.=&nbsp;i($result$i][&#39;name&#39;]).&#39;,&#39;.i($result[$i)."\n";  换行用\n
 */
function outputCsv($str){
        $filename = date('YmdHis').".csv";
        header("Content-type:text/csv");
        header("Content-Disposition:attachment;filename=".$filename);
        header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
        header('Expires:0');
        header('Pragma:public');
        echo $str;

 }
/**
 * [val PHP自带的验证规则]
 * @param  [type] $value [description]
 * @return [type]        [description]
 * FILTER_CALLBACK  调用用户自定义函数来过滤数据。
*FILTER_SANITIZE_STRING     去除标签,去除或编码特殊字符。
*FILTER_SANITIZE_STRIPPED   “string” 过滤器的别名。
*FILTER_SANITIZE_ENCODED    URL-encode 字符串,去除或编码特殊字符。
*FILTER_SANITIZE_SPECIAL_CHARS  HTML 转义字符 ‘”<>& 以及 ASCII 值小于 32 的字符。
FILTER_SANITIZE_EMAIL  删除所有字符,除了字母、数字以及 !#$%&’+-/=?^_`{|}~@.[]
FILTER_SANITIZE_URL    删除所有字符,除了字母、数字以及 $-_.+!’(),{}|\^~[]`<>#%”;/?:@&=
*FILTER_SANITIZE_NUMBER_INT     删除所有字符,除了数字和 +-
*FILTER_SANITIZE_NUMBER_FLOAT   删除所有字符,除了数字、+- 以及 .,eE。
*FILTER_SANITIZE_MAGIC_QUOTES   应用 addslashes()。
*FILTER_UNSAFE_RAW  不进行任何过滤,去除或编码特殊字符。
*FILTER_VALIDATE_INT    在指定的范围以整数验证值。
*FILTER_VALIDATE_BOOLEAN    如果是 “1″, “true”, “on” 以及 “yes”,则返回 true,如果是 “0″, “false”, “off”, “no” 以及 “”,则返回 false。否则返回 NULL。
*FILTER_VALIDATE_FLOAT  以浮点数验证值。
*FILTER_VALIDATE_REGEXP     根据 regexp,兼容 Perl 的正则表达式来验证值。
*FILTER_VALIDATE_URL    把值作为 URL 来验证。
*FILTER_VALIDATE_EMAIL  把值作为 e-mail 来验证。
*FILTER_VALIDATE_IP     把值作为 IP 地址来验证。
 */
function filter($str,$type){
    switch ($type) {
        case 'email':
            $filter = FILTER_VALIDATE_EMAIL;
            break;
        case 'url':
            $filter = FILTER_VALIDATE_URL;
            break;
        
        case 'boolean':
            $filter = FILTER_VALIDATE_BOOLEAN;
            break;
        case 'float':
            $filter = FILTER_VALIDATE_FLOAT;
            break;
        case 'preg':
            $filter = FILTER_VALIDATE_REGEXP;
            break;
        
        default:
            $filter = FILTER_VALIDATE_EMAIL;
            break;
    }
    return filter_var($str,&nbsp;$filter);
}
/**
 * [num_to_rmb 数据转成大写]
 * @Author   Jerry
 * @DateTime 2018-01-22T16:22:44+0800
 * @Example  eg:
 * @param    [type]                   $num [description]
 * @return   [type]                        [description]
 */
function num_to_rmb($num){
    $c1 = "零壹贰叁肆伍陆柒捌玖";
    $c2 = "分角元拾佰仟万拾佰仟亿";
    //精确到分后面就不要了,所以只留两个小数位
    $num&nbsp;=&nbsp;round($num, 2); 
    //将数字转化为整数
    $num&nbsp;=&nbsp;$num * 100;
    if (strlen($num) > 10) {
        return "金额太大,请检查";
    } 
    $i = 0;
    $c = "";
    while (1) {
        if ($i == 0) {
            //获取最后一位数字
            $n&nbsp;=&nbsp;substr($num, strlen($num)-1, 1);
        } else {
            $n&nbsp;=&nbsp;$num % 10;
        }
        //每次将最后一位数字转化为中文
        $p1&nbsp;=&nbsp;substr($c1, 3 * $n, 3);
        $p2&nbsp;=&nbsp;substr($c2, 3 * $i, 3);
        if ($n&nbsp;!=&nbsp;&#39;0&#39;&nbsp;||&nbsp;($n == '0' && ($p2&nbsp;==&nbsp;&#39;亿&#39;&nbsp;||&nbsp;$p2 == '万' || $p2 == '元'))) {
            $c&nbsp;=&nbsp;$p1 . $p2&nbsp;.&nbsp;$c;
        } else {
            $c&nbsp;=&nbsp;$p1 . $c;
        }
        $i&nbsp;=&nbsp;$i + 1;
        //去掉数字最后一位了
        $num&nbsp;=&nbsp;$num / 10;
        $num&nbsp;=&nbsp;(int)$num;
        //结束循环
        if ($num == 0) {
            break;
        } 
    }
    $j = 0;
    $slen&nbsp;=&nbsp;strlen($c);
    while ($j&nbsp;&lt;&nbsp;$slen) {
        //utf8一个汉字相当3个字符
        $m&nbsp;=&nbsp;substr($c, $j, 6);
        //处理数字中很多0的情况,每次循环去掉一个汉字“零”
        if ($m&nbsp;==&nbsp;&#39;零元&#39;&nbsp;||&nbsp;$m == '零万' || $m&nbsp;==&nbsp;&#39;零亿&#39;&nbsp;||&nbsp;$m == '零零') {
            $left&nbsp;=&nbsp;substr($c, 0, $j);
            $right&nbsp;=&nbsp;substr($c, $j + 3);
            $c&nbsp;=&nbsp;$left . $right;
            $j&nbsp;=&nbsp;$j-3;
            $slen&nbsp;=&nbsp;$slen-3;
        } 
        $j&nbsp;=&nbsp;$j + 3;
    } 
    //这个是为了去掉类似23.0中最后一个“零”字
    if (substr($c,&nbsp;strlen($c)-3, 3) == '零') {
        $c&nbsp;=&nbsp;substr($c, 0, strlen($c)-3);
    }
    //将处理的汉字加上“整”
    if (empty($c)) {
        return "零元整";
    }else{
        return $c . "整";
    }
}
/**
 * [hidecard 隐藏敏感信息内容]
 * @Author   Jerry
 * @DateTime 2017-12-27T11:40:37+0800
 * @Example  eg:
 * @param    [type]                   $phone [description]
 * @return   [type]                          [description]
 */
function hidecard($cardnum,&nbsp;$type = 1, $default = "")
{
    if (empty($cardnum)) {
        return $default;
    }
    if ($type == 1) {
        //身份证
        $cardnum&nbsp;=&nbsp;substr($cardnum, 0, 3) . str_repeat("*", 12) . substr($cardnum,&nbsp;strlen($cardnum) - 3);
    }
    elseif ($type == 2) {
        //手机号
        $cardnum&nbsp;=&nbsp;substr($cardnum, 0, 3) . str_repeat("*", 5) . substr($cardnum,&nbsp;strlen($cardnum) - 3);
    }
    elseif ($type == 3) {
        //银行卡
        $cardnum&nbsp;=&nbsp;str_repeat(&quot;*&quot;,&nbsp;strlen($cardnum) - 4) . substr($cardnum,&nbsp;strlen($cardnum) - 4);
    }
    elseif ($type == 4)
    //用户名
    {
        $strlen&nbsp;=&nbsp;mb_strlen($cardnum, 'utf-8');
        $firstStr&nbsp;=&nbsp;mb_substr($cardnum, 0, 1, 'utf-8');
        $lastStr&nbsp;=&nbsp;mb_substr($cardnum, -1, 1, 'utf-8');
        $cardnum&nbsp;=&nbsp;$strlen == 2 ? $firstStr&nbsp;.&nbsp;str_repeat(&#39;*&#39;,&nbsp;mb_strlen($cardnum, 'utf-8') - 1) : $firstStr&nbsp;.&nbsp;str_repeat(&quot;*&quot;,&nbsp;$strlen - 2) . $lastStr;;
    }
    return $cardnum;
}</pre><p><br/></p>


  1. >
  2. :/.
(秒杀应用)PHP 文件锁

<pre style="max-width:100%;overflow-x:auto;"><span class="hljs-comment">/**
模拟秒杀活动-- 商品100件
CREATE TABLE a
(

id int comment '模拟100件活动商品的数量' 

);
INSERT INTO a VALUES(100);
模仿:以10的并发量访问这个脚本! 使用apache自带的ab.exe软件
*/</span>
error_reporting(<span class="hljs-number">0</span>);
mysql_connect(<span class="hljs-string">'localhost'</span>,<span class="hljs-string">'root'</span>,<span class="hljs-string">'admin123'</span>);
mysql_select_db(<span class="hljs-string">'test'</span>);
<span class="hljs-comment"># php中的文件锁 </span>
$fp = fopen(<span class="hljs-string">'./a.lock'</span>, <span class="hljs-string">'r'</span>); <span class="hljs-comment">// php的文件锁和表没关系,随便一个文件即可 </span>
flock($fp, LOCK_EX);<span class="hljs-comment">// 排他锁 </span>

$rs = mysql_query(<span class="hljs-string">'SELECT id FROM a'</span>);
$id = mysql_result($rs, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
<span class="hljs-keyword">if</span>($id > <span class="hljs-number">0</span>)
{

--$id;  
mysql_query(<span class="hljs-string">'UPDATE a SET id='</span>.$id);  

}
<span class="hljs-comment"># php的文件锁,释放锁 </span>
flock($fp, LOCK_UN);
fclose($fp);
</pre><p>
</p>

查看PHP扩展所带来的相关函数 以scws为例

<pre style="max-width:100%;overflow-x:auto;"><span class="hljs-keyword">if</span> (extension_loaded(<span class="hljs-string">'scws'</span>)) {

$module = <span class="hljs-string">'scws'</span>;
$funcs  = get_extension_funcs($module);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"模块包含以下函数:\n"</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-string">"---------------------------------------\n"</span>;
print_r($funcs);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"---------------------------------------\n"</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-string">"模块版本:\n"</span>;
<span class="hljs-keyword">echo</span> scws_version();

} <span class="hljs-keyword">else</span> {

<span class="hljs-keyword">echo</span> <span class="hljs-string">'模块未找到!&lt;br&gt;'</span>;

}</pre><p>
</p>

php.ini注释

<pre style="max-width:100%;overflow-x:auto;"><code class="javascript hljs" codemark="1">;;;;;;;;;;;
; 警告 ;
;;;;;;;;;;;
; 此配置文件是对于新安装的PHP的默认设置.
; 默认情况下,PHP使用此配置文件安装
; 此配置针对开发目的,并且不是针对生产环境
; 基于一些安全方面的考虑,在你的网站上线之前,请考虑使用php.ini-recommended
; 以及在线文档 https:<span class="hljs-comment">//php.net/manual/en/security.php.</span>

;;;;;;;;;;;;;;;;;;;
; 关于 php.ini ;
;;;;;;;;;;;;;;;;;;;
; 此文件控制了PHP行为的很多方面. 为了让PHP能够读取它
; 必须命名为 <span class="hljs-string">'php.ini'</span>. PHP 在其当前工作目录,由PHPRC环境变量指定目录
; 以及由编译时指定的目录(按此顺序)查找此文件
; 在Windows环境下, 编译时目录是Windows目录.
; 在命令行模式下查找php.ini的目录可以被-c参数覆盖.
;
; 此文件的语法非常简单.
; 空行和由分号开始的行会被忽略(你可能已经猜到了).
; 段的开头(例如 [Foo]) 同样会被悄悄忽略
; 即使在将来他们可能会有其他作用.
;
; 使用以下语法来设定指令:
; directive = value
; 指令 = 值
; 指令名称是 大小写敏感 – foo=bar 和 FOO=bar 是不同的.
;
; 值可以是字符串,数值,PHP常量 (例如 E_ALL 和 M_PI),
; INI 常量 (On, Off, True, False, Yes, No 和 None) 或者一个表达式
; (例如 E_ALL & ~E_NOTICE), 或者带引号的字串 (<span class="hljs-string">"foo"</span>).
;
; 在INI文件中的表达式只能使用逻辑运算和圆括号:
; | 逻辑或
; & 逻辑与
; ~ 逻辑非
; ! 取反
;
; 逻辑标志可以使用<span class="hljs-number">1</span>,On,True或者Yes来打开.
; 也可以使用<span class="hljs-number">0</span>, Off, False 或者 No来关闭.
;
; 在等号后面不写任何内容代表了一个空字符串
; 或者使用 None 关键词:
;
; foo = ; 将foo设置成一个空字串
; foo = none ; 将foo设置成一个空字串
; foo = <span class="hljs-string">"none"</span> ; 将foo设置成字串 <span class="hljs-string">'none'</span>
;
; 如果你在值中使用了常量, 并且这个常量属于一个动态加载的扩展模块
; (不论是PHP扩展还是Zend扩展),
; 那你只能在加载这些扩展 之后 使用这些常量.
;
;
;;;;;;;;;;;;;;;;;;;
; 关于这个文件 ;
;;;;;;;;;;;;;;;;;;;
; 在php.ini-dist 文件中所有的值都相当于内建的默认值
; (就是如果没有使用php.ini, 或者如果你删除了这些行,
; 就和内建的默认值一样).

;;;;;;;;;;;;;;;;;;;;
; 语言选项 ;
;;;;;;;;;;;;;;;;;;;;

; 打开在Apache下的PHP脚本语言引擎
engine = On

; 打开Zend Engine兼容模式(PHP <span class="hljs-number">4.</span>x)
zend.ze1_compatibility_mode = Off

; 允许 标签被认为是PHP脚本.
; 注意: 尽可能避免在开发可重新发布的程序或者库的时候使用简略标签,或者在不受你控制的服务器下发布,
; 因为简略标签可能不被目标服务器支持.为了可移植性, 可重新发布的代码, 请不要使用简略标签
short_open_tag = On

; 使用ASP风格 <% %> 标签.
asp_tags = Off

; 浮点数中数值的有效位数(浮点数精度).
precision = <span class="hljs-number">12</span>

; 强制<span class="hljs-number">2000</span>年兼容 (可能引起不兼容浏览器的问题)
y2k_compliance = On

; 输出缓冲允许在你发送了body内容之后发送header(包括 cookies)
; 代价是稍稍减缓了PHP输出层
; 你可以在运行时调用 output buffering 函数来打开此功能
; 你也可以将此指令设置为On来对所有文件打开输出缓冲
; 如果你想将这个缓冲区限制到特定大小 – 你可以使用最大的字节数来代替<span class="hljs-string">'On'</span>,来作为这个指令的参数 (例如 output_buffering=<span class="hljs-number">4096</span>).
output_buffering = Off

; 你可以将所有你脚本输出的内容重定向到指定函数.
; 例如, 如果你设置 output_handler 到 <span class="hljs-string">"mb_output_handler"</span>,
; 字符编码会被转换成为指定的编码..
; 设置任何的输出处理句柄会自动打开输出缓冲.
; 注意: 如果想编写可移植脚本就不要依赖此INI配置
; 取而代之的是, 明确的使用 ob_start() 来设置输出处理句柄.
; 使用此ini指令可能引起问题,除非你很清楚的理解脚本正在做什么.
; 注意: 你不能同时使用 <span class="hljs-string">"mb_output_handler"</span> 和 <span class="hljs-string">"ob_iconv_handler"</span>
; 并且你不能同时使用 <span class="hljs-string">"ob_gzhandler"</span> 和 <span class="hljs-string">"zlib.output_compression"</span>.
; 注意: 如果使用zlib.output_handler指令开启zlib输出压缩, 该指令必须为空.
;output_handler =

; 使用zlib库对输出进行压缩
; 对此选项的有效值是 <span class="hljs-string">'off'</span>, <span class="hljs-string">'on'</span>, 或者字节数 (用来压缩的缓冲大小 , 默认是 <span class="hljs-number">4</span>KB)
; 注意: 结果的chunk大小可能由于压缩对象的大小而不同.
; PHP输出块的大小一般压缩之后每个大小时几百个字节.
; 如果你希望藉由一个大块的堆大小来获取更好的性能, 需要额外的打开 output_buffering 选项.
; 注意: 你必须使用 zlib.output_handler 来替代标准的
; output_handler, 否则输出可能会有问题.
zlib.output_compression = Off
;zlib.output_compression_level = <span class="hljs-number">-1</span>

; 这里激活 zlib.output_compression 之后,你无法再指定额外的输出处理.
; 这个设置和 output_handler 一样,但是处理顺序不同.
;zlib.output_handler =

; 立即刷新告知 PHP 让输出层在每次输出块之后立刻自动刷新.
; 这和每次调用print()或者echo()函数以及任何一种HTML块后调用flush()一样.
; 打开此选项会严重导致性能下降,一般只有用于调试情况下才建议打开.
implicit_flush = Off

; 如果反序列器找到一个可以作为示例的未定义类.未序列化的回调函数会被调用(使用未定义的类名作为参数),
; 如果特定的函数未被定义或者如果此函数没有包含/实现丢失的类,则会发生一个警告.
; 如果只有你真想要实现类似的回调函数,才设定此入口.
unserialize_callback_func=

; 当浮点和双精度被序列化后,浮点号后由 serialize_precision 指定存储精确度的有效位数.
; 默认值是当浮点数被反序列解码后,数值仍旧相同.
serialize_precision = <span class="hljs-number">100</span>

; 是否打开强制通过引用传递参数给函数
; 此方法被反对并且很有可能在未来版本的PHP/Zend中不再被支持.
; 被孤立的指定的方法是参数应该在函数被声明的时候按照引用传入.
; 你被鼓励来尝试上述方法并关闭此选项来确保你脚本在今后的新版本中仍旧可以正常工作 ( 每次你使用此特性的时候会受到一个警告
; 并且参数会传值而不是传引用).
allow_call_time_pass_reference = On

;
; 安全模式
;
safe_mode = Off

; 默认情况下,安全模式在打开文件时,使用UID来比对检测.
; 如果你只想使用GID做宽松的比对,
; 打开 safe_mode_gid.
safe_mode_gid = Off

; 当 safe_mode 被打开, 此目录下包含的文件和子文件夹的UID/GID 检测会被绕过.
; (目录必须在 include_path 中存在或者必须在包含时使用全路径)
safe_mode_include_dir =

; 当 safe_mode 被打开, 只有在 safe_mode_exec_dir 中定义的可执行文件能够通过exec函数组打开执行.
safe_mode_exec_dir =

; 设定某些的环境变量可能成为潜在的安全隐患.
; 此指令包含一个逗号分隔的前导列表.
; 在安全模式中, 用户可能只能改变符合这里所给出前导字符的变量.
; 默认情况下,用户只能改变以PHP_开头的变量(例如. PHP_FOO=BAR).
;
; 注意: 如果此指令为空, PHP会允许用户修改任何环境变量!
safe_mode_allowed_env_vars = PHP_

; 此指令包含了一个用逗号分隔的环境变量列表, 用户无法通过 putenv() 函数来修改列表中的环境变量.
; 这些变量即便已经在 safe_mode_allowed_env_vars 所设定的列表中,也会被被保护不允许修改.
safe_mode_protected_env_vars = LD_LIBRARY_PATH

; 如果设置了open_basedir, 将会限制文件操作只能是此指令下的目录和子目录.
; 此指令对于每目录或者每虚拟主机配置文件最有意义. 此指令 不会 受安全模式开或者关的影响.
;open_basedir =

; 此指令允许你为了安全原因关闭指定的函数.
; 它接受以逗号分隔的函数名的列表.
; 此指令 不会 受安全模式开或者关的影响.
disable_functions =

; 此指令允许你由于安全原因关闭指定的类.
; 它接受以逗号分隔的类名的列表.
; 此指令 不会 受安全模式开或者关的影响.
disable_classes =

; 语法高亮模式的色彩. 任何在 中可接受的值都可以使用.
;highlight.string = #DD0000
;highlight.comment = #FF9900
;highlight.keyword = #<span class="hljs-number">007700</span>
;highlight.bg = #FFFFFF
;highlight.default = #<span class="hljs-number">0000</span>BB
;highlight.html = #<span class="hljs-number">000000</span>

; 如果打开, 即便用户放弃了的请求也会被执行完成.
; 在执行可能被用户打断或者浏览器超时所中断的请求时打开此选项.
; ignore_user_abort = On

; 指定PHP使用的实际路径的缓冲. 对于PHP打开很多文件来处理很多文件操作的系统上,应该增加此值.
; realpath_cache_size=<span class="hljs-number">16</span>k

; 对于给定文件或者目录的缓冲真实路径信息的缓冲保留秒数. 对于很少修改文件的系统可以考虑增加此值.
; realpath_cache_ttl=<span class="hljs-number">120</span>

;
; 其他
;
; 考虑到PHP可能被其所安装的服务器上暴露的事实(例如. 被web服务器作为头部信息的签名).
; 任何情况下这虽然不是安全威胁, 仍有可能暴露在你的服务器上是否正在使用PHP.
expose_php = On

;;;;;;;;;;;;;;;;;;;
; 资源限制 ;
;;;;;;;;;;;;;;;;;;;

; 每个脚本最大执行秒数
max_execution_time = <span class="hljs-number">30</span>
; 每个脚本用来分析请求数据的最大时间
max_input_time = <span class="hljs-number">60</span>
; 最大输入变量的嵌套级别
;max_input_nesting_level = <span class="hljs-number">64</span>
; 每个脚本能够使用的最大内存数量 (<span class="hljs-number">128</span>MB)
memory_limit = <span class="hljs-number">128</span>M

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 错误处理和记录 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; 错误报告时一个位. 对每一个数值取或可以得到最终的报告级别
; E_ALL – 所有错误和警告 (不包含 E_STRICT)
; E_ERROR – 致命的运行时错误
; E_RECOVERABLE_ERROR – 几乎致命的运行时错误
; E_WARNING – 运行时警告 (非致命错误)
; E_PARSE – 编译时语法错误
; E_NOTICE – 运行时提醒 (这些警告常常由你代码中的bug导致, 但是也有可能是有意的行为 (例如, 使用一个未初始化的变量并依赖于其会被自动初始化成为一个空字符串的事实)
; E_STRICT – 运行时提醒, 打开后PHP会给出针对你代码的最易移植和最好向后兼容性的建议
; E_CORE_ERROR – PHP初始化启动时的致命错误
; E_CORE_WARNING – 在PHP初始化时发生的警告 (非致命错误)
; E_COMPILE_ERROR – 致命的编译时错误
; E_COMPILE_WARNING – 编译时警告 (非致命)
; E_USER_ERROR – 用户产生的错误信息
; E_USER_WARNING – 用户产生的警告信息
; E_USER_NOTICE – 用户产生的提示信息
;
;例子:
;
; – 显示所有错误, 除了提示以及代码标准警告以外
;
;error_reporting = E_ALL & ~E_NOTICE
;
; – 显示所有错误,除了提示以外
;
;error_reporting = E_ALL & ~E_NOTICE | E_STRICT
;
; – 只显示错误
;
;error_reporting = E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR
;
; – 显示出了提示以及代码标准警告之外的错误
;
error_reporting = E_ALL & ~E_NOTICE

; 打印输出错误 (作为输出的一部分). 对于生产环境的网站来说,
; 强烈建议你关闭此选项, 使用错误日志来替代 (详情参考下面内容).
; 在一个生产环境下的web站点打开display_errors可能泄漏安全信息给最终用户, 例如web服务器的文件路径,你数据库的结构或者其他信息.
;
; display_errors可用的值:
;
; Off – 不显示任何错误信息
; stderr – 将错误信息输出到STDERR (只有 CGI/CLI 格式下有效!)
;
;display_errors = <span class="hljs-string">"stderr"</span>
;
; stdout (On) – 输出错误信息到STDOUT上
;
display_errors = On

; 即使 display_errors 打开后,PHP启动序列中发生的错误也不会显示.
; 强烈建议你保持 display_startup_errors 关闭状态, 除非在排错
display_startup_errors = Off

; 将错误输入到日志文件 (服务器指定的log,stderr或者error_log (以下指定))
; 和上面提到的一样, 强烈建议你在生产环境的web站点下使用错误日志来代替错误显示.
log_errors = Off

; 设定log_errors的最大长度. 在 error_log 关于源的信息也计算在内.
; 默认是<span class="hljs-number">1024</span>, 设置为<span class="hljs-number">0</span>可以不限制任何最大长度.
log_errors_max_len = <span class="hljs-number">1024</span>

; 不要记录重复的信息.必须出现在同样文件的相同行之中的才被认为是重复信息,除非 ignore_repeated_source 被设为 <span class="hljs-literal">true</span>.
ignore_repeated_errors = Off

; 当忽略重复消息时忽略消息的来源. 当此设置打开后,不再记录来自不同文件或者不同行的相同消息.
ignore_repeated_source = Off

; 如果此选项被设置为 Off, 那么内存泄漏不会被显示 (不论在stdout还是在日志中).
; 此项仅在debug编译模式下有效, 并且错误报告需要包含 E_WARNING
report_memleaks = On

;report_zend_debug = <span class="hljs-number">0</span>

; 在$php_errormsg中保存最后一次错误/警告消息 (逻辑值).
track_errors = Off

; 关闭在错误信息中所包含的HTML标签.
; 注意: 永远不要再生产环境中使用此特性.
;html_errors = Off

; 如果html_errors 设置为On, 则PHP产生可点击的错误信息,点击后会跳转到描述此错误或者引起此错误的函数具体信息的页面.
; 你可以从 https:<span class="hljs-comment">//www.php.net/docs.php 下载一份PHP手册的副本</span>
; 并且将 docref_root指向你放置本地拷贝的以<span class="hljs-string">'/'</span>开头的.
; 你同时必须指定文件文件的包含点的扩展名.
; 注意: 永远不要再生产环境中使用此特性.
;docref_root = <span class="hljs-string">"/phpmanual/"</span>
;docref_ext = .html

; 在输出的错误信息前加上的字符串.
;error_prepend_string = <span class="hljs-string">""</span>

; 在输出的错误信息之后加上的字符串.
;error_append_string = <span class="hljs-string">""</span>

; 将错误记录到指定文件.
;error_log = filename

; 将错误记录到 syslog (NT系统上的Event Log在Windows <span class="hljs-number">95</span>下不可用).
;error_log = syslog

;;;;;;;;;;;;;;;;;
; 文件处理 ;
;;;;;;;;;;;;;;;;;
;
; 注意 – track_vars 在PHP <span class="hljs-number">4.0</span><span class="hljs-number">.3</span> 中总是打开的

; 在PHP产生的URL中用来分隔参数的符号.
; 默认是 <span class="hljs-string">"&"</span>.
;arg_separator.output = <span class="hljs-string">"&"</span>

; PHP用来将URL分割输入到变量中的分隔符.
; 默认是 <span class="hljs-string">"&"</span>.
; 注意: 所有包含在指令内的字符都会被认为是分隔符!
;arg_separator.input = <span class="hljs-string">";&"</span>

; 此指令描述了PHP注册GET, POST, Cookie, 环境 和 内置变量的顺序 (各自使用G, P, C, E 和 S , 一般使用 EGPCS 或 GPC). 注册使用从左往右的顺序, 新的值会覆盖旧的值.
variables_order = <span class="hljs-string">"EGPCS"</span>

; 是否将EGPCS变量注册成为全局变量.
; 如果你不希望由于用户数据而导致你脚本的全局变量变得凌乱,你需要关闭此选项
; 这个一般随着 track_vars 打开 – 在这种情况下你能够通过$HTTP_*_VARS[]存取所有的GPC变量.
;
; 你应该努力写好脚本这样就不必打开register_globals
; 如果代码不是经过详细的斟酌,那将变量作为全局使用可能很容易导致潜在的安全漏洞.
register_globals = Off

; 是否注册老形式的输入数组, HTTP_GET_VARS 和相关数组
; 如果你不使用他们,建议为了提高性能关闭他们.
register_long_arrays = On

; 此指令让PHP确认是否申明 argv&argc 变量 (这些变量会包含GET信息).
; 如果你不使用这些变量,为了提升性能应该关闭此选项.
register_argc_argv = On

; 当打开此项, SERVER 和 ENV 变量将在第一次被使用时而不是脚本一开始时创建(运行时)
; 如果这些变量在脚本中没有被使用过, 打开此项会增加一点性能.
; 为了使此指令有效,PHP指令 register_globals, register_long_arrays,
; 以及 register_argc_argv 必须被关闭.
auto_globals_jit = On

; PHP可以接受的最大的POST数据大小.
post_max_size = <span class="hljs-number">8</span>M

; Magic quotes
;

; 针对GET/POST/Cookie数据打开Magic quotes.
magic_quotes_gpc = On

; 针对实时产生的数据打开Magic quotes, 例如从SQL获取的数据, 从exec()返回的数据等等.
magic_quotes_runtime = Off

; 使用 Sybase 风格的 magic quotes (使用<span class="hljs-string">"来引导'替代\').
magic_quotes_sybase = Off

; 在任何PHP文档之前或之后自动增加文件.
auto_prepend_file =
auto_append_file =

; 和 4.0b4一样, PHP 总是使用默认在头 Content-type: 的编码输出字符.
; 将其设置为空可以禁用发送字符集.
;
; PHP内建默认为text/html
default_mimetype = "</span>text/html<span class="hljs-string">"
;default_charset = "</span>iso<span class="hljs-number">-8859</span><span class="hljs-number">-1</span>″

; 总是填充 $HTTP_RAW_POST_DATA 变量.
;always_populate_raw_post_data = On

;;;;;;;;;;;;;;;;;;;;;;;;;
; 路径和目录 ;
;;;;;;;;;;;;;;;;;;;;;;;;;

; UNIX: <span class="hljs-string">"/path1:/path2″
;include_path = "</span>.:<span class="hljs-regexp">/php/i</span>ncludes<span class="hljs-string">"
;
; Windows: "</span>\path1;\path2″
;include_path = <span class="hljs-string">".;c:\php\includes"</span>

; PHP页面的根路径, 只有非空时有效.
; 如果PHP没有使用FORCE_REDIRECT来编译, 如果你将php作为CGI运行在任何web服务器下(除了IIS)的话,你必须设置doc_root
; 针对安全问题查看文档. 一种替代方案是使用下面的cgi.force_redirect
doc_root =

; PHP使用/~username打开脚本的目录,非空时才有效.
user_dir =

; 可加载的扩展(模块)的目录位置.
extension_dir = <span class="hljs-string">"./"</span>

; 是否启用 dl() 函数. dl() 函数无法正常的在多线程服务下运行, 例如IIS或者Zeus, 并在在这些服务软件下会自动禁用.
enable_dl = On

; 在绝大多数web服务器下,cgi.force_redirect 对于提供安全执行PHP作为CGI来说是很有必要的.
; 没有配置的情况下,PHP会默认打开此项.
; 你可以在这里关闭此项并且自己承担风险
; 你可以在IIS安全的关闭此项,事实上,你必须关闭此项.
; cgi.force_redirect = <span class="hljs-number">1</span>

; 如果 cgi.nph 被打开,就会强制CGI在每个请求时发送Status: <span class="hljs-number">200.</span>
; cgi.nph = <span class="hljs-number">1</span>

; 如果cgi.force_redirect被打开,并且你没有在Apache或者Netscape(iPlanet) web服务器下运行,
; 你也许需要设置一个环境变量名让PHP来查找让其可以获取后继续执行. 设置此变量可能引起安全问题, 在设置之前请先了解可能引起的后果.
; cgi.redirect_status_env = ;

; cgi.fix_pathinfo 为CGI提供 真实 PATH_INFO/PATH_TRANSLATED 支持.
; PHP的预处理行为是设置 PATH_TRANSLATED 到 SCRIPT_FILENAME, 并且不去猜测 PATH_INFO 是什么.
; 想获取关于 PATH_INFO 更多的信息, 查看 cgi 规范.
; 将此值设置为<span class="hljs-number">1</span>会引起PHP CGI修正它的路径来符合规范.
; 设置为<span class="hljs-number">0</span>会引起PHP类似前面的行为. 默认是<span class="hljs-number">1.</span> 你应该修正你的脚本来使用 SCRIPT_FILENAME 而不是 PATH_TRANSLATED.
; cgi.fix_pathinfo=<span class="hljs-number">0</span>

; 在IIS下的FastCGI (在基于 WINNT 的操作系统下) 支持莫让呼叫客户端的安全令牌的能力.
; 这使得IIS能够定义其下运行的安全上下文.
; 在Apache下的mod_fastcgi 目前不支持此特性 (<span class="hljs-number">03</span>/<span class="hljs-number">17</span>/<span class="hljs-number">2002</span>)
; 如果运行在IIS下设置为<span class="hljs-number">1.</span> 默认是<span class="hljs-number">0.</span>
; fastcgi.impersonate = <span class="hljs-number">1</span>;

; 关闭通过 FastCGI 连接的日志
; fastcgi.logging = <span class="hljs-number">0</span>

; cgi.rfc2616_headers 配置选项告知 PHP 当发送HTTP响应代码时使用什么类型的头
; 如果设置为<span class="hljs-number">0</span>,PHP发送被Apache支持的 Status: 头信息.
; 当设置为<span class="hljs-number">1</span>, PHP会发送 RFC2616 兼容的头信息.
; 默认为<span class="hljs-number">0.</span>
; cgi.rfc2616_headers = <span class="hljs-number">0</span>

;;;;;;;;;;;;;;;;
; 文件上传 ;
;;;;;;;;;;;;;;;;

; 是否允许HTTP文件上传.
file_uploads = On

; 对于HTTP上传文件的临时文件目录 (如果没有指定则会使用系统默认).
;upload_tmp_dir =

; 允许上传的最大文件大小.
upload_max_filesize = <span class="hljs-number">2</span>M

;;;;;;;;;;;;;;;;;;
; Fopen 包装 ;
;;;;;;;;;;;;;;;;;;

; 是否允许将URL作为文件 (例如 https:<span class="hljs-comment">// 或者 ftp://) .</span>
allow_url_fopen = On

; 是否允许 include/<span class="hljs-built_in">require</span> 将URL作为文件 (例如 https:<span class="hljs-comment">// 或者 ftp://) .</span>
allow_url_include = Off

; 定义匿名ftp密码 (你的电子邮件地址)
;<span class="hljs-keyword">from</span>=<span class="hljs-string">"john@doe.com"</span>

; 定义 User-Agent 字符串
; user_agent=<span class="hljs-string">"PHP"</span>

; 定义基于流的socket接口的超时时间 (秒)
default_socket_timeout = <span class="hljs-number">60</span>

; 如果你的脚本必须处理从 Macintosh 系统来的文件,
; 或者你运行在一台Mac并且需要从unix或者win32系统上处理文件,
; 设置此标志会引起PHP自动检测这些文件的EOL字符,这样fgets() 和 file() 就可以不用管文件的来源而直接处理了.
; auto_detect_line_endings = Off

;;;;;;;;;;;;;;;;;;;;;;
; 动态扩展 ;
;;;;;;;;;;;;;;;;;;;;;;
;
; 如果你希望扩展自动加载, 使用下列语法:
;
; extension=modulename.extension
;
; 例如,在Windows系统上:
;
; extension=msql.dll
;
; … 或者在 UNIX 下:
;
; extension=msql.so
;
; 注意: 这里应该只是模块的名字;
; 这里不需要模块的目录信息.
; 使用上面的 extension_dir 指令来指定扩展的位置.

; Windows Extensions
; 注意:已经内建了ODBC支持,所以不需要针对ODBC的dll.
; 注意:许多DLL文件位于 extensions/ (PHP <span class="hljs-number">4</span>) 或者 ext/ (PHP <span class="hljs-number">5</span>)目录中,和分割的PECL DLL下载在一起 (PHP <span class="hljs-number">5</span>).
; 确定设置了正确的 extension_dir 指令.

;extension=php_bz2.dll
;extension=php_curl.dll
;extension=php_dba.dll
;extension=php_dbase.dll
;extension=php_exif.dll
;extension=php_fdf.dll
;extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_gmp.dll
;extension=php_ifx.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_ldap.dll
;extension=php_mbstring.dll
;extension=php_mcrypt.dll
;extension=php_mhash.dll
;extension=php_mime_magic.dll
;extension=php_ming.dll
;extension=php_msql.dll
;extension=php_mssql.dll
;extension=php_mysql.dll
;extension=php_mysqli.dll
;extension=php_oci8.dll
;extension=php_openssl.dll
;extension=php_pdo.dll
;extension=php_pdo_firebird.dll
;extension=php_pdo_mssql.dll
;extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_oci8.dll
;extension=php_pdo_odbc.dll
;extension=php_pdo_pgsql.dll
;extension=php_pdo_sqlite.dll
;extension=php_pgsql.dll
;extension=php_pspell.dll
;extension=php_shmop.dll
;extension=php_snmp.dll
;extension=php_soap.dll
;extension=php_sockets.dll
;extension=php_sqlite.dll
;extension=php_sybase_ct.dll
;extension=php_tidy.dll
;extension=php_xmlrpc.dll
;extension=php_xsl.dll
;extension=php_zip.dll

;;;;;;;;;;;;;;;;;;;
; 模块设置 ;
;;;;;;;;;;;;;;;;;;;

[<span class="hljs-built_in">Date</span>]
; 定义date函数使用的默认时区
;date.timezone =

;date.default_latitude = <span class="hljs-number">31.7667</span>
;date.default_longitude = <span class="hljs-number">35.2333</span>

;date.sunrise_zenith = <span class="hljs-number">90.583333</span>
;date.sunset_zenith = <span class="hljs-number">90.583333</span>

[filter]
;filter.default = unsafe_raw
;filter.default_flags =

[iconv]
;iconv.input_encoding = ISO<span class="hljs-number">-8859</span><span class="hljs-number">-1</span>
;iconv.internal_encoding = ISO<span class="hljs-number">-8859</span><span class="hljs-number">-1</span>
;iconv.output_encoding = ISO<span class="hljs-number">-8859</span><span class="hljs-number">-1</span>

[sqlite]
;sqlite.assoc_case = <span class="hljs-number">0</span>

[xmlrpc]
;xmlrpc_error_number = <span class="hljs-number">0</span>
;xmlrpc_errors = <span class="hljs-number">0</span>

[Pcre]
;PCRE 库反响追踪限制.
;pcre.backtrack_limit=<span class="hljs-number">100000</span>

;PCRE 库递归限制.
;请注意如果你设置此项到一个很高的值, 你可能耗尽所有的可用的进程堆并且最终弄宕PHP(由于到达了操作系统强制的堆大小的限制).
;pcre.recursion_limit=<span class="hljs-number">100000</span>

[Syslog]
; 是否定义不同的syslog变量 (例如. $LOG_PID,
; $LOG_CRON, 等等.). 关闭此选项对性能有益.
; 在运行时, 你可以调用 define_syslog_variables() 函数来定义这些变量.
define_syslog_variables = Off

[mail <span class="hljs-function"><span class="hljs-keyword">function</span>]
; 针对<span class="hljs-title">Win32</span>.
<span class="hljs-title">SMTP</span> = <span class="hljs-title">localhost</span>
<span class="hljs-title">smtp_port</span> = 25

; 针对<span class="hljs-title">Win32</span>.
;<span class="hljs-title">sendmail_from</span> = <span class="hljs-title">me</span>@<span class="hljs-title">example</span>.<span class="hljs-title">com</span>

; 针对<span class="hljs-title">Unix</span>. 可以支持参数 (<span class="hljs-params">默认: "sendmail -t -i"</span>).
;<span class="hljs-title">sendmail_path</span> =

; 强制额外的指定的参数被作为扩展参数传送给<span class="hljs-title">sendmail</span>执行文件.
; 这些参数总是替代<span class="hljs-title">mail</span>(<span class="hljs-params"></span>)函数的第五个参数值, 甚至是在安全模式内.
;<span class="hljs-title">mail</span>.<span class="hljs-title">force_extra_parameters</span> =

[<span class="hljs-title">SQL</span>]
<span class="hljs-title">sql</span>.<span class="hljs-title">safe_mode</span> = <span class="hljs-title">Off</span>

[<span class="hljs-title">ODBC</span>]
;<span class="hljs-title">odbc</span>.<span class="hljs-title">default_db</span> = 目前无效
;<span class="hljs-title">odbc</span>.<span class="hljs-title">default_user</span> = 目前无效
;<span class="hljs-title">odbc</span>.<span class="hljs-title">default_pw</span> = 目前无效

; 允许或阻止持久连接.
<span class="hljs-title">odbc</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 在重用前检查连接是否可用.
<span class="hljs-title">odbc</span>.<span class="hljs-title">check_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">odbc</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">odbc</span>.<span class="hljs-title">max_links</span> = -1

; 长字段处理. 返回变量的字节数. 0 意味着略过.
<span class="hljs-title">odbc</span>.<span class="hljs-title">defaultlrl</span> = 4096

; 二进制数据处理. 0 意味着略过, 1按照实际返回, 2 转换到字符.
; 查看 <span class="hljs-title">odbc_binmode</span> 和 <span class="hljs-title">odbc_longreadlen</span> 的文档来获取针对 <span class="hljs-title">uodbc</span>.<span class="hljs-title">defaultlrl</span> 和 <span class="hljs-title">uodbc</span>.<span class="hljs-title">defaultbinmode</span>的解释
<span class="hljs-title">odbc</span>.<span class="hljs-title">defaultbinmode</span> = 1

[<span class="hljs-title">MySQL</span>]
; 允许或阻止持久连接.
<span class="hljs-title">mysql</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">mysql</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">mysql</span>.<span class="hljs-title">max_links</span> = -1

; <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>)默认的端口号. 如果没有设置, <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>) 会使用 <span class="hljs-title">$MYSQL_TCP_PORT</span>
; 或者 位于/<span class="hljs-title">etc</span>/<span class="hljs-title">services</span>的 <span class="hljs-title">mysql</span>-<span class="hljs-title">tcp</span> 入口或者编译时定义的<span class="hljs-title">MYSQL_PORT</span> 值(<span class="hljs-params">按照此顺序查找</span>).
; <span class="hljs-title">Win32</span> 只会查找<span class="hljs-title">MYSQL_PORT</span>值.
<span class="hljs-title">mysql</span>.<span class="hljs-title">default_port</span> =

; 对于本地<span class="hljs-title">MySQL</span>连接的默认<span class="hljs-title">socket</span>名称. 如果为空, 则使用<span class="hljs-title">MySQL</span>内建默认值.
<span class="hljs-title">mysql</span>.<span class="hljs-title">default_socket</span> =

; <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">host</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
<span class="hljs-title">mysql</span>.<span class="hljs-title">default_host</span> =

; <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">user</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
<span class="hljs-title">mysql</span>.<span class="hljs-title">default_user</span> =

; <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">password</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
; 注意在此文件中保存密码一般来说是 糟糕 的主义.
; 任何 使用<span class="hljs-title">PHP</span>的用户可以执行 '<span class="hljs-title">echo</span> <span class="hljs-title">get_cfg_var</span>(<span class="hljs-params">"mysql.default_password"</span>)
; 并且获取到此密码! 而且理所当然, 任何有对此文件读权限的用户都可以获取到此密码.
<span class="hljs-title">mysql</span>.<span class="hljs-title">default_password</span> =

; 连接超时的最大时间 (<span class="hljs-params">秒</span>) , -1 意味着没有限制.
<span class="hljs-title">mysql</span>.<span class="hljs-title">connect_timeout</span> = 60

; 追踪模式. 当 <span class="hljs-title">trace_mode</span> 被打开 (<span class="hljs-params">=On</span>), <span class="hljs-title">table</span>/<span class="hljs-title">index</span> 扫描的警告和<span class="hljs-title">SQL</span>错误会被显示出来.
<span class="hljs-title">mysql</span>.<span class="hljs-title">trace_mode</span> = <span class="hljs-title">Off</span>

[<span class="hljs-title">MySQLi</span>]

; 最大连接数. -1 意味着没有限制.
<span class="hljs-title">mysqli</span>.<span class="hljs-title">max_links</span> = -1

; <span class="hljs-title">mysqli_connect</span>(<span class="hljs-params"></span>)默认的端口号. 如果没有设置, <span class="hljs-title">mysql_connect</span>(<span class="hljs-params"></span>) 会使用 <span class="hljs-title">$MYSQL_TCP_PORT</span>
; 或者 位于/<span class="hljs-title">etc</span>/<span class="hljs-title">services</span>的 <span class="hljs-title">mysql</span>-<span class="hljs-title">tcp</span> 入口或者编译时定义的<span class="hljs-title">MYSQL_PORT</span> 值(<span class="hljs-params">按照此顺序查找</span>).
; <span class="hljs-title">Win32</span> 只会查找<span class="hljs-title">MYSQL_PORT</span>值.
<span class="hljs-title">mysqli</span>.<span class="hljs-title">default_port</span> = 3306

; 对于本地<span class="hljs-title">MySQL</span>连接的默认<span class="hljs-title">socket</span>名称. 如果为空, 则使用<span class="hljs-title">MySQL</span>内建默认值.
<span class="hljs-title">mysqli</span>.<span class="hljs-title">default_socket</span> =

; <span class="hljs-title">mysqli_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">host</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
<span class="hljs-title">mysqli</span>.<span class="hljs-title">default_host</span> =

; <span class="hljs-title">mysqli_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">user</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
<span class="hljs-title">mysqli</span>.<span class="hljs-title">default_user</span> =

; <span class="hljs-title">mysqli_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">password</span>值(<span class="hljs-params">在安全模式中不会生效</span>).
; 注意在此文件中保存密码一般来说是 糟糕 的主义.
; 任何 使用<span class="hljs-title">PHP</span>的用户可以执行 '<span class="hljs-title">echo</span> <span class="hljs-title">get_cfg_var</span>(<span class="hljs-params">"mysqli.default_password"</span>)
; 并且获取到此密码! 而且理所当然, 任何有对此文件读权限的用户都可以获取到此密码.
<span class="hljs-title">mysqli</span>.<span class="hljs-title">default_pw</span> =

; 允许或阻止持久连接.
<span class="hljs-title">mysqli</span>.<span class="hljs-title">reconnect</span> = <span class="hljs-title">Off</span>

[<span class="hljs-title">mSQL</span>]
; 允许或阻止持久连接.
<span class="hljs-title">msql</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">msql</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">msql</span>.<span class="hljs-title">max_links</span> = -1

[<span class="hljs-title">OCI8</span>]
; 打开使用外部认证的授权连接 (<span class="hljs-params">OCI_SYSOPER, OCI_SYSDBA</span>)
;<span class="hljs-title">oci8</span>.<span class="hljs-title">privileged_connect</span> = <span class="hljs-title">Off</span>

; 连接: 每个进程的持久<span class="hljs-title">OCI8</span>连接的最大数, -1 意味着没有限制.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">max_persistent</span> = -1

; 连接: 一个进程允许保持一个空闲持久连接的最大秒数.
; -1意味着空闲持久连接会永远被保持.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">persistent_timeout</span> = -1

; 连接: 当<span class="hljs-title">oci_pconnect</span>(<span class="hljs-params"></span>) 检测一个连接是否有效时每次发起<span class="hljs-title">ping</span>之间必须通过的秒数.
; 当设置为0后, 每个<span class="hljs-title">oci_pconnect</span>(<span class="hljs-params"></span>) 会发起一个<span class="hljs-title">ping</span>. <span class="hljs-title">Using</span> -1 完全关闭<span class="hljs-title">ping</span>.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">ping_interval</span> = 60

; 调优: 此选项打开声明缓冲(<span class="hljs-params">statement cache</span>), 并且指定缓冲多少声明. 使用0关闭声明缓冲.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">statement_cache_size</span> = 20

; 调优: 打开声明预取(<span class="hljs-params">statement prefetch</span>) 并且设置自动在声明执行后被取到行的数量.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">default_prefetch</span> = 10

; 兼容性: 设置为<span class="hljs-title">On</span> 意味着 <span class="hljs-title">oci_close</span>(<span class="hljs-params"></span>) 不会关闭 <span class="hljs-title">oci_connect</span>(<span class="hljs-params"></span>) 和 <span class="hljs-title">oci_new_connect</span>(<span class="hljs-params"></span>) 的连接.
;<span class="hljs-title">oci8</span>.<span class="hljs-title">old_oci_close_semantics</span> = <span class="hljs-title">Off</span>

[<span class="hljs-title">PostgresSQL</span>]
; 允许或阻止持久连接.
<span class="hljs-title">pgsql</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 总是在 <span class="hljs-title">pg_pconnect</span>(<span class="hljs-params"></span>) 时检测断开的持久连接.
; 自动重置特性会引起一点开销.
<span class="hljs-title">pgsql</span>.<span class="hljs-title">auto_reset_persistent</span> = <span class="hljs-title">Off</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">pgsql</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">pgsql</span>.<span class="hljs-title">max_links</span> = -1

; 是否忽略 <span class="hljs-title">PostgreSQL</span> 后端通告消息.
; 通告消息记录会需要一点开销.
<span class="hljs-title">pgsql</span>.<span class="hljs-title">ignore_notice</span> = 0

; 是否记录 <span class="hljs-title">PostgreSQL</span> 后端通告消息.
; 除非 <span class="hljs-title">pgsql</span>.<span class="hljs-title">ignore_notice</span>=0, 否则模块无法记录通告消息
<span class="hljs-title">pgsql</span>.<span class="hljs-title">log_notice</span> = 0

[<span class="hljs-title">Sybase</span>]
; 允许或阻止持久连接.
<span class="hljs-title">sybase</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">sybase</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">sybase</span>.<span class="hljs-title">max_links</span> = -1

;<span class="hljs-title">sybase</span>.<span class="hljs-title">interface_file</span> = "/<span class="hljs-title">usr</span>/<span class="hljs-title">sybase</span>/<span class="hljs-title">interfaces</span>"

; 显示出的消息最小严重程度.
<span class="hljs-title">sybase</span>.<span class="hljs-title">min_error_severity</span> = 10

; 显示出的消息最小严重程度.
<span class="hljs-title">sybase</span>.<span class="hljs-title">min_message_severity</span> = 10

; 兼容老版本<span class="hljs-title">PHP</span> 3.0的模式.
; 如果设为 <span class="hljs-title">on</span>, 会引起 <span class="hljs-title">PHP</span> 自动绑定结果记录的类型到<span class="hljs-title">Sybase</span>的类型,而不是将他们全部按照字符串处理.
; 此兼容模式可能不会永久存在, 所以最好尝试在你代码中需要的地方作出必要的修改, 然后关闭此选项.
<span class="hljs-title">sybase</span>.<span class="hljs-title">compatability_mode</span> = <span class="hljs-title">Off</span>

[<span class="hljs-title">Sybase</span>-<span class="hljs-title">CT</span>]
; 允许或阻止持久连接.
<span class="hljs-title">sybct</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">sybct</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">sybct</span>.<span class="hljs-title">max_links</span> = -1

; 显示出的错误最小严重程度.
<span class="hljs-title">sybct</span>.<span class="hljs-title">min_server_severity</span> = 10

; 显示出的消息最小严重程度.
<span class="hljs-title">sybct</span>.<span class="hljs-title">min_client_severity</span> = 10

[<span class="hljs-title">bcmath</span>]
; 所有<span class="hljs-title">bcmath</span>函数的小数位数
<span class="hljs-title">bcmath</span>.<span class="hljs-title">scale</span> = 0

[<span class="hljs-title">browscap</span>]
;<span class="hljs-title">browscap</span> = <span class="hljs-title">extra</span>/<span class="hljs-title">browscap</span>.<span class="hljs-title">ini</span>

[<span class="hljs-title">Informix</span>]
; 对于 <span class="hljs-title">ifx_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">host</span> (<span class="hljs-params">不会在安全模式被应用</span>).
<span class="hljs-title">ifx</span>.<span class="hljs-title">default_host</span> =

; 对于 <span class="hljs-title">ifx_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">user</span> (<span class="hljs-params">不会在安全模式被应用</span>).
<span class="hljs-title">ifx</span>.<span class="hljs-title">default_user</span> =

; 对于 <span class="hljs-title">ifx_connect</span>(<span class="hljs-params"></span>) 的默认<span class="hljs-title">password</span> (<span class="hljs-params">不会在安全模式被应用</span>).
<span class="hljs-title">ifx</span>.<span class="hljs-title">default_password</span> =

; 允许或阻止持久连接.
<span class="hljs-title">ifx</span>.<span class="hljs-title">allow_persistent</span> = <span class="hljs-title">On</span>

; 持久连接的最大数目. -1 意味着没有限制.
<span class="hljs-title">ifx</span>.<span class="hljs-title">max_persistent</span> = -1

; 最大连接数 (<span class="hljs-params">持久 + 非持久</span>). -1 意味着没有限制.
<span class="hljs-title">ifx</span>.<span class="hljs-title">max_links</span> = -1

; 如果设为 <span class="hljs-title">on</span>, <span class="hljs-title">select</span> 声明返回 <span class="hljs-title">text</span> 段的内容而不是它的<span class="hljs-title">id</span>.
<span class="hljs-title">ifx</span>.<span class="hljs-title">textasvarchar</span> = 0

; 如果设为 <span class="hljs-title">on</span>, <span class="hljs-title">select</span> 声明返回 <span class="hljs-title">byte</span> 段的内容而不是它的<span class="hljs-title">id</span>.
<span class="hljs-title">ifx</span>.<span class="hljs-title">byteasvarchar</span> = 0

; 固定长度字符列的尾部空格会被截去. 可能对 <span class="hljs-title">Informix</span> <span class="hljs-title">SE</span> 用户有帮助.
<span class="hljs-title">ifx</span>.<span class="hljs-title">charasvarchar</span> = 0

; 如果设为 <span class="hljs-title">on</span>, <span class="hljs-title">text</span> 和 <span class="hljs-title">byte</span> 段会被<span class="hljs-title">dump</span>到一个文件而不是在内存中保留它们.
<span class="hljs-title">ifx</span>.<span class="hljs-title">blobinfile</span> = 0

; <span class="hljs-title">NULL</span>会被作为一个空字符串返回, 除非被设为1. 如果设为1, <span class="hljs-title">NULL</span>会被作为字符串'<span class="hljs-title">NULL</span>'返回.
<span class="hljs-title">ifx</span>.<span class="hljs-title">nullformat</span> = 0

[<span class="hljs-title">Session</span>]
; 用来存储/获取数据的处理方法.
<span class="hljs-title">session</span>.<span class="hljs-title">save_handler</span> = <span class="hljs-title">files</span>

; 传送到<span class="hljs-title">save_handler</span>的参数. 在使用文件的情况下, 这里是数据文件被保存的路径.
; 注意: <span class="hljs-title">Windows</span> 用户必须改变此值来使用<span class="hljs-title">PHP</span>的会话函数.
;
; 和在 4.0.1一样, 你可以定义如下路径:
;
; <span class="hljs-title">session</span>.<span class="hljs-title">save_path</span> = "<span class="hljs-title">N</span>;/<span class="hljs-title">path</span>"
;
; 这里的 <span class="hljs-title">N</span> 是一个整数. 使用此参数会在目录内建立一个<span class="hljs-title">N</span>层深度的子目录用来保存<span class="hljs-title">session</span>文件,
; 而不是将所有<span class="hljs-title">session</span>文件保存在同一个/<span class="hljs-title">path</span>目录内.
; 这对你或当你的操作系统在一个目录内保存太多文件时出现问题很有帮助.
; 并且对于处理大量<span class="hljs-title">session</span>的服务器提供更高的效率.
;
; 注意 1: <span class="hljs-title">PHP</span>不会自动创建目录结构. 你可以使用在<span class="hljs-title">ext</span>/<span class="hljs-title">session</span>目录内的脚本来创建目录结构.
; 注意 2: 如果你选择使用子目录来保存<span class="hljs-title">session</span>,请检查下面关于垃圾回收的配置段
;
; 文件存储模块默认使用600模式来创建文件,在使用中你可以改变此选项
;
; <span class="hljs-title">session</span>.<span class="hljs-title">save_path</span> = "<span class="hljs-title">N</span>;<span class="hljs-title">MODE</span>;/<span class="hljs-title">path</span>"
;
; 这里的<span class="hljs-title">MODE</span>由8进制来表示. 注意这里不会覆盖进程的<span class="hljs-title">umask</span>.
;<span class="hljs-title">session</span>.<span class="hljs-title">save_path</span> = "/<span class="hljs-title">tmp</span>"

; 是否使用<span class="hljs-title">cookie</span>.
<span class="hljs-title">session</span>.<span class="hljs-title">use_cookies</span> = 1

;<span class="hljs-title">session</span>.<span class="hljs-title">cookie_secure</span> =

; 这个选项允许管理员去保护那些在<span class="hljs-title">URL</span>中传送<span class="hljs-title">session</span> <span class="hljs-title">id</span>的用户免于被攻击
; 默认是 0.
; <span class="hljs-title">session</span>.<span class="hljs-title">use_only_cookies</span> = 1

; <span class="hljs-title">session</span>的名称 (<span class="hljs-params">作为cookie名称来使用</span>).
<span class="hljs-title">session</span>.<span class="hljs-title">name</span> = <span class="hljs-title">PHPSESSID</span>

; 在请求开始的时候初始化<span class="hljs-title">session</span>.
<span class="hljs-title">session</span>.<span class="hljs-title">auto_start</span> = 0

; <span class="hljs-title">cookie</span>的生存秒数,或者如果为0就直到浏览器重启.
<span class="hljs-title">session</span>.<span class="hljs-title">cookie_lifetime</span> = 0

; <span class="hljs-title">cookie</span>有效的路径.
<span class="hljs-title">session</span>.<span class="hljs-title">cookie_path</span> = /

; <span class="hljs-title">cookie</span>有效的域名.
<span class="hljs-title">session</span>.<span class="hljs-title">cookie_domain</span> =

; 是否将<span class="hljs-title">httpOnly</span>标志增加到<span class="hljs-title">cookie</span>上, 增加后则<span class="hljs-title">cookie</span>无法被浏览器的脚本语言(<span class="hljs-params">例如JavaScript</span>)存取.
<span class="hljs-title">session</span>.<span class="hljs-title">cookie_httponly</span> =

; 用于序列化数据的处理器. <span class="hljs-title">php</span>是标准的<span class="hljs-title">PHP</span>序列化器.
<span class="hljs-title">session</span>.<span class="hljs-title">serialize_handler</span> = <span class="hljs-title">php</span>

; 定义'垃圾回收'进程在每次<span class="hljs-title">session</span>初始化时开始的比例.
; 比例由 <span class="hljs-title">gc_probability</span>/<span class="hljs-title">gc_pisor</span>来得出,
; 例如. 1/100 意味着在每次请求时有1%的机会启动'垃圾回收'进程.

<span class="hljs-title">session</span>.<span class="hljs-title">gc_probability</span> = 1
<span class="hljs-title">session</span>.<span class="hljs-title">gc_pisor</span> = 100

; 在经过以下秒数之后, 存储的数据会被认为是'垃圾'并且被垃圾回收进程清理掉.
<span class="hljs-title">session</span>.<span class="hljs-title">gc_maxlifetime</span> = 1440

; 注意: 如果你使用子目录选项来保存<span class="hljs-title">session</span>文件
; (<span class="hljs-params">查看在上面的session.save_path</span>), 那么垃圾回收就 不会 自动发生.
; 你需要通过一个<span class="hljs-title">shell</span>脚本,<span class="hljs-title">cron</span>或者其他方法来自行处理垃圾回收.
; 例如, 下面的脚本相当于将<span class="hljs-title">session</span>.<span class="hljs-title">gc_maxlifetime</span>设置为 1440 (<span class="hljs-params">1440 秒 = 24 分钟</span>):
; <span class="hljs-title">cd</span> /<span class="hljs-title">path</span>/<span class="hljs-title">to</span>/<span class="hljs-title">sessions</span>; <span class="hljs-title">find</span> -<span class="hljs-title">cmin</span> +24 | <span class="hljs-title">xargs</span> <span class="hljs-title">rm</span>

; <span class="hljs-title">PHP</span> 4.2 和更早版本有一个未公开的 特性/<span class="hljs-title">bug</span> , 此特性允许你在全局初始化一个<span class="hljs-title">session</span>变量,即便 <span class="hljs-title">register_globals</span> 已经被关闭.
; 如果此特性被使用,<span class="hljs-title">PHP</span> 4.3 和更早版本会警告你.
; 你可以关闭此特性并且隔离此警告. 这时候,如果打开<span class="hljs-title">bug_compat_42</span>,那此警告只是被显示出来.

<span class="hljs-title">session</span>.<span class="hljs-title">bug_compat_42</span> = 1
<span class="hljs-title">session</span>.<span class="hljs-title">bug_compat_warn</span> = 1

; 检查<span class="hljs-title">HTTP</span> <span class="hljs-title">Referer</span>来防止带有<span class="hljs-title">id</span>的外部<span class="hljs-title">URL</span>.
; <span class="hljs-title">HTTP_REFERER</span> 必须包含从<span class="hljs-title">session</span>来的这个字段才会被认为是合法的.
<span class="hljs-title">session</span>.<span class="hljs-title">referer_check</span> =

; 从此文件读取多少字节.
<span class="hljs-title">session</span>.<span class="hljs-title">entropy_length</span> = 0

; 在这里指定创建<span class="hljs-title">session</span> <span class="hljs-title">id</span>.
<span class="hljs-title">session</span>.<span class="hljs-title">entropy_file</span> =

;<span class="hljs-title">session</span>.<span class="hljs-title">entropy_length</span> = 16

;<span class="hljs-title">session</span>.<span class="hljs-title">entropy_file</span> = /<span class="hljs-title">dev</span>/<span class="hljs-title">urandom</span>

; 设置为 </span>{nocache,private,public,} 来决定HTTP缓冲的类型
; 留空则防止发送 anti-caching 头.
session.cache_limiter = nocache

; 文档在n分钟之后过期.
session.cache_expire = <span class="hljs-number">180</span>

; trans sid 支持默认关闭.
; 使用 trans sid 可能让你的用户承担安全风险.
; 使用此项必须小心.
; – 用户也许通过email/irc/其他途径发送包含有效的session ID的URL给其他人.
; – 包含有效session ID的URL可能被存放在容易被公共存取的电脑上.
; – 用户可能通过在浏览器历史记录或者收藏夹里面的包含相同的session ID的URL来访问你的站点.
session.use_trans_sid = <span class="hljs-number">0</span>

; 选择hash方法
; <span class="hljs-number">0</span>: MD5 (<span class="hljs-number">128</span> bits)
; <span class="hljs-number">1</span>: SHA<span class="hljs-number">-1</span> (<span class="hljs-number">160</span> bits)
session.hash_function = <span class="hljs-number">0</span>

; 当转换二进制hash数据到可读形式时,每个字符保存时有几位.
;
; <span class="hljs-number">4</span> bits: <span class="hljs-number">0</span><span class="hljs-number">-9</span>, a-f
; <span class="hljs-number">5</span> bits: <span class="hljs-number">0</span><span class="hljs-number">-9</span>, a-v
; <span class="hljs-number">6</span> bits: <span class="hljs-number">0</span><span class="hljs-number">-9</span>, a-z, A-Z, <span class="hljs-string">"-"</span>, <span class="hljs-string">","</span>
session.hash_bits_per_character = <span class="hljs-number">4</span>

; URL rewriter会在已经定义的一组HTML标签内查找URL.
; form/fieldset 是特殊字符; 如果你在这里包含他们, rewriter会增加一个包含信息的隐藏
字段否则就是在URL中附加信息.
; 如果你你想遵守XHTML, 删除form的入口.
; 注意 所有合法的入口都需要一个<span class="hljs-string">"="</span>符号, 甚至是没有任何值的.
url_rewriter.tags = <span class="hljs-string">"a=href,area=href,frame=src,input=src,form=,fieldset="</span>

[MSSQL]
; 允许或阻止持久连接.
mssql.allow_persistent = On

; 持久连接的最大数目. <span class="hljs-number">-1</span> 意味着没有限制.
mssql.max_persistent = <span class="hljs-number">-1</span>

; 最大连接数 (持久 + 非持久). <span class="hljs-number">-1</span> 意味着没有限制.
mssql.max_links = <span class="hljs-number">-1</span>

; 显示出的错误最小严重程度.
mssql.min_error_severity = <span class="hljs-number">10</span>

; 显示出的消息最小严重程度.
mssql.min_message_severity = <span class="hljs-number">10</span>

; PHP <span class="hljs-number">3.0</span> 老版本的兼容模式.
mssql.compatability_mode = Off

; 连接超时
;mssql.connect_timeout = <span class="hljs-number">5</span>

; 查询超时
;mssql.timeout = <span class="hljs-number">60</span>

; 有效范围 <span class="hljs-number">0</span> – <span class="hljs-number">2147483647.</span> 默认 = <span class="hljs-number">4096.</span>
;mssql.textlimit = <span class="hljs-number">4096</span>

; 有效范围 <span class="hljs-number">0</span> – <span class="hljs-number">2147483647.</span> 默认 = <span class="hljs-number">4096.</span>
;mssql.textsize = <span class="hljs-number">4096</span>

; 每批记录的数量限制. <span class="hljs-number">0</span> = 所有记录在一批内.
;mssql.batchsize = <span class="hljs-number">0</span>

; 指定 datetime 和 datetim4 栏如何返回
; On => 返回数据转换到SQL服务器设置的格式
; Off => 使用 YYYY-MM-DD hh:mm:ss 返回
;mssql.datetimeconvert = On

; 当连接到服务器时使用NT验证
mssql.secure_connection = Off

; 指定最大进程数. <span class="hljs-number">-1</span> = 库默认
; msdlib 默认 <span class="hljs-number">25</span>
; FreeTDS 默认 <span class="hljs-number">4096</span>
;mssql.max_procs = <span class="hljs-number">-1</span>

; 指定客户端字符集.
; 如果为空或者没有指定,客户端字符集将会使用freetds.conf的配置
; 只有和FreeTDS编译时会被使用
;mssql.charset = <span class="hljs-string">"ISO-8859-1″

[Assertion]
; 断言(expr); 默认打开.
;assert.active = On

; 对于每个失败断言发起一个PHP警告.
;assert.warning = On

; 默认不要保释.
;assert.bail = Off

; 如果断言失败则调用用户自定义函数.
;assert.callback = 0

; 使用当前 error_reporting() Eval一个表达式. 如果你想要在eval()附近error_reporting(0) ,那设置为true.
;assert.quiet_eval = 0

[COM]
; 包含GUID,IID或者TypeLibs的文件的文件名的文件的路径
;com.typelib_file =
; 允许 Distributed-COM 调用
;com.allow_dcom = true
; 自动注册位于com_load()函数的组件typlib的常量
;com.autoregister_typelib = true
; 注册常量大小写敏感
;com.autoregister_casesensitive = false
; 当有重复常量注册时显示警告
;com.autoregister_verbose = true

[mbstring]
; 内部字符表示的语言.
;mbstring.language = Japanese

; 内部/脚本编码.
; 部分编码无法作为内部编码使用.
; (例如. SJIS, BIG5, ISO-2022-*)
;mbstring.internal_encoding = EUC-JP

; http 输入编码.
;mbstring.http_input = auto

; http 输出编码. mb_output_handler 必须作为函数被注册为输出缓冲
;mbstring.http_output = SJIS

; 按照mbstring.internal_encoding的设置打开自动编码转换
; 当设置为On时,输入字符被转换为内部编码.
; 注意: 不要针对可移植库/应用使用自动编码转换.
;mbstring.encoding_translation = Off

; 自动编码检测序列
; 自动意味着
;mbstring.detect_order = auto

; 当无法将字符从一种转换到另一种时使用的置换符号
;mbstring.substitute_character = none;

; 使用mbstring函数 覆盖(替换) 单字节函数.
; mail(), ereg(), 等等都会被 mb_send_mail(), mb_ereg() 等等覆盖,
; 可以取的值是 0,1,2,4 或者他们的组合.
; 例如, 7 就是覆盖所有函数.
; 0: 不覆盖
; 1: 覆盖 mail() 函数
; 2: 覆盖 str*() 函数
; 4: 覆盖 ereg*() 函数
;mbstring.func_overload = 0

[FrontBase]
;fbsql.allow_persistent = On
;fbsql.autocommit = On
;fbsql.show_timestamp_decimals = Off
;fbsql.default_database =
;fbsql.default_database_password =
;fbsql.default_host =
;fbsql.default_password =
;fbsql.default_user = "</span>_SYSTEM<span class="hljs-string">"
;fbsql.generate_warnings = Off
;fbsql.max_connections = 128
;fbsql.max_links = 128
;fbsql.max_persistent = -1
;fbsql.max_results = 128

[gd]
; 告知jpeg解码器libjpeg警告并且尝试创建一个gd图像. 此警告会被作为一个通告显示
; 默认为关闭
;gd.jpeg_ignore_warning = 0

[exif]
; Exif UNICODE 用户注释会被作为UCS-2BE/UCS-2LE 和 JIS 来进行 JIS处理.
; 当 mbstring.internal_encoding 设置为空,如果有 mbstring 支持,则会自动转换到给出的对应编码设置的编码.
; 对于解码设置你可以在motorola和intel字符序列上进行选择. 解码设置不能设置为空.
;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel = UCS-2LE
;exif.encode_jis =
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel = JIS

[Tidy]
; 当调用tidy时,默认指向tidy配置文件的路径
;tidy.default_config = /usr/local/lib/php/default.tcfg

; tidy是否自动清除和修复输出?
; 警告: 不要在你产生非html内容时使用此项,例如产生动态图片时
tidy.clean_output = Off

[soap]
; 打开或关闭WSDL缓冲特性.
soap.wsdl_cache_enabled=1
; 设置SOAP扩展存放缓冲文件的目录.
soap.wsdl_cache_dir="</span>/tmp<span class="hljs-string">"
; (存活时间) 设置当缓冲文件被用来替换原有缓冲文件的秒数.
soap.wsdl_cache_ttl=86400

; Local Variables:
; tab-width: 4
; End:</span></code></pre><p><br></p>

php跨域

<p>今天在做接口对接时,VUE遇到一个跨域的问题就是用号不能使用,具体原因后面有空再查吧</p><p>##续上,今天查了下上面的问题(参与URL&nbsp;<span style="background-color: rgb(255, 255, 255);">https://juejin.im/entry/584677e279bc440065c79cc2</span>)</p><p><code>Access-Control-Allow-Origin</code>是支持<code></code>,而在<code>Access-Control-Allow-Headers</code>部分却没有提到支持<code></code>通配符。</p><p>所有正确写法&nbsp;</p><pre style="max-width: 100%;"><code class="php hljs" codemark="1">header(<span class="hljs-string">"Access-Control-Allow-Origin: "</span>);
header(<span class="hljs-string">"Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"</span>);</code></pre><p><br></p><p><br></p><pre style="max-width:100%;overflow-x:auto;"><code class="javascript hljs" codemark="1">header(<span class="hljs-string">'Access-Control-Allow-Origin: '</span>*<span class="hljs-string">'</span>); </code></pre><p>改为:<br></p><pre style="max-width:100%;overflow-x:auto;"><code class="javascript hljs" codemark="1"> header(<span class="hljs-string">'Access-Control-Allow-Origin: '</span>.$_SERVER[<span class="hljs-string">'HTTP_ORIGIN'</span>]);

    header(&lt;span class=&quot;hljs-string&quot;&gt;'Access-Control-Allow-Credentials: true'&lt;/span&gt;);
    header(&lt;span class=&quot;hljs-string&quot;&gt;'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'&lt;/span&gt;);
    header(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId&quot;&lt;/span&gt;);
   &lt;/code&gt;&lt;/pre&gt;&lt;p&gt;##以上设置仅为测试环境机器,不建议生产环境,生产环境建议单独配置域名&lt;/p&gt;
echo 用法

无意中看到了一个ECHO 的用法,备注分享下

$str = 'test';
echo &quot;我是一个测试&quot;,$str;
输出:我是一个测试test
53个要点提高PHP编程效率

用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。

  1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍。

  2、$row[’id’] 的速度是$row[id]的7倍。

  3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $str1,$str2。

  4、在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替。

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

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

  7、require_once()代价昂贵。

  8、include文件时尽量使用绝对路径,因为它避免了PHP去include_path里查找文件的速度,解析操作系统路径所需的时间会更少。

  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、错误消息代价昂贵。

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

  19、递增一个全局变量要比递增一个局部变量慢2倍。

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

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

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

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

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

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

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

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

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

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

  (举例如下)

  if (strlen($foo) &lt; 5) { echo “Foo is too short”$$ }

  (与下面的技巧做比较)

  if (!isset($foo{5})) { 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%。

  43、在可以用file_get_contents替代file、fopen、feof、fgets等系列方法的情况下,尽量用file_get_contents,因为他的效率高得多!但是要注意file_get_contents在打开一个URL文件时候的PHP版本问题;

  44、尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;

  45、优化Select SQL语句,在可能的情况下尽量少的进行Insert、Update操作(在update上,我被恶批过);

  46、尽可能的使用PHP内部函数(但是我却为了找个PHP里面不存在的函数,浪费了本可以写出一个自定义函数的时间,经验问题啊!);

  47、循环内部不要声明变量,尤其是大变量:对象(这好像不只是PHP里面要注意的问题吧?);

  48、多维数组尽量不要循环嵌套赋值;

  49、在可以用PHP内部字符串操作函数的情况下,不要用正则表达式;

  50、foreach效率更高,尽量用foreach代替while和for循环;

  51、用单引号替代双引号引用字符串;

  52、“用i+=1代替i=i+1。符合c/c++的习惯,效率还高”;

  53、对global变量,应该用完就unset()掉;

str_replace 该函数返回一个字符串或者数组

<h3>mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &amp;amp;$count ] )&nbsp;</h3><p>&nbsp;该函数返回一个字符串或者数组。该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果。</p><p>&nbsp;之前一直以为str_replace 只能字符串有效果,今天在看手册时发现,<font color="#ff0000">对一维数组value同样有效</font></p><h3>参数</h3><pre style="max-width: 100%;"><code class="javascript hljs" codemark="1">如果 search 和 replace 为数组,那么 str_replace() 将对 subject 做二者的映射替换。如果 replace 的值的个数少于 search 的个数,多余的替换将使用空字符串来进行。如果 search 是一个数组而 replace 是一个字符串,那么 search 中每个元素的替换将始终使用这个字符串。该转换不会改变大小写。

如果 search 和 replace 都是数组,它们的值将会被依次处理。

search
查找的目标值,也就是 needle。一个数组可以指定多个目标。

replace
search 的替换值。一个数组可以被用来指定多重替换。

subject
执行替换的数组或者字符串。也就是 haystack。

如果 subject 是一个数组,替换操作将遍历整个 subject,返回值也将是一个数组。

count
如果被指定,它的值将被设置为替换发生的次数。</code></pre><p>&nbsp;如果是数组,只能一维数组的value有效

测试代码如下</p><pre style="max-width: 100%;"><code class="javascript hljs" codemark="1">$str = <span class="hljs-string">'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'</span>;

  $array = [
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,
    &lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;=&amp;gt;[&lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;'AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA'&lt;/span&gt;]

  ];
  show(str_replace(&lt;span class=&quot;hljs-string&quot;&gt;&quot;A&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;替&quot;&lt;/span&gt;,$str));
  show(str_replace(&lt;span class=&quot;hljs-string&quot;&gt;&quot;A&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;替&quot;&lt;/span&gt;,$array));&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;结果如下&lt;/p&gt;&lt;pre style=&quot;max-width: 100%;&quot;&gt;&lt;code class=&quot;php hljs&quot; codemark=&quot;1&quot;&gt;替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替

<span class="hljs-keyword">Array</span>
(

[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] =&amp;gt; 替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替
[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] =&amp;gt; 替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替
[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;] =&amp;gt; 替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替
[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;] =&amp;gt; 替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替
[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;] =&amp;gt; 替替替BBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJ替替替
[AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA] =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Array&lt;/span&gt;
    (
        [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] =&amp;gt; AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA
        [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] =&amp;gt; AAABBBCCCDDDEEEEFFFGGGGHHHHIIIIJJJJAAA
    )

)</code></pre><p></p><p><br></p>

mysql dump

mysql 5.5 使用MYSQLDUMP 不能直接使用命令行明文密码,不然会报
>Warning: Using a password on the command line interface can be insecure.
在/etc/my.cnf中加入
[mysqldump]
user=root
password=root

然后使用mysqldump
mysqldump --all-databases &gt;/dir

call_user_func_array 用法

call_user_func_array

今天在整理redis用法的时候,遇到一个小问题,就是我们在调一些php-redis的时候,并不是所有的类都需要我们封装。

&lt;?php
    namespace database;
    class Redis
    {
        private $redis;
        //当前数据库ID号
        protected $dbId=0;
        //当前权限认证码
        protected $auth;
        /**
         * 实例化的对象,单例模式.
         * @var \iphp\db\Redis
         */
        static private $_instance=array();
        private  $k;
        //连接属性数组
        protected $attr=array(
            //连接超时时间,redis配置文件中默认为300秒
            'timeout'=&gt;30,
            //选择的数据库。
            'db_id'=&gt;0,
        );
        //什么时候重新建立连接
        protected $expireTime;
        protected $host;
        protected $port;
        public  function __construct($config,$attr=array())
        {
            $this-&gt;attr        =    array_merge($this-&gt;attr,$attr);
            $this-&gt;redis    =    new \Redis();
            $this-&gt;port        =    $config['port'] ? $config['port'] : 6379;
            $this-&gt;host        =    $config['host']? $config['port'] : '127.0.0.1';
            $this-&gt;redis-&gt;connect($this-&gt;host, $this-&gt;port, $this-&gt;attr['timeout']);
            if($config['auth'])
            {
                $this-&gt;auth($config['auth']);
                $this-&gt;auth    =    $config['auth'];
            }
            $this-&gt;expireTime    =    time() + $this-&gt;attr['timeout'];
        }
        /**
         * 得到实例化的对象.
         * 为每个数据库建立一个连接
         * 如果连接超时,将会重新建立一个连接
         * @param array $config
         * @param int $dbId
         * @return \iphp\db\Redis
         */
        public static function getInstance($config, $attr = array())
        {
            //如果是一个字符串,将其认为是数据库的ID号。以简化写法。
            if(!is_array($attr))
            {
                $dbId    =    $attr;
                $attr    =    array();
                $attr['db_id']    =    $dbId;
            }
            $attr['db_id']    =    $attr['db_id'] ? $attr['db_id'] : 0;
            $k    =    md5(implode('', $config).$attr['db_id']);
            if(! (static::$_instance[$k] instanceof self))
            {
                static::$_instance[$k] = new self($config,$attr);
                static::$_instance[$k]-&gt;k        =    $k;
                static::$_instance[$k]-&gt;dbId    =    $attr['db_id'];
                //如果不是0号库,选择一下数据库。
                if($attr['db_id'] != 0){
                    static::$_instance[$k]-&gt;select($attr['db_id']);
                }
            }
            elseif( time() &gt; static::$_instance[$k]-&gt;expireTime)
            {
                static::$_instance[$k]-&gt;close();
                static::$_instance[$k]         =     new self($config,$attr);
                static::$_instance[$k]-&gt;k    =    $k;
                static::$_instance[$k]-&gt;dbId=    $attr['db_id'];
                //如果不是0号库,选择一下数据库。
                if($attr['db_id']!=0){
                    static::$_instance[$k]-&gt;select($attr['db_id']);
                }
            }
            return static::$_instance[$k];
        }
        private function __clone(){}
        /*****************hash表操作函数*******************/
        /**
         * 得到hash表中一个字段的值
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return string|false
         */
        public function hGet($key,$field)
        {
            return $this-&gt;redis-&gt;hGet($key,$field);
        }
        /**
         * 为hash表设定一个字段的值
         * @param string $key 缓存key
         * @param string  $field 字段
         * @param string $value 值。
         * @return bool 
         */
        public function hSet($key,$field,$value)
        {
            return $this-&gt;redis-&gt;hSet($key,$field,$value);
        }
        /**
         * 判断hash表中,指定field是不是存在
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return bool
         */
        public function hExists($key,$field)
        {
            return $this-&gt;redis-&gt;hExists($key,$field);
        }
        /**
         * 删除hash表中指定字段 ,支持批量删除
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return int
         */
        public function hdel($key,$field)
        {
            $fieldArr=explode(',',$field);
            $delNum=0;
            foreach($fieldArr as $row)
            {
                $row=trim($row);
                $delNum+=$this-&gt;redis-&gt;hDel($key,$row);
            }
            return $delNum;
        }
        /**
         * 返回hash表元素个数
         * @param string $key 缓存key
         * @return int|bool
         */
        public function hLen($key)
        {
            return $this-&gt;redis-&gt;hLen($key);
        }

> 然后在使用的时候

namespace app\test\controller;
use app\common\controller\Base;
use database\Redis as redis;
class Index extends Base
{
    public function index(){
        $redis =  redis::getInstance();
    }
}

> 像lSize,sLength这种,我就没必要封装了,用__call回调处理,通过call_user_func_array来传调用PHP-REDIS的方法

&lt;?php
    namespace database;
    class Redis
    {
        private $redis;
        //当前数据库ID号
        protected $dbId=0;
        //当前权限认证码
        protected $auth;
        /**
         * 实例化的对象,单例模式.
         * @var \iphp\db\Redis
         */
        static private $_instance=array();
        private  $k;
        //连接属性数组
        protected $attr=array(
            //连接超时时间,redis配置文件中默认为300秒
            'timeout'=&gt;30,
            //选择的数据库。
            'db_id'=&gt;0,
        );
        //什么时候重新建立连接
        protected $expireTime;
        protected $host;
        protected $port;
        public  function __construct($config,$attr=array())
        {
            $this-&gt;attr        =    array_merge($this-&gt;attr,$attr);
            $this-&gt;redis    =    new \Redis();
            $this-&gt;port        =    $config['port'] ? $config['port'] : 6379;
            $this-&gt;host        =    $config['host']? $config['port'] : '127.0.0.1';
            $this-&gt;redis-&gt;connect($this-&gt;host, $this-&gt;port, $this-&gt;attr['timeout']);
            if($config['auth'])
            {
                $this-&gt;auth($config['auth']);
                $this-&gt;auth    =    $config['auth'];
            }
            $this-&gt;expireTime    =    time() + $this-&gt;attr['timeout'];
        }
        /**
         * 得到实例化的对象.
         * 为每个数据库建立一个连接
         * 如果连接超时,将会重新建立一个连接
         * @param array $config
         * @param int $dbId
         * @return \iphp\db\Redis
         */
        public static function getInstance($config, $attr = array())
        {
            //如果是一个字符串,将其认为是数据库的ID号。以简化写法。
            if(!is_array($attr))
            {
                $dbId    =    $attr;
                $attr    =    array();
                $attr['db_id']    =    $dbId;
            }
            $attr['db_id']    =    $attr['db_id'] ? $attr['db_id'] : 0;
            $k    =    md5(implode('', $config).$attr['db_id']);
            if(! (static::$_instance[$k] instanceof self))
            {
                static::$_instance[$k] = new self($config,$attr);
                static::$_instance[$k]-&gt;k        =    $k;
                static::$_instance[$k]-&gt;dbId    =    $attr['db_id'];
                //如果不是0号库,选择一下数据库。
                if($attr['db_id'] != 0){
                    static::$_instance[$k]-&gt;select($attr['db_id']);
                }
            }
            elseif( time() &gt; static::$_instance[$k]-&gt;expireTime)
            {
                static::$_instance[$k]-&gt;close();
                static::$_instance[$k]         =     new self($config,$attr);
                static::$_instance[$k]-&gt;k    =    $k;
                static::$_instance[$k]-&gt;dbId=    $attr['db_id'];
                //如果不是0号库,选择一下数据库。
                if($attr['db_id']!=0){
                    static::$_instance[$k]-&gt;select($attr['db_id']);
                }
            }
            return static::$_instance[$k];
        }
        private function __clone(){}
        /*****************hash表操作函数*******************/
        /**
         * 得到hash表中一个字段的值
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return string|false
         */
        public function hGet($key,$field)
        {
            return $this-&gt;redis-&gt;hGet($key,$field);
        }
        /**
         * 为hash表设定一个字段的值
         * @param string $key 缓存key
         * @param string  $field 字段
         * @param string $value 值。
         * @return bool 
         */
        public function hSet($key,$field,$value)
        {
            return $this-&gt;redis-&gt;hSet($key,$field,$value);
        }
        /**
         * 判断hash表中,指定field是不是存在
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return bool
         */
        public function hExists($key,$field)
        {
            return $this-&gt;redis-&gt;hExists($key,$field);
        }
        /**
         * 删除hash表中指定字段 ,支持批量删除
         * @param string $key 缓存key
         * @param string  $field 字段
         * @return int
         */
        public function hdel($key,$field)
        {
            $fieldArr=explode(',',$field);
            $delNum=0;
            foreach($fieldArr as $row)
            {
                $row=trim($row);
                $delNum+=$this-&gt;redis-&gt;hDel($key,$row);
            }
            return $delNum;
        }
        /**
         * 返回hash表元素个数
         * @param string $key 缓存key
         * @return int|bool
         */
        public function hLen($key)
        {
            return $this-&gt;redis-&gt;hLen($key);
        }
        /**
     * [__call description]
     * @Author   Jerry
     * @DateTime 2018-08-08T10:48:11+0800
     * @Example  eg:
     * @param    [type]                   $methodName [方法名]
     * @param    [type]                   $argument   [参数]
     * @return   [type]                               [description]
     */
    public function __call($methodName, $argument){

        return call_user_func_array(array($this-&gt;redis, $methodName), $argument);

        
    }
PHP 返出日期时间类型带毫秒
if( !function_exists('current_timestamp'))
{
    /**
     * [current_timestamp 返出日期时间类型带毫秒]
     * @Author   Jerry
     * @DateTime 2018-10-23T11:34:58+0800
     * @Example  eg:
     * @return   [type]                   [description]
     */
    function current_timestamp(){
      // date_default_timezone_set('PRC');
        $mtimestamp = sprintf(&quot;%.3f&quot;, microtime(true)); // 带毫秒的时间戳
        $timestamp = floor($mtimestamp); // 时间戳
        $milliseconds = round(($mtimestamp - $timestamp) * 1000); // 毫秒
        $datetime = date(&quot;Y-m-d H:i:s&quot;, $timestamp) . '.' . $milliseconds;
        return  sprintf(&quot;%s =&gt; %s&quot;, $mtimestamp, $datetime);//1523856374.820 =&gt; 2018-10-13 13:26:14.820
    }
}
php相关转义的函数

htmlspecialchars

> 将与、单双引号、大于和小于号化成HTML格式

&amp; 转成 &amp;amp;
&quot; 转成 &amp;quot;
'  转成 &amp;#039;
&lt; 转成 &amp;lt;
&gt; 转成 &amp;gt;

htmlentities

> 所有字符都转成HTML格式

除上面htmlspecialchars字符外,还包括双字节字符显示成编码等。

addslashes

> 单双引号、反斜线及NULL加上反斜线转义

被改的字符包括单引号 (')、双引号(&quot;)、反斜线 backslash (\) 以及空字符NULL。

stripslashes

> 去掉反斜线字符

去掉字符串中的反斜线字符。若是连续二个反斜线,则去掉一个,留下一个。若只有一个反斜线,就直接去掉。

quotemeta

> 加入引用符号

将字符串中含有 . \\ + * ? [ ^ ] ( $ )等字符的前面加入反斜线 &quot;\&quot; 符号。

nl2br

将换行字符转成&lt;br&gt;

strip_tags

> 去掉HTML及PHP标记

去掉字符串中任何 HTML标记和PHP标记,包括标记封堵之间的内容。注意如果字符串HTML及PHP标签存在错误,也会返回错误。

mysql_real_escape_string

> 转义SQL字符串中的特殊字符

转义 \x00  \n  \r  空格  \  '  &quot; \x1a,针对多字节字符处理很有效。mysql_real_escape_string会判断字符集,mysql_escape_string则不用考虑。

mysql_real_escape_string

> 转义SQL字符串中的特殊字符

转义 \x00  \n  \r  空格  \  '  &quot; \x1a,针对多字节字符处理很有效。mysql_real_escape_string会判断字符集,mysql_escape_string则不用考虑。

base64_decode

> base64解码

对使用 MIME base64 编码的数据进行解码

base64_encode

> base64编码

使用 MIME base64 对数据进行编码

rawurldecode

> URL解码

对已编码的 URL 字符串进行解码

urldecode

> URL解码

解码已编码的 URL 字符串

urlencode

> URL编码

编码 URL 字符串

rawurlencode

> URL编码

按照 RFC 1738 对 URL 进行编码
处理时间的相关方法 日期内容带豪秒和当前毫秒时间戳
if( !function_exists('current_timestamp'))
{
    /**
     * [current_timestamp 返出日期时间类型带毫秒]
     * @Author   Jerry
     * @DateTime 2018-10-23T11:34:58+0800
     * @Example  eg:
     * @return   [type]                   [description]
     */
    function current_timestamp(){
      // date_default_timezone_set('PRC');
        $mtimestamp = sprintf(&quot;%.3f&quot;, microtime(true)); // 带毫秒的时间戳
        $timestamp = floor($mtimestamp); // 时间戳
        $milliseconds = round(($mtimestamp - $timestamp) * 1000); // 毫秒
        return  date(&quot;Y-m-d H:i:s&quot;, $timestamp) . '.' . $milliseconds;
        // return  sprintf(&quot;%s =&gt; %s&quot;, $mtimestamp, $datetime);//1523856374.820 =&gt; 2018-04-16 13:26:14.820
    }
}
if( !function_exists('current_msectime'))
{
    /**
     * [current_msectime 返出毫秒时间戳]
     * @Author   Jerry
     * @DateTime 2018-10-31T19:51:12+0800
     * @Example  eg:
     * @return   [type]                   [description]
     */
    function current_msectime(){
        list($msec, $sec) = explode(' ', microtime());
        return  (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    }
}

JAVA BASE64(HMacSHA256(key, StringToSign)) php 对接处理

今天在对接一个接口的时候,文档用的是一个JAVA的函数进行的加密回传,然后PHP对应的值会有点不一样,记录下

function hash_hmac($StringToSign='',$secret){
      return base64_encode(hash_hmac(&quot;sha256&quot;,$StringToSign, $secret, true));
  }
    
解决SSL connect error及CURLOPT_SSLVERSION 的问题

今天在对接内部关键字处理接口时发生一个报错CURLOPT_SSLVERSION ,因为之前一直用的是HTTP,后观接口地址改为HTTPS。一直报证书问题
文档地址 :http://www.php.net/manual/zh/function.curl-setopt.php

http 请求的CURL

 /**
     * [service description]
     * @Author   Jerry
     * @DateTime 2018-11-24T17:07:50+0800
     * @Example  eg:
     * @param    [type]                   $url    [description]
     * @param    [type]                   $header [description]
     * @param    [type]                   $json   [description]
     * @return   [type]                           [description]
     */
    protected function service($url,$header,$json){
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, &quot;POST&quot;);
        curl_setopt($ch, CURLOPT_POSTFIELDS,$json);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            print curl_error($ch);
        }
        curl_close($ch);
        return  $result;
    }

> 结果一直报SSL: no alternative certificate subject name matches target host name 'xxx.xxx.xxx.xxx',我以为是对方证书的问题

排错后

 protected function service($url,$header,$json){
        $ch = curl_init($url);
      
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, &quot;POST&quot;);
        curl_setopt($ch, CURLOPT_POSTFIELDS,$json);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_SSLVERSION, 4);//设置SSL协议版本号


        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            print curl_error($ch);
        }
        curl_close($ch);
        return  $result;
    }

注意点

CURLOPT_SSLVERSION 值的设定

CURL_SSLVERSION_DEFAULT (0), CURL_SSLVERSION_TLSv1 (1), CURL_SSLVERSION_SSLv2 (2), CURL_SSLVERSION_SSLv3 (3), CURL_SSLVERSION_TLSv1_0 (4), CURL_SSLVERSION_TLSv1_1 (5) , CURL_SSLVERSION_TLSv1_2 (6) 中的其中一个

Note:

你最好别设置这个值,让它使用默认值。 设置为 2 或 3 比较危险,在 SSLv2 和 SSLv3 中有弱点存在。
PHP 对接华为云透传消息DEMO
&lt;?php
/**
 * 华为透传
 */
class demo
{
    private $appSecret = &quot;&quot;;
    private $appId = &quot;&quot;;//用户在华为开发者联盟申请的appId和appSecret(会员中心-&gt;我的产品,点击产品对应的Push服务,点击“移动应用详情”获取)
    private $tokenUrl = &quot;https://login.cloud.huawei.com/oauth2/v2/token&quot;; //获取认证Token的URL
    private $apiUrl = &quot;https://api.push.hicloud.com/pushsend.do&quot;; //应用级消息下发API
    private $accessToken;//下发通知消息的认证Token
    private $tokenExpiredTime;  //accessToken的过期时间
    private $void;//参数组

    /**
     * [void 参数设置]
     * @Author   Jerry
     * @DateTime 2018-10-31T08:45:37+0800
     * @Example  eg:
     * @param    [type]                   $key   [description]
     * @param    [type]                   $value [description]
     * @return   [type]                          [description]
     */
    private function void($key, $value)
    {
        $this-&gt;void[$key] = $value;
    }
    
    /**
     * [send 数据推送方法]
     * @Author   Jerry
     * @DateTime 2018-11-12T20:25:51+0800
     * @Example  eg:
     * @param    array                    $deviceTokens [description]
     * @param    string                   $title        [description]
     * @param    string                   $content      [description]
     * @param    integer                  $actionType   [description]
     * @param    integer                  $msgType      [description]
     * @param    array                    $params       [description]
     * @return   [type]                                 [description]
     */
    public function sends($deviceTokens=[],$title='',$content='',$actionType=3,$msgType=3,$params=[])
    {
        $this-&gt;refreshToken();
        return $this-&gt;sendPushMessage($deviceTokens,$title,$content,$actionType,$msgType,$params);
    }

    /**
     * [refreshToken 获取ke下发通知消息的认证Token]
     * @Author   Jerry
     * @DateTime 2018-10-31T08:44:39+0800
     * @Example  eg:
     * @return   [type]                   [description]
     */
    private function refreshToken()
    {
        $client_secret = $this-&gt;appSecret;
        $client_id = $this-&gt;appId;

        $this-&gt;void = null;

        $this-&gt;void(CURLOPT_POST, 1);
        $this-&gt;void(CURLOPT_HEADER, false);
        $this-&gt;void(CURLOPT_RETURNTRANSFER, true);
        $this-&gt;void(CURLOPT_CONNECTTIMEOUT, 5000);
        $this-&gt;void(CURLOPT_TIMEOUT, 5000);
        $this-&gt;void(CURLOPT_POSTFIELDS, 'grant_type=client_credentials&amp;client_secret=' . $client_secret . '&amp;client_id=' . $client_id);

        $response = $this-&gt;send($this-&gt;tokenUrl, $this-&gt;void);
        $obj = json_decode($response);
        $this-&gt;accessToken = $obj-&gt;access_token;
        $this-&gt;tokenExpiredTime = $this-&gt;msectime() + $obj-&gt;expires_in - 5 * 60 * 1000;
    }

    /**
     * [sendPushMessage 发送Push消息]
     * @Author   Jerry
     * @DateTime 2018-10-31T08:43:47+0800
     * @Example  eg:
     * @param    array                    $deviceTokens [设置TOKEN]
     * @param    string                   $title        [推送标题]
     * @param    string                   $content      [推送内容]
     * @param    integer                  $actionType   [行为类型]
     * @param    integer                  $msgType      [信息类型]
     * @param    array                    $params       [附加参数]
     * @return   [type]                                 [description]
     */
    private function sendPushMessage($deviceTokens=[],$title='',$content='',$actionType=3,$msgType=3,$params=[])
    {
        if ($this-&gt;tokenExpiredTime &lt;= $this-&gt;msectime()) {
            $this-&gt;refreshToken();
        }
        /*PushManager.requestToken为客户端申请token的方法,可以调用多次以防止申请token失败*/
        /*PushToken不支持手动编写,需使用客户端的onToken方法获取*/
        if(!$deviceTokens){
            $deviceTokens[] = 'XXXXXXXXX';## 测试用的设备TOKEN
        }
        // die;
        // dump($deviceTokens);
        //仅通知栏消息需要设置标题和内容,透传消息key和value为用户自定义
        $body = [
            'title'         =&gt; $title?$title:'Push message title',//消息标题
            'content'       =&gt; $content?$content:'Push message content',//消息标题
        ];
        $param = [
            'appPkgName'    =&gt;isset($params['appPkgName'])?$params['appPkgName']:'cn.honor.qinxuan',//定义需要打开的appPkgName
            'intent'        =&gt;'#Intent;action=cn.honor.qinxuan.action.msg;package=cn.honor.qinxuan;end',

        ];
        $action = [
            'param'         =&gt;$param,//消息点击动作参数
            'type'          =&gt;$actionType?$actionType:3,//1 自定义行为:行为由参数intent定义2 打开URL:URL地址由参数url定义3 打开APP:默认值,打开App的首页 注意:富媒体消息开放API不支持。
            

        ];

        $msg = [
            'action'        =&gt;$action,//消息点击动作
            'type'          =&gt;$msgType?$msgType:3,//1 透传异步消息3 系统通知栏异步消息注意:2和4以后为保留后续扩展使用
            'body'          =&gt;$body
        ];
        $ext = [
            'biTag'         =&gt;'Trump',//设置消息标签,如果带了这个标签,会在回执中推送给CP用于检测某种类型消息的到达率和状态。注意:BigTag不能携带下面几个保留字符:逗号‘,’,竖线‘|’,长度不能超过100个字符。
            'icon'          =&gt; '',//自定义推送消息在通知栏的图标,value为一个公网可以访问的URL
            &quot;customize&quot; =&gt;[$params['customize']],##扩展信息
        ];
        
        
        
        #华为PUSH消息总结构体
        $hps = [
            'msg'           =&gt;$msg,
            'ext'           =&gt;$ext,

        ];

        $payload = [
            'hps'           =&gt;$hps, 

        ];

        $postBody = 'access_token=' . urlencode($this-&gt;accessToken) . '&amp;nsp_svc=' . urlencode('openpush.message.api.send') . '&amp;nsp_ts=' . (int)urlencode($this-&gt;msectime()/1000)
            . '&amp;device_token_list=' . urlencode(json_encode($deviceTokens)) . '&amp;payload=' . urlencode(json_encode($payload));
        $postUrl = $this-&gt;apiUrl . '?nsp_ctx=' . urlencode(&quot;{\&quot;ver\&quot;:\&quot;1\&quot;, \&quot;appId\&quot;:\&quot;&quot; . $this-&gt;appId . &quot;\&quot;}&quot;);
        $this-&gt;void = null;
        $this-&gt;void(CURLOPT_POST, 1);
        $this-&gt;void(CURLOPT_HEADER, false);
        $this-&gt;void(CURLOPT_RETURNTRANSFER, 1);
        $this-&gt;void(CURLOPT_BINARYTRANSFER, 1);
        $this-&gt;void(CURLOPT_CONNECTTIMEOUT, 5000);
        $this-&gt;void(CURLOPT_TIMEOUT, 5000);
        $this-&gt;void(CURLOPT_POSTFIELDS, $postBody);
        return $response = $this-&gt;send($postUrl, $this-&gt;void);
    }


   
}
过滤enmoji表情

``
/**

  • [removeEmoji 移除enmoji表情]
  • @Author Jerry
  • @DateTime 2018-12-20T17:55:40+0800
  • @Example eg:
  • @param [type] $message [description]
  • @return [type] [description]
    */
    function removeEmoji($message) {
    $str = preg_replace_callback(

           '/./u',
           function (array $match) {
               return strlen($match[0]) &gt;= 4 ? '' : $match[0];
           },
           $str);
    
    return $str;

}
``

PHP 大数据导出

最近被数据导出搞得够晕的。导出数据只有10W+的数据,但导出一直报内存不够。。。

原思路

1,分页查出数据,然后合并 但是,太消耗内存

新思路

2,分页查出,拼成CSV,追加至CSV文件

以下为逻辑代码

##查出数据
while( $listFlag = $dataObj-&gt;fgetlist($data,$params['filter'],$offset) ){
            $offset++;
            if(!$data)break;
            foreach ($data as $k =&gt;$v) {
                $cloumn = [];
                foreach ($dataObj-&gt;title as $ki =&gt; $vi) {
                    ##转码
                    $v[$ki] = iconv('utf-8', 'gbk', $v[$ki]);
                    ##处理科学计数
                    $cloumn[] = is_numeric($v[$ki])?$v[$ki].&quot;\t&quot;:$v[$ki];
                }
                ##追加至文件
                file_put_contents($name, implode(&quot;,&quot;, $cloumn).&quot;\n&quot;,FILE_APPEND);
            }
             $taskModel-&gt;update( array('complete_date'=&gt;time(),'step'=&gt;&quot;写入第{$offset}页数据,每页&quot;.$dataObj-&gt;limit.&quot;条&quot;), array('key'=&gt;$params['key']) );
        }
PHP 微服务

目前用PHP做微服务的解决方案
要用PHP做微服务必须要搞定微服务的服务注册发现问题

Agent模式
微博采用了这样的方式,在跑PHP-FPM的机器上跑了一个Agent(这个和后面会讲到的Service Mesh的 Sidecar模式很像)
通过Agent去完成服务注册发现,调用方通过Agent去调用。Agent作为一个包裹层。
Agent其实是后面在Service Mesh节提到的Sidecar的雏形。

以Swoole为基础的常驻内存damon模式
Swoole是PHP的一个扩展
使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。
基于Swoole开发的php程序是直接常驻内存damon的方式运行的
所以这样就可以方便的做服务注册和发现了
基于Swoole体系的开源PHP微服务框架有
Swoft
PHP-MSF
GroupCo
SwooleDistributed
Tencent/Tars

phpRaghtWay

http://laravel-china.github.io/php-the-right-way/

emoji表情处理

最近在开发APP接口时候,遇到了emoji表情。这个东东,搞了我好久。。。。之前遇到都是用base64加密处理的,今天特地看了下。

1, mysql&gt;5.5
2, 修改 php.ini

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqld]
init-connect='SET NAMES utf8mb4'
character-set-server=utf8mb4

3,修改以前的表的字符集 utf8mb4
4,修改你要处理表的字段的字符集 utf8mb4
5,连接 PHP 连接代码 chartset utf8mb4

以上设置完后,重启SQL就可保存emoji了

php+redis 限流

思路

用户请求限限流(同接口访问时间限制)

> redis key 接品名+ user_id 每访问一次+1 过期时间为限制访问时间


&lt;?php

/**
 * @brief 公共限流处理
 */
class sysitem_data_cache_commonlimit {
   public  $_scene = 'sysitem';
   public  $_length;
   private $_prefix = '_limit_';
   private $_search_key;
   private $_user_id;
   private $_user_max_limit;##单用户限流数
   private $_max_limit;##当前接口用户数量
   private $_key;
   private $_expireat_time; ##过期时间
   /**
    * [__construct description]
    * @Author   Jerry                    (c84133883)
    * @DateTime 2019-08-02T15:50:58+0800
    * @Example  eg:
    * @param    [type]                   $apiName    [description]
    * @param    [type]                   $user_id    [description]
    */
   public function __construct($params=[]){

    $this-&gt;_user_id         = (int)$params['user_id'];
    $this-&gt;_search_key      = $params['apiName'].$this-&gt;_prefix;
    $this-&gt;_key             = $this-&gt;_search_key.$params['user_id'];
    $this-&gt;_expireat_time   = 60;##配置项
    $this-&gt;_user_max_limit  = 100;##配置项
    $this-&gt;_max_limit       = 100;##配置项

   } 
   /**
    * [userLimit 是否达到单用户接口请求峰值]
    * @Author   Jerry                    (wx621201)
    * @DateTime 2019-08-02T15:35:52+0800
    * @Example  eg:
    * @return   [type]                   [description]
    */
   public function checkUserLimit(){
      if($this-&gt;_user_max_limit==0) return true;//0不限流,不存在防刷,可以购买
      ##如果不存在,说明超过一分钟,给SQL拦截
      $matchNum = $this-&gt;_exists();
      $matchNum = (int)$matchNum?$matchNum:0;
      if($matchNum&gt;$this-&gt;_user_max_limit) return false;##达到限流条件
      $this-&gt;_set($matchNum+1);
      return true;##默认通过
   }
   /**
    * [countLimit 是否达到用户限流数]
    * @Author   Jerry                    (c84133883)
    * @DateTime 2019-08-05T10:26:39+0800
    * @Example  eg:
    * @return   [type]                   [description]
    */
   public function checkCountLimit(){
      if($this-&gt;_max_limit==0) return true;//0不限流
      if($this-&gt;_userCount&gt;$this-&gt;_max_limit){
        return false;
      }else{
        return true;
      }
   }
   /**
    * [_userCount 总用户数]
    * @Author   Jerry                    (wx621201)
    * @DateTime 2019-08-02T15:41:08+0800
    * @Example  eg:
    * @return   [type]                   [description]
    */
   private function _userCount(){
        $list = redis::scene($this-&gt;_scene)-&gt;keys($this-&gt;_search_key.'*');
        return count($list);
   }
   /**
    * [_set description]
    * @Author   Jerry                    (wx621201)
    * @DateTime 2019-08-02T15:45:51+0800
    * @Example  eg:
    * @param    [type]                   $key       [description]
    * @param    [type]                   $value     [description]
    * @param    integer                  $time      [description]
    * @param    string                   $scene     [description]
    */
   private function  _set($value){
        redis::scene($this-&gt;_scene)-&gt;set($this-&gt;_key,$value);
         ##处理过期时间
        $expiretime = time()+(float)$this-&gt;_expireat_time;##1分钟
        redis::scene($this-&gt;_scene)-&gt;expireat($this-&gt;_key,$expiretime);
        return ture;
    }
  /**
   * [_exists 检查是否存在]
   * @Author   Jerry                    (wx621201)
   * @DateTime 2019-08-02T15:45:54+0800
   * @Example  eg:
   * @param    [type]                   $key       [description]
   * @param    string                   $scene     [description]
   * @return   [type]                              [description]
   */
   private function _exists(){
        if(!redis::scene($this-&gt;_scene)-&gt;exists($this-&gt;_key)||!redis::scene($this-&gt;_scene)-&gt;get($this-&gt;_key)){
            return false;
        }
        return redis::scene($this-&gt;_scene)-&gt;get($this-&gt;_key);
    }

 
  

   
}

总的用户限流

求合上面的key数,得出当前所在的用户数量

所有请求限流

思路1 通过IP限流

PHP WINDOS 工具

&gt; phpstudy
&gt; Wampserver64
&gt; PHPCUSTOM (绿色版)

composer 加载本地包
  • 本地包目录结构
cylcode/bear
        ├── src
        ├── tests
        ├── README.md
        ├── composer.json
        └── LICENSE
        /manager
        ├── src
        ├── tests
        ├── README.md
        ├── composer.json
        └── LICENSE
  • 首先定义本地包的目录
composer config repositories.cylcode path ./cylcode
  • 安装本地包
composer require cylcode/bear:dev-master -vvv