标签:errno pex 认证 database 分发 chunk 回滚事务 二次开发 权限
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
php.exe -f "filename"
cd C:\wamp\bin\php\php5.5.12
//^在dos中转义,>新建文件写一行,>>继续写一行
echo ^<?php > test.php
echo phpinfo(); >> test.php
php.exe -f "test.php"
php.exe -r "php代码"
php.exe -r "$i = 10; echo $i;"
标准形式
# php代码后没有其他内容结束标记有时可以省略
<?php
php代码
?>
<script language=”php”>
php代码
</script>
短标签形式(需设置php.ini中short_open_tag = On)
<?
.....这里是php代码
?>
#可省略
<?php
echo 1
?>
#不可省略
<?php
echo 1;
<?php
$v1 = 1;
<?php
$v1 = null;
echo isset($v1);
<?php
$v1 = null;
$v2 = 0;
$v3 = 1;
echo empty($v1)."===";
echo empty($v2)."===";
echo empty($v3)."===";
将一个变量的数据拷贝一份,然后赋值给另一个变量。
将一个变量的引用拷贝一份,然后赋值给另一个变量(将另一个变量指向被引用传递变量的数据)。
一个变量的名是另一个变量。
<?php
$v1 = ‘v2‘;
$v2 = 10;
echo $$v1;//10
PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。
序列化就是将一个变量的数据转换为字符串(并不是类型转换),目的是将该字符串进行存储和传输。
serialize:序列化
unserialize:反序列化
<?php
$arr = array(‘z‘=>1,‘x‘=>2,‘c‘=>3,‘zxc‘);
var_dump($s = serialize($arr));//序列化
file_put_contents(‘./test_serialize‘, $s);
var_dump(unserialize(file_get_contents(‘./test_serialize‘)));//反序列化
常量是一个简单值的标识符(名字),在脚本执行期间该值不能改变。
传统上常量标识符总是大写的。
<?php
define(‘CONST1‘, 123);
const CONST2 = 456;
<?php
define(‘CONST1‘, 123);
echo CONST1;
echo constant(‘CONST1‘);//constant(CONST1)->constant(‘123‘);
defined()返回布尔值
<?php
define(‘CONST1‘, 123);
echo ‘CONST1---‘.defined(‘CONST1‘);
echo ‘CONST2---‘.defined(‘CONST2‘);
<?php
var_dump(PHP_VERSION);
var_dump(PHP_OS);
var_dump(PHP_EOL);
var_dump(M_PI);
var_dump(M_PI_2);
var_dump(M_1_PI);
名字 | 说明 |
---|---|
__LINE__ | 文件中的当前行号。 |
__FILE__ | 文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。 |
__DIR__ | 文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。它等价于 dirname(__FILE__)。除非是根目录,否则目录中名不包括末尾的斜杠。 |
__FUNCTION__ | 函数名称。自 PHP 5起本常量返回该函数被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。 |
__CLASS__ | 类的名称。自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。类名包括其被声明的作用区域(例如 Foo\Bar)。注意自 PHP 5.4 起__CLASS__对 trait 也起作用。当用在 trait 方法中时,__CLASS__是调用 trait 方法的类的名字。 |
__TRAIT__ | Trait 的名字。自 PHP 5.4 起此常量返回 trait 被定义时的名字(区分大小写)。Trait 名包括其被声明的作用区域(例如 Foo\Bar)。 |
__METHOD__ | 类的方法名。返回该方法被定义时的名字(区分大小写)。 |
__NAMESPACE__ | 当前命名空间的名称(区分大小写)。此常量是在编译时定义的。 |
<?php
var_dump(__LINE__);
var_dump(__FILE__);
var_dump(__DIR__);
var_dump(__FUNCTION__);
var_dump(__CLASS__);//get_class()必须有对象才能获得类名
var_dump(__TRAIT__);
var_dump(__METHOD__);
var_dump(__NAMESPACE__);
<?php
var_dump(decbin(123));
var_dump(bindec(‘101010‘));
应该设置在一定精度要求下比较
<?php
$v1 = 1.2/3;
echo ‘$v1=‘."$v1\r\n";
//0.4==0.4不会打印
if($v1 == 0.4){
echo "$v1==0.4\r\n";
}
//设置在0.001的精度下比较
//400==0.4*1000会打印
if(round($v1*1000) == 0.4*1000){
echo ($v1*1000)."==0.4*1000\r\n";
}
<?php
var_dump(12345*1000000);
<?php
$v1 = 123;
echo ‘$v1\r\n‘;
echo "---\r\n";
echo "$v1\r\n";
echo "---\r\n";
echo <<<‘HTML‘
‘html1‘$v1
HTML;//‘html1‘$v1
echo "---\r\n";
/*
HTML;为最后一行报错:
Parse error: syntax error,
unexpected end of file, expecting variable (T_VARIABLE)
or heredoc end (T_END_HEREDOC)
or ${ (T_DOLLAR_OPEN_CURLY_BRACES)
or {$ (T_CURLY_OPEN)
*/
echo <<<"HTML"
"html2"$v1
HTML;//‘html1‘123
//要有一行
true或false两个值
隐式转换为布尔值是为false的是:
<?php
if($v1){
echo ‘yse‘;
}else{
echo ‘no‘;
}
<?php
//使用array定义
$arr1 = array(‘test1‘=>1,‘test2‘=>2,3,4,5);
//使用变量[]定义
$arr2[‘test1‘] = 1;
$arr2[‘test2‘] = 2;
$arr2[] = 3;
$arr2[] = 4;
$arr2[] = 5;
var_dump($arr1, $arr2);
//使用变量[]添加
$arr1[] = 6;
var_dump($arr1);
<?php
//linux使用[]包围数组会报错:Parse error: syntax error, unexpected ‘[‘,不知什么原因
$array1 = array(1,2,‘third‘);
$array2 = array(‘one‘ => 1, ‘two‘ => 2, ‘three‘ => ‘third‘);
$array3 = [1,2,‘third‘];//尽量使用
$array4 = [‘one‘ => 1, ‘two‘ => 2, ‘three‘ => ‘third‘];//尽量使用
var_dump($array1,$array2,$array3,$array4);
数组指针:
<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $key => &$value) {
echo $value;
}
var_dump($arr);//最后一项是5
var_dump($value);//5(没有释放)
foreach ($arr as $key => $value) {
echo $value;
}
var_dump($arr);//最后一项是4
var_dump($value);//4(因为上面的$value引用传递了,最后$value一直指向数组最后一个元素)
$val = 2;
$value = 1;//现在$value还是指向数组最后一个元素
foreach ($arr as $key => $val) {
echo $val;
}
var_dump($arr);//最后一项是1
var_dump($val);//1(虽然foreach结束但$val不是2,而是最后一项数组最后一项的值1)
<?php
$arr = array(‘test1‘=>‘test‘,‘test2‘=>‘test‘,22,33);
echo ‘$value‘;
foreach($arr as $key => $value){
$arr[] = ‘new‘;
echo $value;//没有new
}
echo ‘&$value‘;
foreach($arr as $key => &$value){
//每次加上new会循环这个加上的new,进入循环又会加一个new
$arr[] = ‘new‘;
echo $value;//有new并死循环
}
<?php
$arr = array(‘test1‘=>‘test‘,‘test2‘=>‘test‘,22,33);
reset($arr);//数组指针初始化
$len = count($arr);
for($i=0;$i<$len;$i++){
$key = key($arr);//key
$value = current($arr);//value
echo $key,$value;
next($arr);//指针移到下一个元素
}
<?php
$arr = array(‘test1‘=>‘test‘,‘test2‘=>‘test‘,22,33);
var_dump(each($arr));//四个元素0,1,key,value
list($v1, $v2) = array(‘test‘=>‘test‘,1=>1,2);//将数字索引对应的值放到list的变量中
var_dump($v1, $v2);//null,1
reset($arr);//数组指针初始化
//当each到数组最后的时候,就返回false,即此时循环结束
while(list($key, $value)=each($arr)){
var_dump($key, $value);
}
<?php
$arr = array(10,10,5,4,3,6,1,8);
$len = count($arr);
for($i=0; $i<$len-1; ++$i){
for($j=0; $j<$len-$i-1; ++$j){
($arr[$j] > $arr[$j+1]) && change($arr[$j], $arr[$j+1]);
}
}
function change(&$v1, &$v2){
$v1 += $v2;
$v2 = $v1 - $v2;
$v1 -= $v2;
}
var_dump($arr);
<?php
$arr = array(10,10,5,4,3,6,1,8);
$len = count($arr);
for($i=0; $i<$len-1; ++$i){
$max = 0;
for($j=1; $j<$len-$i; ++$j){
($arr[$j] > $arr[$max]) && $max = $j;
}
($max != $len-$i-1) && change($arr[$len-$i-1], $arr[$max]);
}
function change(&$v1, &$v2){
$v1 += $v2;
$v2 = $v1 - $v2;
$v1 -= $v2;
}
var_dump($arr);
<?php
class myClass{
public $v1 = 123;
public function myfunc(){
echo $this->v1;
}
}
$myobj = new myClass();
echo $myobj->v1;
$myobj->myfunc();
资源 resource 是一种特殊变量,保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。
由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄,因此将其它类型的值转换为资源没有意义。
变量没有指向任何空间
getType(变量名):获取一个变量的类型名称
setType(变量名,目标类型字符串):设置一个变量的类型
is_XX类型()系列函数:判断某个数据是否是某种类型,包括:
<?php
$v1 = 123;
echo getType($v1)."---";
echo setType($v1, ‘string‘)."---";
echo is_int($v1)."---";
echo is_string($v1)."---";
通过语法来让某数据转换为另一种类型的数据
<?php
echo (int) 12.3;
echo (float) 123;
<?php
var_dump((int)"12.3");
var_dump((float)"12.3");
var_dump((int)"12.3a");
var_dump((float)"12.3a");
var_dump((int)"a12.3");
var_dump((float)"a12.3");
+,-,*,/,%(取整后取余),++,--(前++或--效率高)
字符串++:下一字符
null++:1
false++:没用
<?php
$str1 = "abc";
echo ++$str1."---";//abd
$str1 = "张";
echo ++$str1."---";//???
$v1 = null;
echo ++$v1."---";//1
$v2 = false;
echo ++$v2."---";//没用还是false
>,>=,<,<=,==,!=,===,!==
==:数据内容相等
===:数据内容和类型都相等
字符串的比较规则:按字符的先后顺序找到第一个不同的字符当做整个字符串比较大小
<?php
$str123 = "123";
$int123 = 123;
$v1 = $str123 == $int123;
$v2 = $str123 === $int123;
$v3 = "abd" > "abc";
echo "$str123 == $int123 $v1 \r\n";
echo "$str123 === $int123 $v2 \r\n";
echo "‘abc‘ > ‘abd‘ $v3 \r\n";
&&,||,!
逻辑与短路:如果前面是真执行后面的
<?php
!defined(‘BASEPATH‘) && exit(‘No direct script access allowed‘);
逻辑或短路:如果前面是假执行后面的
<?php
defined(‘BASEPATH‘) || exit(‘No direct script access allowed‘);
.,.=
=,+=,-=,*=,/=,%=,.=
数据1 ? 数据2 : 数据3
<?php
$is_show = true;
echo $is_show ? ‘show‘ : ‘hide‘;
&,|,~,^,<<,>>
<?php
$v1 = 1&2;
$v2 = 1|2;
$v3 = ~1;
$v4 = 1^2;
$v5 = 1<<1;
$v6 = 1>>1;
echo "1&1->".$v1.PHP_EOL;//0
echo "1|1->".$v2.PHP_EOL;//3
echo "~1->".$v3.PHP_EOL;//2
echo "1^2->".$v4.PHP_EOL;//3
echo "1<<1->".$v5.PHP_EOL;//2
echo "1>>1->".$v6.PHP_EOL;//0
计算机中的加减法都是:补码+补码=补码(都转换成补码运算)
1:开,0:关
eg:PHP的错误
值 | 常量 | 说明
---|---|---
1| E_ERROR (integer)| 致命的运行时错误。这类错误一般是不可恢复的情况,例如内存分配导致的问题。后果是导致脚本终止不再继续运行。
2| E_WARNING (integer)| 运行时警告 (非致命错误)。仅给出提示信息,但是脚本不会终止运行。
4| E_PARSE (integer)| 编译时语法解析错误。解析错误仅仅由分析器产生。
8| E_NOTICE (integer)| 运行时通知。表示脚本遇到可能会表现为错误的情况,但是在可以正常运行的脚本里面也可能会有类似的通知。
16| E_CORE_ERROR (integer)| 在PHP初始化启动过程中发生的致命错误。该错误类似 E_ERROR,但是是由PHP引擎核心产生的。
32| E_CORE_WARNING (integer)| PHP初始化启动过程中发生的警告 (非致命错误) 。类似 E_WARNING,但是是由PHP引擎核心产生的。
64| E_COMPILE_ERROR (integer)| 致命编译时错误。类似E_ERROR, 但是是由Zend脚本引擎产生的。
128| E_COMPILE_WARNING (integer)| 编译时警告 (非致命错误)。类似 E_WARNING,但是是由Zend脚本引擎产生的。
256| E_USER_ERROR (integer)| 用户产生的错误信息。类似 E_ERROR, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。
512| E_USER_WARNING (integer)| 用户产生的警告信息。类似 E_WARNING, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。
1024| E_USER_NOTICE (integer)| 用户产生的通知信息。类似 E_NOTICE, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。
2048| E_STRICT (integer)| 启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
4096| E_RECOVERABLE_ERROR (integer)| 可被捕捉的致命错误。 它表示发生了一个可能非常危险的错误,但是还没有导致PHP引擎处于不稳定的状态。 如果该错误没有被用户自定义句柄捕获 (参见 set_error_handler()),将成为一个 E_ERROR 从而脚本会终止运行。
8192| E_DEPRECATED (integer)| 运行时通知。启用后将会对在未来版本中可能无法正常工作的代码给出警告。
16384| E_USER_DEPRECATED (integer)| 用户产少的警告信息。 类似 E_DEPRECATED, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。
30719| E_ALL (integer)| E_STRICT出外的所有错误和警告信息。
<?php
echo "NOTICE->".sprintf("%‘016s",decbin(E_ERROR)).PHP_EOL;//致命性运行时错
echo "NOTICE->".sprintf("%‘016s",decbin(E_WARNING)).PHP_EOL;//运行时警告
echo "NOTICE->".sprintf("%‘016s",decbin(E_PARSE)).PHP_EOL;//编译时解析错误
echo "NOTICE->".sprintf("%‘016s",decbin(E_NOTICE)).PHP_EOL;//运行时提醒
echo "STRICT->".sprintf("%‘016s",decbin(E_STRICT)).PHP_EOL;//PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
echo "DEPRECATED->".sprintf("%‘016s",decbin(E_DEPRECATED)).PHP_EOL;//运行时通知
echo "ALL->".sprintf("%‘016s",decbin(E_ALL)).PHP_EOL;//所有的错误和警告
//禁用错误报告
error_reporting(0);
//只显示运行时错误
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//只显示运行时错误和异常
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// 除了 E_NOTICE,报告其他所有错误(这是在 php.ini 里的默认设置)
error_reporting(E_ALL ^ E_NOTICE);
// 报告所有 PHP 错误
error_reporting(E_ALL);
// 报告所有 PHP 错误
error_reporting(-1);
ini_set(‘error_reporting‘, E_ALL);
+,==,!=(<>),===,!==
+:将右边的数组项合并到左边数组的后面,得到一个新数组。如有重复键,则结果以左边的为准。
<?php
$arr1 = array(1,2,3,4);
$arr2 = array(1,4,5,6,7);
var_dump($arr1+$arr2);//1,2,3,4,7
==:两个数组具有相同的键名和键值则返回true。
===:如果两个数组具有相同的键名和键值且顺序和类型都一样。
<?php
$arr1 = array(1=>‘1‘,2=>‘2‘,3=>‘3‘,4=>‘4‘);
$arr2 = array(1=>1,2=>2,3=>3,4=>4);
$arr3 = array(1=>‘1‘,2=>‘2‘,4=>‘4‘,3=>‘3‘);
var_dump($arr1 == $arr2);//true
var_dump($arr1 === $arr2);//false
var_dump($arr1 == $arr3);//true
var_dump($arr1 === $arr3);//false
@:用于可能发生错误的表达式(通常错误控制运算符用在程序开发测试阶段无法预测的可能出错的位置,一般是获取外部资源的时候)。
<?php
$link = @mysqli_connect(‘localhost‘,‘root‘,‘error‘) or die (‘can not connect‘);
<?php
//if语句
if(true)
echo 1;
//if else 语句
if(false)
echo 1;
else
echo 1;
//if elseif语句
if(false)
echo 1;
elseif(true)
echo 1;
//if elseif else语句
if(false)
echo 1;
elseif(true)
echo 1;
else
echo 1;
//switch
//break一般都加上,除非特殊应用
switch (1){
case 1:
echo 1;
break;
case 2:
echo 1;
break;
default:
echo 1;
}
<?php
while(false){
echo ‘whilefalse‘;//不打印
}
do{
echo ‘dowhilefalse‘;//打印
}while(false);
//不是三个参数是三个表达式
for($v=10;$v<11;++$v){
echo $v;//10
}
break中断:结束这个循环。
continue中断:进行下一循环。
可以加上中断的层数。(eg:break 2;)
<?php
//continue 2; = break;(要有两重循环)
for($v=1;$v<10;++$v){
for($n=1;$n<10;++$n){
if($n>$v){
echo PHP_EOL;
break;
}else
echo "$v*$n=".$v*$n.‘ ‘;
}
}
echo PHP_EOL;
for($v=1;$v<10;++$v){
for($n=1;$n<10;++$n){
if($n>$v){
echo PHP_EOL;
continue 2;
}else
echo "$v*$n=".$v*$n.‘ ‘;
}
}
//continue 2;错了
echo PHP_EOL;
for($n=1;$n<10;++$n){
if($n>3){
echo PHP_EOL;
continue 2;
}else
echo "$n=".$n.‘ ‘;
}
if ( ... ) :
//语句块
endif;
if ( ... ) :
//语句块
else:
//语句块
endif;
if ( ... ):
//语句块
elseif( ... ) :
//语句块
elseif( ... ):
//语句块
else:
//语句块
endif;
switch( ... ) :
case ...
case ...
endSwitch;
while(...):
//语句块
endwhile;
for(...; ...; ...):
//语句块
endfor;
foreach( ):
//语句块
endForeach;
严重不推荐适用!
它可以让我们的程序执行流程“任意跳转”。
语法:
goto 标识符1;
...很多语句。
标识符1:
...很多语句。
标识符2:
...很多语句。
goto 标识符2;
注意:
<?php
goto a;
b:
echo ‘heyheyhey‘.‘ ‘;
goto c;
d:
echo ‘This is library‘.PHP_EOL;
a:
goto b;
c:
echo ‘Good job‘.PHP_EOL;
if(rand(0,1))
goto d;
else
goto a;
终止php脚本的运行:die();或exit();
die是一种“语言结构”,并非函数,可以不写括号。
echo也是一种语言结构,而非函数:
echo (“abc”);
echo “abc”;
echo “abc”, “def”, 123;
<?php
echo ‘abc‘;
echo ‘abc‘,‘def‘;
echo(‘abc‘);
die(‘123‘);
die;
exit(‘123‘);
//echo(‘abc‘,‘def‘);//错
//exit ‘123‘;//错
//die ‘123‘;//错
//PHP默认最长执行执行超过30s可能报错用set_time_limit()解决。
<?php
echo "start";
sleep(50);
echo "ok";
include,include_once,require,require_once(是语言结构,不是函数)
<?php
//./1.php不存在
include(‘./1.php‘);//warning
require(‘./1.php‘);//warning error
dos代码:
cd C:\Users\Administrator\Desktop
::^在dos中转义,>新建文件写一行,>>继续写一行
echo ^<?php > include_once_test.php
echo echo 1; >> include_once_test.php
php代码:
<?php
include(‘./include_once_test.php‘);//加载
include(‘./include_once_test.php‘);//加载
include_once(‘./include_once_test.php‘);//不加载
dos代码:
cd C:\Users\Administrator\Desktop
::^在dos中转义,>新建文件写一行,>>继续写一行
echo ^<?php > include_test.php
echo echo "php"; >> include_test.php
php代码:
<?php echo include(‘include_test.php‘)?>//输出php1
<?php echo include‘include_test.php‘?>//输出php1
<?= include(‘include_test.php‘)?>//输出php1
<? include(‘include_test.php‘) ?>//输出php
<? include‘include_test.php‘ ?>//输出php
./ 表示当前网页文件的所在位置(文件夹,目录)
../ 表示当前网页文件的所在位置的上一级位置(文件夹,目录)
这种相对位置对一个网站中的所有内容(包括php,html,图片,css,js文件)都有效。
php.ini:
;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;
; UNIX: "/path1:/path2"
;include_path = ".:/php/includes"
;
; Windows: "\path1;\path2"
;include_path = ".;c:\php\includes"
php脚本中设置:
<?php
//get_include_path获取以前的设置别给原有的覆盖了
$path = get_include_path();
//PATH_SEPARATOR目录分隔符(unix:":",windows:";")
set_include_path($path.PATH_SEPARATOR."c:/dir1");
echo get_include_path();
就像是把include,include_once,require,require_once那一行语句替换成要加载的文件并执行。
注意:在哪里使用就在哪里替(eg:在下面的例子中,在函数中调用函数会找不到上层函数的变量)
test.php
<?php
class TestInclude{
public function func(){
$val = ‘func‘;
$this->inc();
}
public function inc(){
// $val = ‘inc‘;
//在test2中var_dump($val);能找到$val = ‘inc‘;
include ‘./test2.php‘;
}
}
$ti = new TestInclude();
$ti->inc();//在test2中var_dump($val);找不到$val = ‘func‘;
test2.php
<?php
var_dump($val);
结束脚本
return;
结束脚本带返回值(在加载脚本的语句接收)
return ‘Hello World‘
语法错误(程序没法跑),运行时错误(跑半道没法跑了),逻辑错误(程序正常跑,结果不对)
error, warning,notice什么的
自己就触发了
<?php
$i = 1/0;//Warning: Division by zero in C:\Users\Administrator\Desktop\test.php
自己根据需求设置的错误
<?php
$money = 100;
if($money < 60)
trigger_error("你连终身卡都买不起,这游戏不适合你。", E_USER_ERROR);
elseif($money >= 60 && $money < 10000)
trigger_error("先生先买个终身卡,再把648,328,198首冲都买了吧。", E_USER_WARNING);
elseif($money >= 10000 && $money < 10000000)
trigger_error("只要冲够钱您就会变得更强。", E_USER_NOTICE);
elseif($money >= 10000000)
echo "先定一个小目标,冲他一个亿。喵";
display_error = On;
ini_set(“display_error”, 1);
error_reporting = E_ALL;
ini_set(“error_reporting”, E_ALL);
在开发阶段:我们通常都是显示所有错误——意图解决错误
在产品阶段:我们通常都是隐藏所有错误——并同时将错误信息记录到文件中——错误日志文件
log_errors(是否记录错误日志),error_log(设定错误日志的文件名,设置为syslog会放到系统错误日志中)
php.ini中设置错误日志:
log_errors=On//开启
error_log=‘php_error.log‘//设置文件
脚本中错误日志:
ini_set(‘log_errors‘, On);//开启
ini_set(‘error_log‘, ‘php_error.log‘);//设置文件
<?php
set_error_handler(‘myError‘, E_ALL);
echo "$i";
function myError($errNo, $errMsg, $errFile, $errLine){
echo "大事不好了,文件: $errFile 的第 $errLine 行错了,赶紧去百度吧。".PHP_EOL;
echo "错误号:$errNo ,$errMsg";
}
形参可以有默认值(默认值只能是常量表达式,或常量,不能是变量)
形参可以设置为引用传递
<?php
function myFunc($arg1, $arg2){
return $arg1 + $arg2;
}
function myFunc2($arg1, $arg2 = 1){
return $arg1 + $arg2;
}
function myFunc3(&$arg1, $arg2){
$arg1 += $arg2;
}
<?php
//有返回值
function myFunc($arg1, $arg2){
return $arg1 + $arg2;
}
echo myFunc(1,2);
//没有返回值
function myFunc2($arg1, $arg2){
echo $arg1 + $arg2;
}
myFunc2(1,2);
//引用传递
$v1 = 1;
function myFunc3(&$arg1, $arg2 = 2){
$arg1 += $arg2;
}
myFunc3($v1);
echo $v1;
实参可以多于,少于形参。
<?php
function myFunc($arg1, $arg2){
echo $arg1 + $arg2;
}
//多于:舍去多余的
myFunc(1,2,3,4);//3
//少于:用到时找不到会警告
myFunc(1);//1
定义时可以不给定形参,调用时可以给定任意个数的实参。
<?php
function myFunc(){
var_dump(func_get_args()); //获得一个函数所接收到的所有实参数据,并结果是一个数组
var_dump(func_get_arg(1)); //获得一个函数所接收到的第n歌实参数据(n从0开始)
var_dump(func_num_args()); //获得一个函数所接收到的所有实参数据的个数
}
myFunc(1,2,3,4,5);
引用传递返回值
<?php
function &myFunc(){
static $result = 0;//静态变量,第一次调用这个函数赋值,再次调用这个函数不会被赋值
return $result;
}
$v1 = &myFunc();//0
echo $v1;
$v1++;
$v1 = &myFunc();//1
echo $v1;
函数名是变量
<?php
function myFunc($func){
function f1(){
echo "function f1";
}
$func();
}
myFunc(‘f1‘);
<?php
$myFunc = function(){
echo "myFunc";
};//这是赋值,这个分号必须有
$myFunc();
<?php
$arr = array(1,2,3,4,5,6,7);
//求和
$sum = call_user_func_array(function(){
$arr = func_get_args();
$sum = 0;
foreach($arr as $v){
$sum += $v;
}
return $sum;
},$arr);
echo $sum;
使用:
<?php
$global1 = 123;
$global2 = 456;
function get_global(){
global $global1;
echo $global1;//123
echo $GLOBALS[‘global2‘];//456
unset($global1);
unset($GLOBALS[‘global2‘]);
};
get_global();
echo "---".$global1;//123
echo $global2;//undefined
<?php
function set_global(){
$GLOBALS[‘local‘] = ‘local‘;
};
set_global();
echo $local;
function get_local1(&$v1){
$local = ‘local‘;
$v1 = $local;
}
get_local1($v1);
echo $v1;
function &get_local2(){
$local = ‘local‘;
return $local;
}
$v1 = &get_local2();
echo $v1;
<?php
if(function_exists(‘link_db‘) == false){
function link_db(){
@mysqli_connect(‘localhost‘,‘123456‘) or die(mysqli_connect_error());
}
}
link_db();
求阶乘:
<?php
function factorial($n){
if($n == 1)
return 1;
$result = factorial($n-1) * $n;
return $result;
}
echo factorial(10);
求斐波那契数列的第n项的值:
<?php
function fibonacci($n){
$last = 1;
$result = 1;
if($n <= 2){
return 1;
}
for($i=2;$i<$n;++$i){
$temp = $result;
$result += $last;
$last = $temp;
}
return $result;
}
echo fibonacci(6);
==不推荐使用mysql_XXX()这些方法==
mysqli_query($link, ‘CHARSET utf8‘);
<?php
//1. 连接数据库
$link = mysqli_connect(‘localhost‘, ‘root‘, ‘123456‘);
//2. 设定连接编码
mysqli_set_charset($link, "utf8");//也可以使用:mysqli_query($link, "set names utf8");
//3. 选择数据库
mysqli_select_db($link, "test");//也可以使用:mysqli_query($link, "use test");
//4. 执行sql命令
$result = mysqli_query($link, "show tables");
//5. 处理返回结果
var_dump($result);
if($result !== false){
// mysql和mysqli方法不同
// 获取全部结果,并形成二维数组
// mysqli_fetch_array获取一个结果
$fields = mysqli_fetch_fields($result);
while($rec = mysqli_fetch_array($result)){
foreach ($fields as $field) {
$field_name = $field->name;
$tables[$field_name][] = $rec[$field_name];
}
}
// 获取全部结果,没有字段名
//mysqli_fetch_all获取全部结果
mysqli_fetch_all($result);
}
<?php
class PDODB{
private $pdo;
function __construct(){
// 1.连接数据库
$dsn = ‘mysql:host=127.0.0.1;port=3306;dbname=mysql‘;
$username = ‘root‘;
$password = ‘123456‘;
$driver_options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => ‘SET NAMES UTF8‘
);
$this->pdo = new PDO($dsn, $username, $password, $driver_options);
}
function show_tables(){
// 2.执行sql语句
$result = $this->pdo->query(‘select * from user;‘);
// 3.处理返回结果
# 返回列名和数据的关联数组
# $list = $result->fetchAll();
# 返回数组,不显示列名
$list = $result->fetchAll(PDO::FETCH_NUM);
var_dump($list);
}
}
$pdo = new PDODB();
$pdo->show_tables();
一条SQL的执行,MySQL分成两大步骤:1编译->2执行
优点:1.连续执行多条结构相同的SQL速度快(结构已经编译好了)。2.可以防止sql注入。
<?php
class PDODB{
private $pdo;
function __construct(){
$dsn = ‘mysql:host=127.0.0.1;port=3306;dbname=test‘;
$username = ‘root‘;
$password = ‘123456‘;
$driver_options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => ‘SET NAMES UTF8‘
);
$this->pdo = new PDO($dsn, $username, $password, $driver_options);
}
function crate_table_testpre(){
$result = $this->pdo->exec(‘create table testpre (name varchar(20));‘);
var_dump($result);
}
function insert_data(){
$names = array(
‘张三‘, ‘李四‘, ‘王五‘
);
$stmt = $this->pdo->prepare(‘insert into testpre values (:name)‘);
foreach ($names as $key => $value) {
$stmt->bindValue(‘:name‘, $value);
$result = $stmt->execute();
var_dump($result);
}
}
}
$pdo = new PDODB();
$pdo->crate_table_testpre();
$pdo->insert_data();
PDOStatement对象的常用方法
OOP:object oriented program
类:是用于描述“某一些具有共同特征”的物体的概念,是某一类物体的总称,包括属性和方法
对象:是指一个具体的“物体”,该物体隶属于某个“类别”(类)。通常,对象离不开类,没有类,就不能有对象。
一个类的内部可以有3种代码:属性,方法和类常量,它们统称为“类中成员”。
定义形式:
错误定义形式:
$v1 = 1;//不写作用域
var $v2 = 1+3;//右边不能是计算表达式
public $v3 = $v2;//右边不能是变量
使用形式:
$对象->属性名;//注意:属性名前面没有$符号。
<?php
class C1{
public $v1 = 10;
var $v2 = 10;
public $v3;
var $v4;
}
$o1 = new C1();
echo $o1->v1;
定义:跟原来函数定义几乎一样。
方法前可以加修饰词:public,protected,private,省略就算“public”
方法中的$this是一个“伪对象”,代表当前所属类的当前对象。
方法中使用self代表当前类名
使用:通过类或类的对象来调用。
<?php
class C1{
public $v1 = 123;
function f1(){
echo $this->v1;
}
}
$o1 = new C1();
echo $o1->f1();
定义:在定义属性的时候,前面加上关键字static
使用:
<?php
class C1{
static $v1 = 123;
}
$o1 = new C1();
echo C1::$v1;
echo $o1::$v1;
//echo $o1->$v1;对象无法这样使用静态属性
定义:在定义方法时前面加上static(静态方法中不能出现$this,只能使用静态属性和静态方法)
使用:
<?php
class C1{
static $v1 = 123;
public $v2 = 456;
static function f1(){
echo C1::$v1;
// echo $this->v2;错的
// $this->f2();错的
return new self;//self当前类名
}
function f2(){
echo 123;
}
}
$o1 = new C1();
var_dump(C1::f1());
var_dump($o1::f1());
构造方式是类中的一个特殊的方法,其作用是在实例化一个对象的同时,给该对象的属性赋值,使之一创建完成,就具有了其本身的特有数据(属性值)。
<?php
class C1{
function __construct($v1, $v2){
$this->v1 = $v1;
$this->v2 = $v2;
}
public $v1;
public $v2;
}
$o1 = new C1(123, 456);
var_dump($o1->v1);
var_dump($o1->v2);
析构方法是“销毁”对象的时候会自动调用
析构方法通常用于在销毁对象的时候来“清理数据”
通常,php程序结束后,所有对象都会自动销毁(其实属于php内部的垃圾回收机制)
说明:
对象销毁的几个情形:
实际上,当一个对象没有任何一个变量指向它的时候,该对象就会被自动销毁。如果整个程序结束,也会销毁。
<?php
class C1{
function __construct(){
echo ‘construct‘.PHP_EOL;
}
function __destruct(){
echo ‘destruct‘.PHP_EOL;
}
}
$o1 = new C1();//construct:$o1
$o2 = new C1();//construct:$o2
unset($o1);//construct:$o1
//construct:$o2
创建对象:
<?php
class C1{
function f1(){
$o3 = new self;
}
}
$o1 = new C1();
$class1 = ‘C1‘;
$o2 = new $class1();
$o4 = new $o1;
// 创建空对象
$o5 = (object)null;
// 不通过类创建对象
$o6 = (object)array(‘name‘=>123,‘pwd‘=>456);
对象的传值:
默认是值传递,可以使用引用传递
值传递:将这个对象复制一个给新变量(对象的属性和方法不复制,所以这两个对象共用一套属性和方法)
引用传递:将新变量指向当前对象的空间
<?php
class C1{
public $v1 = 10;
}
$o1 = new C1();
$o2 = $o1;
$o3 = &$o1;
var_dump($o1);//class C1#1
var_dump($o2);//class C1#1
var_dump($o3);//class C1#1
$o1 = new C1();
var_dump($o1);//class C1#2
var_dump($o2);//class C1#1
var_dump($o3);//class C1#2(引用传递)
<?php
class C1{
public $test_public = ‘test_public‘;
protected $test_protected = ‘test_protected‘;
private $test_private = ‘test_private‘;
public function func(){
echo $this->test_public;//可以访问
echo $this->test_protected;//可以访问
echo $this->test_private;//可以访问
}
}
class C2 extends C1{
public function func(){
echo $this->test_public;//可以访问
echo $this->test_protected;//可以访问
echo $this->test_private;//不可以访问
}
}
$o1 = new C1();
$o2 = new C2();
$o1->func();
$o2->func();
echo $o1->test_public;//可以访问
//echo $o1->test_protected;//不可以访问
//echo $o1->test_private;//不可以访问
parent通常用于在子类中调用父类的成员的时候使用,多数通常就是使用父类的“静态类”成员。因为parent代表的类,而非对象。
<?php
class C1{
public $v;
function __construct(){
$this->v = 1;
}
}
class C2 extends C1{
public $v2;
function __construct(){
parent::__construct();
$this->v2 = 1;
}
}
$o2 = new C2();
echo $o2->v;//1
重写就是将从父类继承下来的属性或方法重新定义
<?php
class C1{
function func1(){
echo 123;
}
}
class C2 extends C1{
//protected function func1(){
// echo 456;
//}//会报错
////function func1($v1){
// echo 456;
//}//会报错
function func1(){
echo 456;
}
}
如果某个类不希望对其进行扩展,则可以将其声明为最终类。
<?php
final class C1{}
class C2 extends C1{}//会报错Class C2 may not inherit from final class (C1)
如果某个方法不希望被下级类覆盖,就可以对其声明为最终方法。
<?php
class C1{
final function final_func(){
}
}
class C2 extends C1{
function final_func(){
}//会报错Cannot override final method C1::final_func()
}
在正常定义类的前面,加上关键字:abstract,那就构成抽象类。
抽象类可以用来规范一些类的共同特性,但又不需要去对其进行实例化。
抽象方法是一个没有方法体(也不含大括号)的方法。
方法前面需要加上abstract。
<?php
abstract class Animal{
public $legs = 4;
public $eyes = 2;
public abstract function run();
}
class Man extends Animal{
public $legs = 2;
public function run(){
echo "man can run with 6 meters per second";
}
}
class Dog extends Animal{
public function run(){
echo "man can run with 20 meters per second";
}
}
其基本语法是这样的:
在一个类中,有多个同名的方法,每个方法的参数不同而已。这种现象就称为“重载”。
参数不同可以是:数量个数不同,或类型不同,或顺序不同。
比如:
class A{
int function f1(int x){...}
int function f1(int x, int y){...}
int function f1(string s, int m){...}
但,在php中,一个类中,根本就不可以定义多个同名方法——这直接是语法错误。
实际上,php中的重载指的是:
属性重载:如果使用一个不存在的属性,就会去自动调用类中预先定义好的某个方法以处理数据
方法重载:如果使用一个不存在的方法,就会去自动调用类中预先定义好的某个方法以处理该行为
属性有4种使用情形:
所谓属性重载,就是在面对上述4种情形的属性使用场景中,该对象如果来“应对”的问题。
如果某属性不存在,但在语法中使用如下情形,则会发生
<?php
class C1{
public $v1 = 1;
public $propArr = array();
function __get($propName){
if(isset($this->propArr[$propName])){
return $this->propArr[$propName];
}
return "不存在的属性 $propName";
}
function __set($propName,$value){
$this->propArr[$propName] = $value;
}
function __isset($propName){
if(isset($this->propArr[$propName])){
return true;
}
return false;
}
function __unset($propName){
unset($this->propArr[$propName]);
}
}
$obj = new C1();
$obj->v2 = 123;
echo $obj->v2;//123
echo isset($obj->v2);//1
unset($obj->v2);
当使用一个对象调用一个不存在的普通方法的时候,会自动去调用预先定义好的“__call”方法。
<?php
class C1{
function f1(){
echo ‘f1‘;
}
function f2($v){
echo "f2 $v";
}
function __call($name, $array){
$count = count($array);
if($count == 0){
$this->f1();
}elseif($count == 1){
$this->f2($array[0]);
}
}
}
$obj = new C1();
$obj->ff();
$obj->ff("123");
接口中只有两类最简单特性信息:(没有普通方法)
接口可以看作是抽象类的更高层面的抽象规范,不考虑接口常量的话,那么就相当于之规定了下级类要做什么,至于怎么就,没有规定。
接口可以实现“多继承”(多实现),而类不行。
一个类只能继承一个父类,但可以实现多个“上级接口”,语法形式:
class 类A extends 类B implements 接口1,接口2,... {...}
一个接口同样可以继承另一个接口(也是单继承):
interface 接口1 extends 接口2{...}
<?php
interface I1{
const V1 = 1;
function f1();
}
interface I2 extends I1{
const V2 = 2;
function f2();
}
class C1 implements I1,I2{
public function __construct(){
echo self::V1;
echo self::V2;
}
function f1(){}
function f2(){}
}
$o1 = new C1();
做法1:使用__autoload魔术函数
<?php
function testFile(){
mkdir("C:/Users/Administrator/library");
$file = fopen("C:/Users/Administrator/library/A.class.php", ‘w‘);
fwrite($file, "<?php\n");
fwrite($file, "class A{}");
fclose($file);
}
function __autoload($className){
require "C:/Users/Administrator/library/{$className}.class.php";
}
testFile();
$obj = new A();
var_dump($obj);
做法2:使用spl_autoload_register函数
用spl_autoload_register函数可以声明多个可以用来代替__autoload函数作用的函数(类文件分布在不同的目录中可以使用这种方法)
<?php
function testFile(){
mkdir("C:/Users/Administrator/library");
$file = fopen("C:/Users/Administrator/library/A.class.php", ‘w‘);
fwrite($file, "<?php\n");
fwrite($file, "class A{}");
fclose($file);
}
spl_autoload_register(‘autoload1‘);
spl_autoload_register(‘autoload2‘);
function autoload1($className){
require "C:/Users/Administrator/library/{$className}.class.php";
}
function autoload2($className){
require "C:/Users/Administrator/class/{$className}.class.php";
}
testFile();
/*
1.先看这个文件中是否加载该类
2.autoload1运行后是否加载该类
3.autoload2运行后是否加载该类
*/
$obj = new A();
var_dump($obj);
浅克隆(默认):只能克隆对象中的“非对象非资源”数据
<?php
class C1{public $v1 = 1;}
class C2{
public $v2 = 2;
public $v3;
public function __construct(){
$this->v3 = new C1();
}
}
var_dump($o1 = new C2());
var_dump($o2 = clone $o1);//共用一个v3
深克隆:要想实现深克隆(一个对象的所有属性数据都彻底实现了“复制”),就需要对该对象类使用魔术方法__clone(),人为去复制浅克隆复制不了数据。
<?php
class C1{public $v1 = 1;}
class C2{
public $v2 = 2;
public $v3;
public function __construct(){
$this->v3 = new C1();
}
public function __clone(){
$this->v3 = clone $this->v3;
}
}
var_dump($o1 = new C2());
var_dump($o2 = clone $o1);//新建了个v3
用foreach语句进行遍历(只能遍历可访问的属性)
<?php
class C1{
public $v1 = 1;
protected $v2 = 2;
private $v3 = 3;
public function fetchAllProp(){
foreach($this as $key => $value){
echo "$key => $value".PHP_EOL;
}
}
}
$o1 = new C1();
//只有1
foreach($o1 as $key => $value){
echo "$key => $value".PHP_EOL;
}
echo "---".PHP_EOL;
//有1,2,3
$o1->fetchAllProp();
stdclass:该类内部没有定义任何属性,但我们还是可以使用该类的属性(不存在的属性)
<?php
var_dump($obj = new stdclass());
$obj->v1 = 1;
$obj->v2 = 2;
var_dump($obj);
<?php
var_dump($o_arr = (object) array("v1" => 1,"v2"=>2,3,4));
var_dump($n_arr = (object) null);
var_dump($n_arr = (object) 1);
php是弱类型语言,其特点是无需为变量指定类型,而且在其后也可以存储任何类型。
但在php的较新的语法中,在某些特定场合,针对某些特定类型,也可以进行语法约束。
特定场合:函数(或方法)的形参变量
特定类型:对象类型(类名),接口类型(接口名),数组类型(array),函数类型(callable)
<?php
class C1{}
interface I1{}
class C2 implements I1{}
function f1(C1 $v){//只能传该类的对象
var_dump($v);
}
function f2(I1 $v){//只能传实现该接口的类的对象
var_dump($v);
}
function f3(array $v){//只能传数组
var_dump($v);
}
function f4(callable $v){//只能传函数
var_dump($v);
}
当对一个对象进行“序列化”操作的时候,会自动调用类中的__sleep()方法;
当“反序列化”一个对象的时候,会自动调用对应类中的__wakeup()方法;
<?php
class C1{
public $v1 = 1;
public $v2 = 2;
function __sleep(){//只保存C1
echo "__sleep";
return array(‘v1‘);
}
function __wakeup(){//经常用于重新建立数据库连接,或执行其它初始化操作。
echo "__wakeup";
}
}
var_dump($s = serialize(new C1));
file_put_contents(‘./test_serialize‘, $s);
var_dump(unserialize(file_get_contents(‘./test_serialize‘)));
<?php
class C1{
public $v1 = 1;
public $v2 = 2;
function __tostring(){
return "{$this->v1},{$this->v2}";
}
}
var_dump((string)new C1());
<?php
class C1{
public $v1 = 1;
public $v2 = 2;
function __invoke(){
echo "你怎么可以拿对象当函数,好讨厌,锤你胸口";
}
}
$obj = new C1();
$obj();//打印:你怎么可以拿对象当函数,好讨厌,锤你胸口
系统函数
运算符
<?php
class C1{}
class C2 extends C1{}
$obj1 = new C1();
$obj2 = new C2();
var_dump($obj1 instanceof C1);//true
var_dump($obj2 instanceof C1);//true
当一个对象调用一个实例方法,然后,在该实例方法中又去“静态”调用另一个类的普通方法,则在类的普通方法中会自动获得在实例方法中的那个$this对象。
<?php
class C1{
public $v1 = 1;
function f1(){
@C2::f2();
@C2::f3();
}
}
class C2{
function f2(){
var_dump($this);//有this
}
static function f3(){
var_dump($this);//null
}
}
$o1 = new C1();
$o1->f1();
static在类方法中代表调用该方法的对象所在的类
<?php
class C1{
public static $v = 1;
function f1(){
echo self::$v;
echo static::$v;
}
}
class C2 extends C1{
public static $v = 2;
}
$o1 = new C1();
$o2 = new C2();
$o1->f1();//11
echo "---";
$o2->f1();//1,2
可见static有3个不同含义的语法:
function f1(){
static $v1 = 1;
}
class A{
static $v1 = 1;
static function f1(){}
}
class A{
function f1(){
static::f2();//static此时指代调用f1这个方法的类(或对象的类)
self::f2(); //self这里永远指代当前A这个类。
}
}
设计模式就是一些解决问题的“常规做法”,是一种认为较好的经验总结。面对不同的问题,可能会有不同的解决办法,此时就可以称为不同的设计模式。
在实际应用中,遇到需要去实例化很多很多的类以得到对象的情况,可以设计出一个工厂(类),该工厂(类)的作用就是实例化各种对象。这种工厂通常只要指定类名,就可以据此获取一个该类的对象。
<?php
class factory{
static function testFile(){
mkdir("C:/Users/Administrator/class");
$file = fopen("C:/Users/Administrator/class/A.class.php", ‘w‘);
fwrite($file, "<?php\n");
fwrite($file, "class A{}");
fclose($file);
}
static function getInstance($className){
if(file_exists("C:/Users/Administrator/class/{$className}.class.php")){
require_once "C:/Users/Administrator/class/{$className}.class.php";
return $obj1 = new $className();
}else{
return null;
}
}
}
factory::testFile();
$o1 = factory::getInstance("A");
var_dump($o1);
在实际应用中,对于某些类在使用它的时候,从程序运行的开始到结束都只需要一个对象就可以完成所有任务。就可以使用单例。
单例:某个类,只允许其创建出一个对象,即使去进行多次创建,也只能得到一个对象。
<?php
class DB{
public $db = ‘mysql‘;
private static $instance;
//禁止通过构造方法创建对象(new对象)
private function __construct(){}
//禁止通过克隆对象(克隆产生的对象也是新对象)
private function __clone(){}
public static function getNew(){
if( !isset(DB::$instance)){
DB::$instance = new self;
}
return DB::$instance;
}
}
$db1 = DB::getNew();
$db1->db = ‘mysql1‘;
$db2 = DB::getNew();
echo $db2->db;//mysql1
在一个成熟(常规业务逻辑实现)的产品上,完成自己项目的特定业务逻辑。
框架:规范了结构,基础功能,但没有常规业务逻辑实现一种产品。
(ZendFramework,ThinkPHP,YII,symfony,CI 等等)
CREATE DATABASE myimg CHARSET=utf8;
GRANT ALL PRIVILEGES ON myimg.* TO ‘myimg‘@‘%‘ IDENTIFIED BY ‘123456‘;
<VirtualHost *:80>
DocumentRoot "C:/wamp/www/myimg"
ServerName myimg.com
<Directory "C:/wamp/www/myimg">
Options FollowSymLinks
AllowOverride all
Require all granted
DirectoryIndex index.php
</Directory>
</VirtualHost>
127.0.0.1 myimg.com
1.创建单一入口文件
2.声明路径常量
3.初始化配置
4.确定分发参数
5.当前平台相关的路径常量
6.注册自动加载
7.请求分发
标签:errno pex 认证 database 分发 chunk 回滚事务 二次开发 权限
原文地址:https://www.cnblogs.com/jffun-blog/p/10217508.html