02后端/PHP

一。介绍

PHP(外文名: PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了 C 语言、Java 和 Perl 的特点,利于学习,使用广泛,主要适用于 Web 开发领域。PHP 独特的语法混合了 C、Java、Perl 以及 PHP 自创的语法。它可以比 CGI 或者 Perl 更快速地执行动态网页。用 PHP 做出的动态页面与其他的编程语言相比,PHP 是将程序嵌入到 HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成 HTML 标记的 CGI 要高许多;PHP 还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。

PHP 中文手册
PHP 英文手册

二。运行 PHP

php.exe -f “filename”

1
2
3
4
5
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 代码”

1
php.exe -r "$i = 10; echo $i;"

三. PHP 脚本嵌入

标准形式

1
2
3
4
5
6
7
# php代码后没有其他内容结束标记有时可以省略
<?php
php代码
?>
<script language=”php”>
php代码
</script>

短标签形式(需设置 php.ini 中 short_open_tag = On)

1
2
3
<?
.....这里是php代码
?>

四。基本语法

  • 变量名区分大小写
  • 常量名区分大小写(可设置不区分)
  • 函数名不区分大小写
  • 系统中使用的关键字也不区分大小写
  • 一个 php 标记块中的最后一个分号在有结束标记时可省略
1
2
3
4
5
6
7
8
9
#可省略
<?php
echo 1
?>

#不可省略

<?php
echo 1;

五。变量

使用

  • 变量必须以 $ 开头,后面紧跟变量名
  • 定义变量:直接给变量赋值,就是定义
1
2
<?php
$v1 = 1;
  • 判断变量是否存在:isset()
    存在就返回 true,不存在就返回 false,null 返回 false
1
2
3
<?php
$v1 = null;
echo isset($v1);
  • 判断变量是否为空:empty()
1
2
3
4
5
6
7
<?php
$v1 = null;
$v2 = 0;
$v3 = 1;
echo empty($v1)."===";
echo empty($v2)."===";
echo empty($v3)."===";
  • 修改变量值:直接给变量赋新值
  • 删除变量:unset()
    unset () 断开变量名跟该变量名所指向的数据的引用

命名规则

基本规则

  1. 只能使用大小写字母,数字和下划线(_)
  2. 不能以数字开头
  3. 不能跟系关键字重名

经典命名规则

  1. 匈牙利命名法:该命名法是在每个变量名的前面加上若干表示数据类型的字符。基本原则是:变量名 = 属性 + 类型 + 对象描述。如 i 表示 int, 所有 i 开头的变量命都表示 int 类型。s 表示 String, 所有变量命以 s 开头的都表示 String 类型变量。
  2. 骆驼命名法:混合使用大小写字母来构成变量和函数的名字,如 userName。
  3. 帕斯卡命名法(pascal 命名法):做法是首字母大写,如 UserName, 常用在类的变量命名中。
  4. 下划线法:使用小写字母和下划线来构成变量和函数的名字,如 user_name。

传值方式

值传递(默认)

将一个变量的数据拷贝一份,然后赋值给另一个变量。

引用传递

将一个变量的引用拷贝一份,然后赋值给另一个变量(将另一个变量指向被引用传递变量的数据)。

可变变量

一个变量的名是另一个变量。

1
2
3
4
<?php
$v1 = 'v2';
$v2 = 10;
echo $$v1;//10

预定义变量

  • $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 — 传递给脚本的参数数组

超全局变量

PHP 中的许多预定义变量都是 “超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。

  • $GLOBALS
  • $_SERVER
  • $_GET
  • $_POST
  • $_FILES
  • $_COOKIE
  • $_SESSION
  • $_REQUEST
  • $_ENV

变量序列化

序列化就是将一个变量的数据转换为字符串(并不是类型转换),目的是将该字符串进行存储和传输。
serialize:序列化
unserialize:反序列化

1
2
3
4
5
<?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')));//反序列化

六。常量

常量是一个简单值的标识符(名字),在脚本执行期间该值不能改变。
传统上常量标识符总是大写的。

定义常量

  1. 使用 define() 函数定义
  2. 使用 const 语法定义
    使用 const 关键字定义常量必须处于最顶端的作用区域,因为用此方法是在编译时定义的。这就意味着不能在函数内,循环内以及 if 语句之内用 const 来定义常量。
  • const 和 define 的区别?
  1. 使用 const 使得代码简单易读,const 本身就是一个语言结构,而 define 是一个函数。另外 const 在编译时要比 define 快很多。
  2. const 用于类成员变量的定义,一经定义,不可修改。define 不可以用于类成员变量的定义,可用于全局常量。
  3. const 可在类中使用,define 不能
  4. const 不能再条件语句中定义常量,define 可以
1
2
3
<?php
define('CONST1', 123);
const CONST2 = 456;

使用常量

  1. 直接使用
  2. 使用 constant() 函数
1
2
3
4
<?php
define('CONST1', 123);
echo CONST1;
echo constant('CONST1');//constant(CONST1)->constant('123');

检查常量:defined()

defined () 返回布尔值

1
2
3
4
<?php
define('CONST1', 123);
echo 'CONST1---'.defined('CONST1');
echo 'CONST2---'.defined('CONST2');

预定义常量

  • 内核预定义常量:是在 PHP 的内核中就定义好了的常量。区分大小写。
    PHP_VERSION:返回 PHP 的版本。
    PHP_OS:返回执行 PHP 解释器的操作系统名称。
    PHP_EOL:系统换行符,Windows 是(\r\n),Linux 是(\n),MAC 是(\r)。
  • 标准预定义常量:PHP 默认定义的常量。区分大小写。
    M_PI:返回 π 的值。
    M_PI_2:返回 π/2 的值。
    M_1_PI:返回 1/π 的值。
1
2
3
4
5
6
7
<?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__ 当前命名空间的名称(区分大小写)。此常量是在编译时定义的。
1
2
3
4
5
6
7
8
9
<?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__);

八。数据类型

  • 标量类型: int, float, string, bool
  • 复合类型: array, object
  • 特殊类型: null, resouce

1. 整数类型(int)

  • 十进制:123
  • 八进制:0123
  • 十六进:0x123

dec (Decimal): 十进制
bin (Binary):二进制
oct (Octal):八进制

hex (Hexadecimal):十六进制

== 十进制是数组,二、八、十六进制是字符串 ==
十进制转二进制decbin()
十进制转八进制decoct()
十进制转十六进制dechex()
二进制转十进制bindec()
八进制转十进制octdec()
十六进制转十进制hexdec()

1
2
3
<?php
var_dump(decbin(123));
var_dump(bindec('101010'));

2. 浮点类型(float, double, real)

  • 普通表示:$v1 = 1.23;
  • 科学计数法表示:$v1 = 1.23E3;($v1 = 123E3;// 结果值是 123000,但也是一个浮点数。)

浮点数不应直接进行大小比较

应该设置在一定精度要求下比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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";
}

整数运算的结果超出整数的范围后,会自动转换为浮点数。

1
2
<?php
var_dump(12345*1000000);

3. 字符串类型(string)

  • 单引号字符串:不识别变量,识别反斜杠单引号转义字符
  • 双引号字符串:识别变量和换行回车等转义字符
  • nowdoc(单引号)定界符字符串:不识别转义字符
  • heredoc(双引号)定界符字符串:识别变量,识别转义字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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
//要有一行

4. 布尔类型(bool)

true 或 false 两个值
隐式转换为布尔值是为 false 的是:

  1. 0
  2. 0.0
  3. null
  4. “”1.”0”
  5. array()
  6. 未定义的变量 (会报 Notice: Undefined variable)
1
2
3
4
5
6
<?php
if($v1){
echo 'yse';
}else{
echo 'no';
}

5. 数组类型(array)

分类

  1. 键值关系:关联数组,索引数组
  2. 数组层次:一维数组,二维数组,多维数组

定义

  1. 使用 array() 方法
  2. 使用变量 []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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);

遍历

数组指针:

  • current($arr); // 取得 $arr 中当前指针所指向的元素的值,如果没有指向元素,则为 false
  • key($arr); // 取得 $arr 中当前指针所指向的元素的下标
  • next($arr1); // 将指针移向 “下一个元素”,然后取得该下一个元素的值
  • prev($arr); // 将指针移向 “上一个元素”,然后取得该上一个元素的值
  • reset($arr); // 将指针移向 “第一个元素”,然后取得该元素的值 —— 数组指针初始化
  • end($arr); // 将指针移向 “最后一个元素”,然后取得该元素的值
  • each($arr); // 取得当前元素的下标和值,然后移动指针到下一个位置。
  1. foreach
    ==foreach 不会主动释放 $value==
  • 传递方式
    默认值传递,引用传递要在变量前加 &(foreach ($arr as $key => &$value){…})
    $key 不能设置为引用传递
    因为引用传递不会自动销毁 $value 所以引用传递注意要手动销毁 $value,不然可能不小心通 $value 修改了数组最后一项。(eg:在两个循环都用 $value 时第一个用了引用传递,第二个用值传递。会将数组最后一项的值改成倒数第二项)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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)
  • foreach 过程中进行修改
    foreach 默认是原数组上进行遍历。
    如果在遍历过程中对数组进行了某种修改或使用了数组指针函数,则会复制数组后在复制的数组上继续遍历循环。
    foreach 中如果值变量是引用传递,则无论如何都是在原数组上进行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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并死循环
}
  1. for+next+reset 遍历数组
1
2
3
4
5
6
7
8
9
10
<?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);//指针移到下一个元素
}
  1. while+each ()+list () 遍历数组
1
2
3
4
5
6
7
8
9
10
11
<?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);
}

排序

  1. 冒泡排序:俩俩比较大小交换位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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);
  1. 选择排序:选择出最大的与最后一个交换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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);

查找

  1. 顺序查找:直接 foreach
  2. 二分查找:必须是排好序并且下标连续的数组
    效率:2^n 个数据,需要 n 次查找

6. 对象类型(object)

1
2
3
4
5
6
7
8
9
10
<?php
class myClass{
public $v1 = 123;
public function myfunc(){
echo $this->v1;
}
}
$myobj = new myClass();
echo $myobj->v1;
$myobj->myfunc();

7. 资源类型(resource)

资源 resource 是一种特殊变量,保存了到外部资源的一个引用。资源是通过专门的函数来建立和使用的。
由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄,因此将其它类型的值转换为资源没有意义。

8. 空类型(null)

变量没有指向任何空间

10. 类型想关函数

getType (变量名):获取一个变量的类型名称
setType (变量名,目标类型字符串):设置一个变量的类型
is_XX 类型 () 系列函数:判断某个数据是否是某种类型,包括:

  1. is_int()
  2. is_float()
  3. is_bool()
  4. is_numeric()
  5. is_array()
  6. is_string()
  7. is_scalar():判断是否为标量类型(即 int,float,stirng,bool)
1
2
3
4
5
6
<?php
$v1 = 123;
echo getType($v1)."---";
echo setType($v1, 'string')."---";
echo is_int($v1)."---";
echo is_string($v1)."---";

11. 类型转换

自动转换

  • 自动转换是弱类语言的一个最基本也最方便的一个特征:它会在各种运算中根据运算符的需要也将非该运算符所能处理的数据转换为可以处理的数据。
  • if (数据){}:转为 bool 类型
  • 算术运算符:转为数字类型
  • 连接运算符:转为字符串类型
  • 比较运算符:转为布尔类型或数字类型
    两边如果有至少一个布尔,则另一边就会转为布尔,并进行比较
    否则,就转为数字进行比较

强制转换

通过语法来让某数据转换为另一种类型的数据

1
2
3
<?php
echo (int) 12.3;
echo (float) 123;

字符串转数字

1
2
3
4
5
6
7
<?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++:没用

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$str1 = "abc";
echo ++$str1."---";//abd

$str1 = "张";
echo ++$str1."---";//???

$v1 = null;
echo ++$v1."---";//1

$v2 = false;
echo ++$v2."---";//没用还是false

比较运算符

>,>=,<,<=,\=\=,!=,\=\=\=,!\=\=
==:数据内容相等
===:数据内容和类型都相等
字符串的比较规则:按字符的先后顺序找到第一个不同的字符当做整个字符串比较大小

1
2
3
4
5
6
7
8
9
<?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";

逻辑运算符

&&,||,!

逻辑短路

逻辑与短路:如果前面是真执行后面的

1
2
<?php
!defined('BASEPATH') && exit('No direct script access allowed');

逻辑或短路:如果前面是假执行后面的

1
2
<?php
defined('BASEPATH') || exit('No direct script access allowed');

字符串运算符

.,.=

赋值运算符

=,+=,-=,*=,/=,%=,.=

条件(三目)运算符

数据 1 ? 数据 2 : 数据 3

1
2
3
<?php
$is_show = true;
echo $is_show ? 'show' : 'hide';

位运算符

&,|,~,^,<<,>>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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 :00000001
    -1:10000001
  • 反码:
    1 :00000001
    -1:11111110
  • 补码:(负数是反码加 1)
    1 :00000001
    -1:11111111

计算机中的加减法都是:补码 + 补码 = 补码(都转换成补码运算)

位运算开关

1:开,0:关

  • 设定
    第一个开:00000001
    第二个开:00000010
    第三个开:00000100
    第四个开:00001000
    第五个开:00010000
    第一,二个开:00000011
    第一,二,五个开:00010011
  • 查询
    当前状态 & 查询状态(大于 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 出外的所有错误和警告信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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);

数组运算符

+,\=\=,!=(<>),\=\=\=,!\=\=
+:将右边的数组项合并到左边数组的后面,得到一个新数组。如有重复键,则结果以左边的为准。

1
2
3
4
<?php
$arr1 = array(1,2,3,4);
$arr2 = array(1,4,5,6,7);
var_dump($arr1+$arr2);//1,2,3,4,7

==:两个数组具有相同的键名和键值则返回 true。
===:如果两个数组具有相同的键名和键值且顺序和类型都一样。

1
2
3
4
5
6
7
8
<?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

错误控制运算符

@:用于可能发生错误的表达式(通常错误控制运算符用在程序开发测试阶段无法预测的可能出错的位置,一般是获取外部资源的时候)。

1
2
<?php
$link = @mysqli_connect('localhost','root','error') or die ('can not connect');

运算符的优先级

  1. 括号最优先,赋值最落后
  2. 算术运算符 > 比较运算符 > 逻辑运算符(非运算符比算术运算符优先级高)

十:流程控制

程序框图

  • 开始,结束:椭圆
  • 语句(块):正方形
  • 判断:菱形
  • 输入输出:平行四边型

分支结构

  1. if 语句
  2. if else 语句
  3. if elseif 语句
  4. if elseif else 语句
  5. switch 语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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;
}

循环结构

  1. while 循环
  2. do while 循环
  3. for 循环
1
2
3
4
5
6
7
8
9
10
11
<?php
while(false){
echo 'whilefalse';//不打印
}
do{
echo 'dowhilefalse';//打印
}while(false);
//不是三个参数是三个表达式
for($v=10;$v<11;++$v){
echo $v;//10
}

循环的中断

break 中断:结束这个循环。
continue 中断:进行下一循环。
可以加上中断的层数。(eg:break 2;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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.' ';
}

流程控制的替换语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
if ( ... ) :
//语句块
endif;

if ( ... ) :
//语句块
else:
//语句块
endif;

if ( ... ):
//语句块
elseif( ... ) :
//语句块
elseif( ... ):
//语句块
else:
//语句块
endif;

switch( ... ) :
case ...
case ...
endSwitch;

while(...):
//语句块
endwhile;

for(...; ...; ...):
//语句块
endfor;

foreach( ):
//语句块
endForeach;

goto 语句(跳转语句)

严重不推荐适用!
它可以让我们的程序执行流程 “任意跳转”。
语法:
goto 标识符 1;
… 很多语句。
标识符 1:
… 很多语句。
标识符 2:
… 很多语句。
goto 标识符 2;
注意:

  • 不能跳入循环中
  • 不能跳入函数中
  • 不能跳出函数外
  • 不能跳出文件外
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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;

1
2
3
4
5
6
7
8
9
10
<?php
echo 'abc';
echo 'abc','def';
echo('abc');
die('123');
die;
exit('123');
//echo('abc','def');//
//exit '123';//
//die '123';//
  • 让 php 脚本停止 n 秒,然后继续执行:sleep(n);

    //PHP 默认最长执行执行超过 30s 可能报错用set_time_limit() 解决。

1
2
3
4
<?php
echo "start";
sleep(50);
echo "ok";

十一:文件加载

include,include_once,require,require_once(是语言结构,不是函数)

  • 加载 / 引入 / 包含 / 载入不存在的文件 include
1
2
3
4
<?php
//./1.php不存在
include('./1.php');//warning
require('./1.php');//warning error
  • 加上 once 只会引入一次

    dos 代码:
    cd C:\Users\Administrator\Desktop
    ::^ 在 dos 中转义,> 新建文件写一行,>> 继续写一行
    echo ^<?php> include_once_test.php
    echo echo 1; >> include_once_test.php
    php 代码:

1
2
3
4
<?php
include('./include_once_test.php');//加载
include('./include_once_test.php');//加载
include_once('./include_once_test.php');//不加载
  • 文件加载返回值
    使用 include,include_once,require,require_once 时成功会返回 1

    dos 代码:
    cd C:\Users\Administrator\Desktop
    ::^ 在 dos 中转义,> 新建文件写一行,>> 继续写一行
    echo ^<?php> include_test.php
    echo echo “php”; >> include_test.php
    php 代码:

    //输出php1

    //输出php1

    //输出php1

    //输出php

    //输出php

文件加载路径

相对路径

./ 表示当前网页文件的所在位置(文件夹,目录)
../ 表示当前网页文件的所在位置的上一级位置(文件夹,目录)
这种相对位置对一个网站中的所有内容(包括 php,html,图片,css,js 文件)都有效。

绝对路径:

  1. 本地绝对路径:
    window 系统: c:/dir1/dir1/test.php
    unix 系列系统: /dir1/dir1/test.php
  2. 网络绝对路径: http://www.abc.com/dir1/dir1/test.php

只有文件名(不写路径)

  1. 首先在 php.ini 设置的 include 目录中查找:

    php.ini:
    ;;;;;;;;;;;;;;;;;;;;;;;;;
    ; Paths and Directories ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;

    ; UNIX: “/path1:/path2”
    ;include_path = “.:/php/includes”
    ;
    ; Windows: “\path1;\path2”
    ;include_path = “.;c:\php\includes”

    php 脚本中设置:

1
2
3
4
5
6
<?php
//get_include_path获取以前的设置别给原有的覆盖了
$path = get_include_path();
//PATH_SEPARATOR目录分隔符(unix:":",windows:";")
set_include_path($path.PATH_SEPARATOR."c:/dir1");
echo get_include_path();
  1. php.ini 设置中没找到,当前工作目录查(地址栏中显示的那个文件名所在目录)
  2. 当前工作目录中没找到,则在当前 include 命令所在文件的目录中查找

文件加载执行过程

就像是把 include,include_once,require,require_once 那一行语句替换成要加载的文件并执行。
注意:在哪里使用就在哪里替(eg:在下面的例子中,在函数中调用函数会找不到上层函数的变量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

  1. 结束脚本
    return;

  2. 结束脚本带返回值 (在加载脚本的语句接收)
    return 'Hello World'

十二:错误处理

错误的分类

语法错误(程序没法跑),运行时错误(跑半道没法跑了),逻辑错误(程序正常跑,结果不对)

错误的分级

error, warning,notice 什么的

错误的触发

系统错误

自己就触发了

1
2
<?php
$i = 1/0;//Warning: Division by zero in C:\Users\Administrator\Desktop\test.php

用户自定义错误

自己根据需求设置的错误

1
2
3
4
5
6
7
8
9
10
<?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 "先定一个小目标,冲他一个亿。喵";

错误的显示控制

  • 是否显示
    php.ini 中:
    display_error = On;
    (On 显示,Off 不显示)
    脚本中:
    ini_set(“display_error”, 1);
    (1,true 显示,0,false 不显示)
  • 显示哪些级别的错误
    php.ini 中:
    error_reporting = E_ALL;
    (本质是数字,可以用位运算控制)
    脚本中:
    ini_set(“error_reporting”, E_ALL);

错误日志

在开发阶段:我们通常都是显示所有错误 —— 意图解决错误
在产品阶段:我们通常都是隐藏所有错误 —— 并同时将错误信息记录到文件中 —— 错误日志文件
log_errors(是否记录错误日志),error_log(设定错误日志的文件名,设置为 syslog 会放到系统错误日志中)
php.ini 中设置错误日志:

1
2
log_errors=On//开启
error_log='php_error.log'//设置文件

脚本中错误日志:

1
2
ini_set('