第3章后端技术 Web应用的前端,包括Web页面的结构、Web的外观视觉表现以及Web层面的交互实现,这些都是Web应用中用户看得见、碰得着的东西; 而Web应用的后端,更多的是应用与数据库的交互,从而实现复杂的业务逻辑。所以,后端技术的重点在于,如何实现业务逻辑,如何存储数据,如何让应用具有优越的性能,如何提高应用运行的稳定性等。 本章介绍PHP项目开发的后端技术,包括PHP基本语法、面向过程程序设计、面向对象程序设计以及PHP应用扩展等内容。 视频讲解 3.1PHP语言基础 在使用任何一门程序设计语言进行编程之前,都需要详细了解该语言的词法结构和基本语法规则。例如,该语言有哪些数据类型,如何定义变量和常量,怎样控制程序的流程,如何处理程序的错误等。 PHP的语法规则与大家熟悉的C、C++和Java非常相似,所以这里只对PHP进行概要性的介绍。 3.1.1语法基础 PHP是一种嵌入式的程序设计语言,其代码的编写,除需要特定的语言标记之外,其他语法与C、C++、Java等程序设计语言基本相同。 1. PHP语言标记与注释 PHP代码常常被嵌入HTML页面中,因此,为了区分HTML与PHP代码,需要使用特定的标记将PHP代码进行界定。PHP提供如下两种形式的语言标记。 1) 标准形式 开始标记: 。例如: PHP的所有版本均支持该标记。当一个文件中只有PHP代码时,一般省略结束标记,且开始标记最好顶格书写。 2) 短风格形式 开始标记: ; 结束标记: ?>。例如: echo "Hello World"; ?> 使用PHP的短风格标记,需要开启PHP的short_open_tag指令。若要使用该标记进行快速输出,还可以采用如下形式。 = "Hello World" ?> PHP的所有版本均支持该输出形式的短风格标记,与PHP的short_open_tag指令是否开启无关。 在程序设计过程中,为了便于代码的阅读与维护,在编写某行代码或功能模块时,常常需要添加注释,来对代码进行解释或说明。PHP的注释分为单行注释和多行注释。 1) 单行注释 PHP的单行注释使用“//”或“#”两种格式。例如: 2) 多行注释 PHP的多行注释使用“/**/”或“/***/”两种格式。例如: 或 在PHP中,多行注释可以嵌套单行注释,但不能再嵌套多行注释。 2. 标识符与关键字 在程序设计过程中,经常需要定义一些符号来标记一些名称,例如变量名、函数名、类名等,这些符号被称为标识符。 PHP中的标识符必须满足以下规定。 (1) 标识符只能由字母、数字和下画线组成。 (2) 标识符可以由一个或多个字符组成,且必须以字母或下画线开头。 (3) 当标识符用作变量名时,区分大小写。 (4) 标识符可以是任意长度。 (5) 标识符不能与PHP预定义关键字相同。 与C、C++、Java等语言不同,在PHP中,变量名是可以使用其关键字的,但建议最好不要这样做,以避免产生不必要的麻烦。 PHP的关键字是预先定义好并赋予了特殊含义的单词,也称为保留字,包括关键词、预定义类、预定义常量,以及其他保留字。详情请参见PHP手册附录。 3. 变量与常量 变量是可以在不同时刻存储不同数据的符号,它实际上表示了某个内存单元。存放在内存单元中的数据,可以在程序执行期间进行处理。 PHP的变量由“$”符号和变量名组成,其中的变量名就是前述的标识符。例如: $str = "php"; 在PHP中,变量名大小写敏感。 除普通变量之外,在PHP中还可以定义可变变量。所谓可变变量,就是变量名可以变化的变量。例如: $str = "php"; $$str = "PHP"; 其中,“$$str”就是可变变量,它的名字由变量“$str”的值确定。这里,可变变量“$$str”就是表示变量“$php”。 由于PHP是弱类型语言,变量不需要事先声明,可以直接赋值使用。PHP中的变量赋值分为传值赋值和引用赋值两种形式。 1) 传值赋值 定义两个变量,赋值并输出,如下。 $str = "php"; $php = $str; //传值赋值 $str = 'java'; echo $php; 示例输出变量“$php”的值“php”,不会因为变量“$str”的值变化为“java”而改变。 2) 引用赋值 定义两个变量,赋值并输出,代码如下。 $str = "php"; $php = &$str; //引用赋值 $str = 'java'; echo $php; 示例输出变量“$php”的值“java”,它随变量“$str”的值的变化而变化。 除变量之外,在PHP中还可以使用常量来存储数据。常量用于存储在程序运行过程中始终保持不变的数据。 PHP中的常量通常使用函数define()或关键字const来定义。例如: define('PI',3.1416); const PAI = 3.1415; 常量一旦被定义,就不能再修改它的值,也不能重新定义。 4. 数据类型 数据类型是具有一组相同属性的数据的统称。PHP支持三大类的数据类型,分别为标量数据类型、复合数据类型和特殊数据类型。 1) 标量数据类型 PHP的标量数据类型包括4种,分别是boolean(布尔型)、integer(整型)、float(浮点型,也称为double)和string(字符串型)。例如: $boolean1 = true; //布尔型 $boolean2 = false; //布尔型 $boolean3 = (bool)-10; //布尔型 $boolean4 = (bool)''; //布尔型 $int1 = 10; //十进制整型 $int2 = 0b10; //二进制整型 $int3 = 010; //八进制整型 $int4 = 0x10; //十六进制整型 $int_min = PHP_INT_MIN; //最小整型值 $int_max = PHP_INT_MAX; //最大整型值 $int_size= PHP_INT_SIZE; //整型值的字长 $float1 = 3.0; //浮点型 $float2 = 3.1415926; //浮点型 $float3 = 3.14e-2; //浮点型 $float4 = 3.14E+2; //浮点型 $string1 = 'php'; //字符串 $string2 = "java"; //字符串 $string3 = <<PHP的数据类型
浮点型数据
HTML; //字符串 注意PHP的数据的不同表达方式。 2) 复合数据类型 PHP的复合数据类型包括三种,分别是array(数组)、object(对象)和callable(可调用)。例如: $array1 = array('php','java','c++'); //索引数组 $array2 = ['php','java','c++']; //索引数组 $array3 = array('课程1'=>'php', '课程2'=>'java'); //关联数组 $array4 = $_SERVER; //预定义数组 $array5 = range(1,10); //索引数组 class Student { private $name; public function setName($name) { $this->name = $name; } public function getName(){ return $this->name; } } $obj1 = new Student; //对象 $obj2 = (object)10; //对象 $double = function ($param) { return $param*2; }; //对象 $num = range(1, 5); $result = array_map($double,$num); //函数的第1个参数为callable类型 PHP的“可调用”数据类型,就是指的“回调函数”,其值表示回调函数的名称。 3) 特殊数据类型 PHP的特殊数据类型包括两种,分别是resource(资源)和NULL(空或不存在)。例如: $file = fopen('doc.txt','r'); //资源类型 $name = NULL; //NULL类型 @var_dump($password); //此时的变量$password为NULL类型 $str = 'php'; settype($str,'NULL'); //函数调用后变量$str为NULL类型 需要注意的是,PHP中变量的数据类型,通常由该变量使用的上下文在运行时自动设定,程序设计者一般不会手动去设置。 5. 运算符 与其他高级语言一样,PHP提供了丰富的运算符,用于处理各种类型的数据。PHP的运算符分为算术运算符、字符串连接运算符、赋值运算符、比较运算符、逻辑运算符、条件运算符、自增自减运算符、位运算符,以及错误抑制运算符等。 1) 算术运算符 PHP的算术运算符有7种,分别是-(取负)、+(加法)、-(减法)、*(乘法)、/(除法)、%(取模)、**(乘方)。例如: $a = 10; $b = 20; $r1 = -$a; //取负 $r2 = $a + $b; //加法 $r3 = $a - $b; //减法 $r4 = $a * $b; //乘法 /* 两个数相除,运算结果通常为浮点型数据; 只有当两个操作数均为整型且能整除时,运算结果才为整型数据*/ $r5 = $a / $b; //除法,结果为浮点数 $r6 = $a / 5; //除法,结果为整数 /*取模运算符的操作数在运算之前都会自动转换成整数,取模运算符的结果和被除数的符号(正负号)相同*/ $r7 = $a % 3; //取模,结果为1 $r8 = $a % -3; //取模,结果为1 $r9 = $r1 % 3; //取模,结果为-1 $r10 = $r1 % -3; //取模,结果为-1 $r11 = $a ** 2; //乘方,结果为整数 $r12 = $a ** -0.5; //乘方,结果为浮点数 与C、C++和Java等高级语言不同的是,PHP的变量不需要预先定义,在程序的任何地方给一个新变量赋值,PHP引擎都会自动定义该变量。 2) 字符串连接运算符 在PHP中,使用字符串连接运算符(.)将两个字符串拼接成一个字符串。例如: $str1 = 'Hello '; $str2 = 'PHP'; $str = $str1.$str2; 当然,也可以使用字符串连接函数。 3) 赋值运算符 PHP中的赋值运算符,包括基本赋值运算符(=)和复合赋值运算符(如+=等)。复合赋值运算符也称为组合运算符,适合所有的二元运算符。例如: $a = 10; //赋值 $b = 20; $a += $b; //加等于,相当于$a = ($a+$b) $a -= $b; //减等于 $a *= $b; //乘等于 $a /= $b; //除等于 $a %= $b; //模等于 $a **= $b; //乘方等于 $a .= $b; //连接等于 PHP实质上是HTML代码生成器,在实际开发过程中,会频繁使用“.=”来拼接HTML代码,希望读者熟练掌握该运算符的使用方法。 4) 比较运算符 PHP的比较运算符有9种,分别是==(等于)、!=(不等于)、<>(不等于)、===(恒等于)、!==(不恒等)、>(大于)、<(小于)、>=(大于或等于)、<=(小于或等于)。例如: $a = 10; $b = '10'; $r1 = ($a == $b); //等于,结果为true $r2 = ($a != $b); //不等于,结果为false $r3 = ($a <> $b); //不等于,结果为false $r4 = ($a === $b); //恒等于,结果为false $r5 = ($a !== $b); //等于,结果为true $r6 = ($a == $b); //等于,结果为true $r7 = ($a > $b); //大于,结果为false $r8 = ($a < $b); //小于,结果为false $r9 = ($a >= $b); //大于或等于,结果为true $r10 = ($a <= $b); //小于或等于,结果为true 在PHP中,当两个数据类型不相同的数据进行比较时,会自动将其转换成相同类型的数据后再进行运算。在进行恒等与不恒等运算时,除比较操作数的数值是否相同外,还要判断它们的数据类型是否一样。 5) 逻辑运算符 PHP的逻辑运算符有4种,分别是&&(与)或and(与)、| |(或)或or(或)、!(非)、xor(异或)。例如: $a = true; $b = false; $r1 = $a && $b; //逻辑与,结果为false $r2 = $a and $b; //逻辑与 $r3 = $a || $b; //逻辑或,结果为true $r4 = $a or $b; //逻辑或 $r5 = !$a; //逻辑非,结果为false $r6 = $a xor $b; //逻辑异或,结果为true 在PHP中,尽管&&、| |与and、or功能相同,但前者的优先级别高于后者; 对于“与”运算和“或”运算,在使用时需要注意以下两点。 (1) 进行逻辑“与”运算时,如果两个操作数均为表达式,当左边表达式的值为false时,右边表达式不会执行,逻辑运算结果为false。例如: $a = 1; $r = (1 > 2) && ($a += 1); 由于表达式1>2的值为false,则表达式$a+=1不会被执行,也就是变量$a的值仍为1,此时变量$r的值为false。 (2) 进行逻辑“或”运算时,如果两个操作数均为表达式,当左边表达式的值为true时,右边表达式不会执行,逻辑运算结果为true。例如: $a = 1; $r = (1 < 2) || ($a += 1); 由于表达式1<2的值为true,则表达式$a+=1不会被执行,也就是变量$a的值仍为1,此时变量$r的值为true。 6) 条件运算符 条件运算符(? : )是PHP中唯一的一个三元运算符,其运算结果由第1个操作数(或表达式)的值确定。当第1个操作数的值为true时,运算结果为第2个操作数(或表达式)的值; 否则,运算结果为第3个操作数(或表达式)的值。例如: $a = 10; $b = 20; $r = ($a > $b) ? $a : $b; 上述代码中,由于表达式“$a>$b”的值为false,则变量$r的值等于变量$b的值。 7) 自增自减运算符 PHP的自增(++)、自减(--)运算符,也称为递增、递减运算符,是一种特定形式的复合赋值运算符。例如: $a = 10; $r1 = $a++; //后缀自增,执行后变量$r1的值为10,变量$a的值为11 $r2 = ++$a; //前缀自增,执行后变量$r1的值为11,变量$a的值为11 $r3 = $a--; //后缀自减,执行后变量$r1的值为10,变量$a的值为9 $r4 = --$a; //前缀自减,执行后变量$r1的值为9,变量$a的值为9 在实际开发过程中,一般仅在循环结构中使用这些运算符,强烈不建议让它们参与混合运算。 8) 位运算符 位运算符,就是对整型数据的各个位进行操作。这些操作分别为&(按位与)、|(按位或)、~(取反)、<<(左移)、>>(右移)。例如: $a = 0b1010; $b = 0b1111; $r1 = $a & $b; //按位与,执行后变量$r1的值为1010(二进制)或10(十进制) $r2 = $a | $b; //按位或,执行后变量$r2的值为1111(二进制)或15(十进制) $r3 = $a ^ $b; //按位异或,执行后变量$r3的值为0101(二进制)或5(十进制) $r4 = ~$a; //按位取反 $r5 = $a << 1; //左移,将$a的每个位都向左移动一位,即变量$a乘以2 $r6 = $a >> 1; //右移,将$a的每个位都向右移动一位,即变量$a除以2 PHP的位运算与其算术运算相比较,其执行效率高,运行速度快。 9) 错误抑制运算符 PHP支持一个错误控制运算符@。当将其放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉。例如: $a = 10; $r = @($a + $b); //由于变量$b没有定义,执行该语句时会出现错误,使用@将其抑制 当然,也可以使用PHP的错误显示函数来控制页面中的错误显示级别。 10) 类型运算符 instanceof用于确定一个PHP变量是否属于某一个类的实例。例如: $a = 10; $r1 = $a instanceof stdClass; //变量$r1的值为false $a = (object)$a; $r2 = $a instanceof stdClass; //变量$r2的值为true 这里的stdClass为PHP预定义的标准类。 6. 数据类型转换 在PHP中,对两个变量进行操作时,若其数据类型不相同,则需要对其进行数据类型转换。通常情况下,数据类型转换分为自动类型转换和强制类型转换。 1) 自动类型转换 自动类型转换也称为隐式转换,是指当运算需要或与期望的结果类型不匹配时,PHP会将数据类型进行自动转换。例如: $a = 10; $b = "20"; $c = "3.14e2"; $r1 = $a + $b; //变量$r1的值为30,变量$b被自动转换为整型数据 $r2 = $c * 2; //变量$r2的值为624,变量$c被自动转换为浮点型数据 $r3 = $a ? $b : null; //变量$r3的值为"20",变量$a被自动转换为布尔型数据 $r4 = $a . $b; //变量$r4的值为"1020",变量$a被自动转换为字符串型数据 PHP的自动类型转换规则与C、C++和Java基本相同。 2) 强制类型转换 强制类型转换也称为显式类型转换,是指在编写程序时,将一个变量强制转换为与原类型不同的另一种类型。其实现方法有两种,一是通过强制类型转换运算符,另一种就是通过调用settype()、intval()、floatval()等函数。 PHP提供了8种强制类型转换运算符,它们是bool或boolean、int或integer、float或double或real、string、array、object、binary和unset。例如: $a = 10; $b = "20PHP"; $c = "0"; $r1 = (bool)$a; //强制转换为布尔型,变量$r1的值为true $r2 = (boolean)$c; //强制转换为布尔型,变量$r2的值为false $r3 = (float)$b; //强制转换为布尔型,变量$r3的值为true $r4 = (string)$a; //强制转换为字符串型,变量$r4的值为"10" $r5 = (array)$a; //强制转换为数组,变量$r5的值为array(0=>10) $r6 = (object)$a; //强制转换为stdClass对象,变量$r5的scalar属性值为10 $r7 = (binary)$a; //强制转换为二进制字符串,变量$r7的值为"0b10" echo bindec($r7); //输出十进制整数2 $r8 = (unset)$a; //强制转换为NULL类型 需要注意的是,使用强制类型转换符将变量的类型转换为新类型,只是改变了其参与运算时的类型,变量本身的数据类型并没有发生变化。 使用函数实现数据类型的强制转换。例如: $a = 10; $b = 3.14; $c = true; settype($a,'float'); //将变量$a由整型强制转换为浮点型 var_dump($a); //输出变量$a的数据类型为float $r1 = intval($b); //取整,变量$r1为整型数据3,变量$b仍为浮点数3.14 $r2 = strval($c); //转换为字符串,变量$r2为字符串"1",变量$c仍为整数10 $r3 = floatval(20); //转换为浮点型数据 注意区分变量本身的类型与其参与运算时的临时类型之间的差别。在PHP的高版本中,会更加强调变量的数据类型,尤其是在调用自定义函数的时候。在PHP的高版本中,在定义函数时,要求指定形参的数据类型以及返回值的数据类型。 3.1.2流程控制 流程控制就是确定应用程序中的代码执行流程。例如,程序中的某代码块是否需要执行,是否需要执行多次; 是否需要从主流程进入辅流程(函数流程等); 是否需要执行其他文件中的代码等。 1. 分支结构 PHP的分支结构分为单分支和多分支。 1) 单分支 使用if条件判断语句,来实现流程的单分支。例如: $a = 10; $b = 20; if($a >= $b){ echo $a; //当条件为真时,执行该语句 } 2) 多分支 在PHP中,使用if…else…语句、if…elseif…else…语句和switch语句,实现流程的多分支。例如: $a = 10; $b = 20; if($a > $b){ echo $a; //当条件为真时,执行该语句 }else{ echo $b; //当条件为假时,执行该语句 } if($a%2 == 0){ echo $a.'是偶数'; }elseif($a%3 == 0){ echo $a.'是奇数,也是3的倍数'; }else{ echo $a.'是奇数,但不是3的倍数'; } switch($a%3){ case 1: echo '变量$a除以3余1'; break; //跳出switch结构 case 2: echo '变量$a除以3余2'; break; default: echo '变量$a是3的倍数'; break; } 这些结构与C、C++和Java语言几乎一样。 2. 循环结构 PHP有4种形式的循环结构,分别是while、do…while、for和foreach。例如: $data = range(1, 100); $i = 0; $sum = 0; while ($i<100){ $sum += $data[$i]; $i++; } $i = 0; $sum = 0; do{ $sum += $data[$i]; $i++; }while ($i<100); for ($i = 0, $sum = 0; $i < 100; $i++) { $sum += $data[$i]; } $sum = 0; foreach ($data as $value) { $sum += $value; } $sum = 0; foreach ($data as $key=>$value) { $sum += $value; } echo $sum; 在PHP的循环结构中,常常使用continue语句终止本次循环,而使用break语句终止循环。例如: $data = range(1, 100); $i = 1; $sum = 0; while ($i++){ if($i%2) continue; //若为奇数,终止本次循环 if($i>100) break; //若变量$i的值大于100,终止循环 $sum += $data[$i-1]; } echo $sum; //输出1~100中所有偶数之和 循环结构一般用于对集合数据的遍历。 3. 函数 PHP的函数分为自定义函数和内置函数。 1) 自定义函数 自定义PHP函数,可以采用如下示例中的两种格式。 //PHP 7以下版本格式,PHP 7兼容这种格式 function sum($data) { $sum = 0; foreach ($data as $value) { $sum += $value; } return $sum; } $data = range(1, 100); //测试数据 echo sum($data); //输出1~100所有自然数之和 //PHP 7版本新增格式 function dataSum(array $data):float { $sum = 0; foreach ($data as $value) { $sum += $value; } return $sum; } $data = array(1.2, 2.3, 10, 20.5); //测试数据 //$data = 2.5; //若将该变量作为实参传入dataSum()函数,会出现数据类型错误 var_dump(dataSum($data)); //输出的值为float数据类型 PHP的高版本会逐渐加强对数据类型的检查,所以建议使用上述新格式来定义PHP函数。 2) 内置函数 内置函数是预先在PHP中定义的函数,可以直接使用。在PHP的核心库及扩展库中,预定义了丰富的函数,正是这些函数成就了PHP的强大功能。 在PHP的核心库中,常用的内置函数主要有以下几种。 (1) 字符串函数: strlen()、strrpos()、str_replace()、substr()等。 (2) 数组函数: is_array()、count()、range()、sort()、rsort()、ksort()、krsort()、array_search()、array_unique()、array_column()、array_keys()、array_values()、array_unshift()、array_push()、array_shift()、array_pop()、in_array()、array_key_exists()等。 (3) 数学函数: abs()、ceil()、floor()、fmod()、is_nan()、max()、min()、pi()、pow()、sqrt()、round()、rand()等。 (4) 日期时间函数: checkdate()、date()、gettimeofday()、getdate()、time()、mktime()、setlocale()、strftime()、strtotime()、getlastmod()等。 PHP的内置函数的使用方法,请参考PHP手册或其他技术文档。 4. 文件包含 为了提高效率,在项目开发过程中需要特别注重代码的重用性以及功能的模块化。PHP提供了4种在应用程序中包含文件的语句,用于组装被隔离的单独的功能模块。 1) include与include_once include语句将在其被调用的位置处判断并包含一个文件; include_once与include功能相同,不同的是,它会首先判断是否已经包含该文件。例如: if(file_exists('./inc.php') { include './inc.php'; }) 或 if(file_exists('./inc.php') { $data = include_once './inc.php'; //被包含的文件中有return语句 }) 若被包含的文件不存在,使用上述包含语句时,PHP会给出错误信息,程序会继续运行。 2) require与require_once require和require_once语句的用法与include、include_once相同,区别在于,若被包含的文件不存在,使用require和require_once语句时,PHP会给出错误信息,并终止程序运行。 3.1.3字符串 字符串是PHP的重要数据类型,也是PHP应用程序中使用最多的一种数据。 1. 字符串的定义 PHP提供了4种定义字符串的方法,分别是单引号('')、双引号("")和定界符(<<课程简介: $str2
HTML; //定界符:heredoc 结构,定界符可以为任意的PHP标识符 $str4 = <<<'HTML'课程简介: $str2
HTML; //定界符:nowdoc 结构,开始标识符要用单引号引起来 echo $str1.''; print_r($result); echo ''; 上述例程输出: Array ( [color] => Array ( [favorite] => Array ( [0] => red [1] => green ) [0] => blue ) [0] => 5 [1] => 10 ) 当某个输入数组中的某个键已经存在于结果数组中时,函数array_merge_recursive()把两个值合并在一起,形成一个新的数组,并以原有的键作为键名。 2) 连接数组 使用函数array_combine()创建一个新数组,以一个数组的值作为其键名,另一个数组的值作为其值。例如: $keys = array('username','password'); $values = array('王一','123456'); $user = array_combine($keys, $values); print_r($user); //输出Array([username]=>王一[password]=>123456) 3) 拆分数组 使用函数array_chunk()将一个数组分割成多个。例如: $array = range(1, 5); $r = array_chunk($array, 2); //将数组进行拆分,每个子数组包含两个元素 echo '
'; print_r($r); echo ''; 上述例程输出: Array ( [0] => Array ( [0] => 1 [1] => 2 ) [1] => Array ( [0] => 3 [1] => 4 ) [2] => Array ( [0] => 5 ) ) 若使用如下函数调用形式: $r = array_chunk($array, 2, true); 则会保留原数组中的键/值顺序,上述输出结果变成如下形式。 Array ( [0] => Array ( [0] => 1 [1] => 2 ) [1] => Array ( [2] => 3 [3] => 4 ) [2] => Array ( [4] => 5 ) ) 使用函数array_slice()取出数组中的一部分。例如: $array = range(1, 5); $r = array_slice($array, 2, 2); print_r($r); //输出Array([0]=>3[1]=>4) 使用函数array_splice()去掉数组中的某一部分,并用其他值取代。例如: $array = range(1, 5); $r = array_splice($array, 2, 2, array(10,20)); print_r($array); //输出Array([0]=>1[1]=>2[2]=>10[3]=>20[4]=>5) print_r($r); //输出Array([0]=>3[1]=>4) 4) 获取数组的交集与差集 使用函数array_intersect()、array_diff()、array_intersect_assoc()、array_diff_assoc()获取数组的交集或差集。例如: $array1 = array("a" => "green", "red", "blue"); $array2 = array("b" => "green", "yellow", "red"); $r1 = array_intersect($array1, $array2); $r2 = array_diff($array1, $array2); $r3 = array_intersect_assoc($array1, $array2); $r4 = array_diff_assoc($array1, $array2); print_r($r1); //输出Array ([a] => green[0] => red ) print_r($r2); //输出Array ([1] => blue ) print_r($r3); //输出Array ( ) print_r($r4); //输出Array ([a] => green[0] => red[1] => blue ) 5) 其他数组函数 除了上述介绍的数组函数之外,还有很多不同功能的数组处理函数。例如,从数组中随机取出一个或多个元素的函数array_rand(); 对数组中所有值求和的函数array_sum(); 随机以数组进行重排的函数shuffle(); 获取数组中的指定列的函数array_column()等,这些函数的使用方法请参考相关的技术文档。 3.1.5错误处理 在运行PHP程序时,难免会出现各种各样的错误,需要对这些错误的显示进行控制。PHP中的错误级别主要包括E_ALL、E_COMPILE_ERROR、E_COMPILE_WARNING、E_CORE_ERROR、E_CORE_WARNING、E_ERROR、E_NOTICE、E_WARNING、E_PARSE、E_RECOVERABLE_ERROR、E_STRICT、E_USER_ERROR、E_USER_WARNING、E_USER_NOTICE、E_DEPRECATED、E_USER_DEPRECATED等。 使用函数error_reporting()设置应该报告哪一种级别的PHP错误。例如: error_reporting(E_NOTICE); //显示提示信息 echo $a; //这里会有运行提示信息 include 'doc.txt'; //假设doc.txt文件不存在,这里会有E_WARNING信息 当给函数error_reporting()传递参数E_ALL时,会显示所有的错误信息; 当给其传递参数0时,则不显示任何级别的错误。 PHP中错误的显示除了使用上述函数外,还可以通过设置php.ini中的相关配置项来进行控制。这些配置项主要有error_reporting、display_errors、display_startup_errors、log_errors、log_errors_max_len、ignore_repeated_errors、ignore_repeated_source等。它们的含义请参考相关的技术文档。 视频讲解 3.2面向过程编程 PHP程序设计可以采用面向过程方法,也可以采用面向对象方法。使用面向过程的方法进行程序设计,主要是通过PHP的内置函数和用户自定义函数来实现程序功能,它涉及数据的输入与检验、会话处理、文件和数据库操作等相关技术。 3.2.1数据输入 PHP程序的数据输入方式有多种,包括URL查询字符串、Web表单、文件以及数据库等。为了保证输入数据的安全,需要对接收到的用户数据进行检验、过滤等相关处理。 1. 查询字符串 查询字符串是附加在URL后面的字符串,它一般以“?”符号开头,并以“参数名/值”对的形式传递参数。例如: https://www.example.com?id=1&page=1 当有多个参数需要传递时,使用“&”符号进行连接。 通过查询字符串传递的参数,采用GET数据传送方式,它存储在PHP的预定义数组$_GET中,可以直接通过参数名来获取。例如: $id = $_GET['id']; $page = $_GET['page']; 接收到的GET数据一般要进行安全处理。例如: $id = isset($_GET['id'])?trim($_GET['id']):false; if (!filter_var($id,FILTER_VALIDATE_INT)) { echo '数据类型错误'; } 这里采用PHP内置函数对用户输入数据进行处理。 2. Web表单 Web表单是PHP与用户交互的主要方式,通过表单提交的数据,可以采用GET方式或POST方式来传递数据,但一般都使用POST方式。例如: 通过POST方式传递的数据,存储在PHP的预定义数组$_POST中,可以通过参数名来获取。例如: $username = $_POST['username']; 为了保证数据的安全,需要对用户输入的数据进行检查与处理。例如: $username = isset($_POST['username'])?trim($_POST['username']):''; $username = htmlentities($username); 这里采用PHP内置函数对用户输入数据进行处理。也可以使用自定义函数来检验用户输入的数据是否符合格式、类型等要求。例如: function validateUsername($username) { $pattern = '/^[\w\x{4E00}-\x{9FA5}]{2,10}$/u'; if (!preg_match($pattern, $username)) { return '用户名只允许使用英文字母、数字、下画线和汉字,长度为2~10'; } return true; } 采用正则表达式对用户输入数据进行验证。 3. 文件 文件是数据的常用存储方式,可以从文件中批量导入数据作为PHP程序的输入。 1) 配置文件 从配置文件中导入数据。例如: //config.ini配置文件 # 应用设置 appName = example # 数据库配置 host = localhost user = root password = 123456 database = exampleDB //导入config.ini中的数据 $filename = 'inc.ini'; $config = parse_ini_file($filename); echo '
'; print_r($config); echo ''; 示例代码输出: Array ( [appName] => example [host] => localhost [user] => root [password] => 123456 [database] => exampleDB ) 2) 其他文件 将数据以特定的格式存储在文件中,通过读取文件内容,将数据导入PHP程序中。具体操作方法见后续的3.2.3节。 4. 数据库 数据的持久化,一般都是通过文件和数据库来实现的。因此,将数据库中的数据读取到PHP程序中,即可作为程序的输入数据来使用。具体操作方法见后续的3.2.4节。 3.2.2会话管理 HTTP(超文本传输协议)定义了通过万维网(WWW)传输文本、图形、视频和所有其他数据所用的规则。它是一种无状态的协议,也就是说,服务器对每次的处理都与之前或之后的请求无关。 在PHP中,解决HTTP的无状态问题可以使用两种技术,一种是Cookie技术,另一种是Session技术。Session也被称为会话。 1. 配置 在PHP的配置文件php.ini中,有许多与Session或Cookie有关的配置项,它们负责确定PHP会话处理的功能行为。主要有session.save_handler、session.save_path、session.use_strict_mode、session.use_cookies、session.use_only_cookies、session.name、session.auto_start、session.cookie_lifetime、session.cookie_path、session.cookie_domain、session.cookie_httponly、session.referer_check等。 2. Cookie技术 Cookie是Web应用为了辨别用户而存储在客户端的数据。通过Cookie,可以跟踪用户与服务器之间的会话状态,通常应用于保存浏览历史、保存用户登录状态等场景。 1) 创建Cookie 使用函数setcookie()创建或修改Cookie。例如: setcookie('username','李木子',time()+60); //1分钟后过期 setcookie('username','李木子',time()+24*60*60); //1天后过期 setcookie('username','李木子',time()-1); //立即过期,删除Cookie 2) 使用Cookie 当浏览器向服务器发送请求时,会携带GET、POST和Cookie等数据,因此,可以通过PHP的预定义数组$_COOKIE来获取Cookie数据。例如: If(isset($_COOKIE['username'])){ $username = $_COOKIE['username']; //从Cookie中获取username数据 } 注意: 当PHP第1次通过setcookie()函数创建Cookie时,$_COOKIE数组中没有这个数据,只有当浏览器再次请求并携带Cookie时,才能通过$_COOKIE数组获取到该数据。 3. Session技术 Session在Web应用中称为“会话”,是指用户在访问某个Web应用时,从进入应用到离开应用所经过的时间。Session技术是一种服务器端的技术,它的生命周期从用户访问应用开始,直到断开与应用的连接时结束。当PHP启动Session时,服务器为每个用户的浏览器创建一个供其独享的Session文件,用于保存用户登录状态、验证码等。 当服务器创建Session时,每个Session文件都具有一个唯一的会话ID,用于标识不同的用户。会话ID分别保存在客户端和服务器端两个位置。在客户端上通过浏览器Cookie来保存,在服务器端以文件的形式保存在指定的Session目录中。 1) 启动Session 在使用Session之前必须先启动。使用session_start()函数启动Session。 2) 使用Session 通过预定义数组$_SESSION,来添加、读取或修改Session中的数据。例如: Session_start(); $_SESSION['username'] = '李木子'; //添加Session数据 if(isset($_SESSION['password'])){ $password = $_SESSION['password']; //获取Session数据 } 3) 删除Session数据 可以删除Session中的单个数据,也可以销毁全部的Session数据。例如: unset($_SESSION['username']); //删除单个数据 $_SESSION = array(); //删除所有数据 Session_unset(); //删除所有数据 Session_destroy(); //结束会话 4) 编码和解码Session数据 无论采用什么样的存储方式,PHP都会以标准化格式存储Session数据。例如: username|s:9:"李木子";password|s:32:"e10adc3949ba59abbe56e057f20f883e"; 从示例可以看出,各个会话变量用分号隔开,每个会话变量由3部分组成,即名称、长度和值。 PHP自动处理会话的编码和解码。若需要手工执行这些操作,可以使用session_encode()和session_decode()函数。例如: session_start(); $_SESSION['username'] = '李木子'; $_SESSION['password'] = md5('123456'); $session = session_encode(); //会话编码 session_unset(); //清空所有数据 echo $session; //输出格式化的所有会话数据 echo '
'; print_r($file); echo ''; 示例代码输出: Array ( [0] => # 应用设置 [1] => appName = example [2] => # 数据库配置 [3] => host = localhost [4] => user = root [5] => password = 123456 [6] => database = exampleDB ) 2) 将文件内容读入字符串变量 使用file_get_contents()函数将文件中的内容读到字符串中。例如: $filename= 'inc.ini'; //上述1)中的测试文件 $file = file_get_contents($filename); $file = nl2br($file); echo $file; 示例代码输出: # 应用设置 appName = example # 数据库配置 host = localhost user = root password = 123456 database = exampleDB 还可以使用fread()和readfile()函数,将文件中的内容读到字符串中。例如: $filename= 'inc.ini'; $file = fopen($filename, 'r'); $fcontent = fread($file,filesize($filename)); //变量$fcontent为字符串 fclose($file); $size = readfile($filename); //将文件内容输出到缓存中,返回文件大小 $content = ob_get_contents(); //获取缓存数据 ob_clean(); //清除缓存 echo '文件大小:'.$size.'
'; print_r(unserialize($content)); //恢复到PHP的变量形式,这里为数组 echo ''; 除fwrite()函数之外,还可以使用file_put_contents()函数将数据写入文件中。 5. 文件上传 在PHP中,通过适当的配置,利用上传表单可以将客户端的文件上传到服务器上。 1) 文件上传配置 若通过PHP上传文件,首先需要在PHP的文件中进行适当的配置。相关的配置项主要有file_uploads、upload_tmp_dir、upload_max_filesize、max_file_uploads、post_max_size等。 2) 文件上传表单 上传的文件数据通过POST方法传送,表单的enctype必须设置为multipart/formdata。例如: 3) 上传文件的接收 在PHP中,与上传文件有关的信息存储在预定义数组$_FILES中。例如: '; print_r($_FILES); //输出上述2)中的表单上传的文件信息 echo ''; ?> //示例代码输出下面的数组 Array ( [upload] => Array ( [name] => pic_htmltree.gif [type] => image/gif [tmp_name] => E:\wampserver3.0.6\tmp\php1B66.tmp [error] => 0 [size] => 3051 ) ) 4) 上传文件的移动 PHP上传文件存储在服务器上的临时目录中,需要将其移动到指定的目录下。使用函数copy()或move_upload_file()实现上传文件的移动。例如: if (is_uploaded_file($_FILES['upload']['tmp_name'])) { copy($_FILES['upload']['tmp_name'], './upload/'.$_FILES['upload']['name']); } 将上传文件复制到当前目录下的upload子目录中,文件名不变。 $ext = explode('.', $_FILES['upload']['name']); move_uploaded_file($_FILES['upload']['tmp_name'], './upload/'.time().".$ext[1]"); 将上传文件移动到当前目录下的upload子目录中,并更改文件名。 3.2.4数据库操作 PHP支持多种数据库的操作,下面以MySQL为例简单介绍。 1. 使用mysqli扩展 PHP对数据的支持,是通过扩展来实现的。打开PHP的配置文件php.ini,开启相应的数据库扩展。例如: extension = php_mysqli.dll 启用该配置,开启mysqli扩展。 2. 连接数据库 使用mysqli_connect()函数连接MySQL数据库。例如: $link = @mysqli_connect('localhost','root','123456','exampleDB'); 该函数其实是函数mysqli::__construct()的别名。 若连接时出现错误,可以使用mysqli_connect_errno()和mysqli_connect_error()函数判断并显示错误信息。 3. 执行查询 可以使用mysqli_query()函数执行查询。例如: $query = 'show databases';//查询语句 $result = mysqli_query($link, $query);//执行查询 该函数为mysqli::query()函数别名。 4. 处理结果集 执行查询后得到的结果集的类型,与查询的种类有关。例如,成功执行select查询后返回的是mysqli_result对象; 而执行insert后,返回的是受影响的行数。所以,要根据不同的结果类型,进行不同的处理。 下面是执行select查询后的示例。 $query = 'select * from users'; $result = mysqli_query($link, $query); mysqli_close($link); //断开连接 $data = mysqli_fetch_all($result); //从结果集中取出所有记录(数组形式) mysqli_free_result($result); //释放资源 除了以数组的形式保存数据之外,也可以使用对象形式; 数组可以使用索引数组,也可以使用关联数组; 可以从结果集中取出所有的数据,也可以只取出一条数据。不同的情况使用不同的函数进行操作,请参考相关的技术文档。 视频讲解 3.3面向对象编程 目前,Web应用开发普遍采用面向对象的程序设计方法,该方法允许开发人员把相似的任务组织在类中,这有助于编写出遵守“不重复自己”(Don’t Repeat Yourself,DRY)原则,并且易于维护的程序代码。 3.3.1类与对象 类是用户自定义的数据类型,是用于生成对象的代码模板; 对象是根据类中定义的模板所构造的数据,也称为类的实例,它是由类定义的数据类型。 1. 类的定义 在PHP中,类由关键字class来声明。例如: class Employee { private $name; public function setName($name){ $this->name = $name; } public function printInfo() { echo $this->name; } } 声明了一个名为Employee的类。其中,$name为属性,setName()和printInfo()为方法。 PHP 7开始支持匿名类,使用匿名类可以创建一次性的简单对象。例如: var_dump(new class{ public function __construct(){ echo '****'; }}); 这里的class{…}为匿名类。 2. 对象的创建 对象是类的实例。通过new关键字创建类的对象。例如: $staff = new Employee;//Employee为1中定义的类 $staff = new Employee(); 类的方法中还可以使用一个名为$this的内部变量,它表示对象本身。该对象默认存在,不需要创建。 3. 对象的使用 对象创建完成后,就可以用它访问对象的属性和方法了。例如: $staff->setName('李木子'); //$staff为2中定义的对象 $staff->printInfo(); //输出字符串"李木子" 注意对象的属性和方法具有访问权限,外部对象只能访问public权限的属性和方法; 内部对象可以访问对象本身的所有权限的属性和方法,以及父类的public、protected权限的属性和方法。例如: $staff->name; //会出现错误 4. 对象方法 对象方法,也就是对象中的函数,用于定义对象的行为。在PHP的类中定义方法,除了必须使用关键字function外,还可以用public、private、protected、abstract、final和static关键字进行修饰。 1) 构造方法 对象的构造方法用于初始化对象,例如给属性赋值、调用方法等。构造方法由PHP自动调用,并且具有特定的名称“__construct”。例如: class Employee { private $name; public function __construct($name=''){ $this->name = $name; } public function printInfo() { echo $this->name; } } $staff = new Employee('李木子'); //自动调用构造方法,初始化name属性 $staff->printInfo(); //输出字符串"李木子" 2) 析构方法 PHP的程序执行完毕后,对象会被自动销毁。也可以在类中定义析构方法,来完成对象的清除工作。例如: class Employee { private $name; public function __construct($name=''){ $this->name = $name; } public function __destruct(){ echo get_class($this).'的对象被销毁!'; } } $staff = new Employee('李木子'); 运行上述程序,会输出字符串“Employee的对象被销毁!”。 3) 魔术方法 在PHP中,将所有以__(双下画线)开头的类方法,称为魔术方法。主要有__construct()、__destruct()、__call()、__callStatic()、__get()、__set()、__isset()、__unset()、__sleep()、__wakeup()、__toString()、__invoke()、__set_state()、__clone()和__debugInfo()等。例如: class Employee { private $name; public function __set($name,$value){ $this->$name = $value; } public function __get($name) { return $this->$name; } } $staff = new Employee; $staff -> name = '李木子'; //给不可访问属性赋值,自动调用__set()方法 echo $staff -> name; //获取不可访问属性值,自动调用__get()方法 若没有在类中定义__set()和__get()魔术方法,用对象$staff访问name属性会出现错误。使用__set()魔术方法,还可以给对象增加属性。例如: $staff = new Employee; $staff -> age = 20; //添加新属性 echo $staff -> age; //输出20 4) 静态方法 在PHP中,用static关键字定义的方法称为静态方法。静态方法既可以通过类的实例访问,也可以通过类名直接访问。例如: class Employee{ private static $name = ''; public static function init($name) { self::$name = $name; } public static function printInfo(){ echo self::$name; } } //通过类名直接调用 Employee::init('李木子'); Employee::printInfo(); //通过类的对象调用 $staff = new Employee; $staff->init('aa'); $staff->printInfo(); 5. 对象属性 对象属性,也就是对象中的变量或常量,用于定义对象的静态特性。属性的定义与普通的PHP变量或常量基本相同,唯一不同的是,它的前面会有public、private、protected、var或static、const关键字修饰。例如: class Employee{ var $name = 'a'; //var相当于public,是对低版本PHP的兼容,最好不使用 private $age; protected $gender; public static $depart = 'b'; //静态属性 const COMPANY = 'WUHAN'; //常量 } 1) 普通属性 普通属性在定义时可以初始化,也可以只声明。如上述示例代码中的$name、$age和$gender。它只能用对象访问。 2) 静态属性 用static关键字修饰的属性,称为静态属性。在类的内部,使用self来对其进行访问; 在类的外部,只能使用类名对其进行访问。例如: echo Employee::$depart;//输出b 需要注意的是,类的静态属性的任何改变,都会反映到该类的所有实例化对象中。例如: class Visitor { private static $visitors = 0; public function __construct() { self::$visitors++; } public static function getVisitors() { return self::$visitors; } } $visits1 = new Visitor(); echo Visitor::getVisitors(); //输出1 echo '
'; Reflection::export($reflector); //输出类的详细信息 代码输出: Class [ class Employee ] { @@ F:\wtu_php_course\test\index.php 2-15 - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [1] { Property [ private $name ] } - Methods [3] { Method [ public method __construct ] { @@ F:\wtu_php_course\test\index.php 4 - 6 - Parameters [1] { Parameter #0 [ $name = '' ] } } Method [ public method getName ] { @@ F:\wtu_php_course\test\index.php 7 - 10 } Method [ public method setName ] { @@ F:\wtu_php_course\test\index.php 11 - 14 - Parameters [1] { Parameter #0 [ $name ] } } } } 从输出结果可以看出,Reflection::export()可以提供类的大量信息,包括属性和方法的访问控制方式、每个方法需要的参数以及每个方法在代码文件中的位置等。 2) 检查类 除了使用Reflection类的静态方法export()查询类信息外,还可以使用反射类中的方法,获取特定的类信息。例如: $class_name = $reflector->getName(); //类名 $isUserDefined = $reflector->isUserDefined(); //是否是用户自定义类 $isInternal = $reflector->isInternal(); //是否是内置类 $isInterface = $reflector->isInterface(); //是否是接口 $isAbstract = $reflector->isAbstract(); //是否是抽象类 $isFinal = $reflector->isFinal(); //是否是最终类 $isInstantiable = $reflector->isInstantiable(); //是否可以实例化 除了以上代码中的方法外,还有很多其他的方法,请参考相关的技术文档。 3) 检查方法 使用ReflectionMethod类的对象检查类中的方法。例如: $reflector = new ReflectionClass('Employee'); //上述1)中Employee类 $methods = $reflector->getMethods(); foreach ($methods as $m) { $method_name[] = $m->name; //变量$m为ReflectionMethod对象 } echo ''; print_r($method_name); //输出Employee类的方法名数组 获取到类的某个方法的ReflectionMethod对象后,就可以使用ReflectionMethod类的成员函数对该方法进行检查了。 ReflectionMethod类的成员函数主要有getDeclaringClass()、isAbstract()、isConstructor()、isPublic()、isStatic()等。这些成员函数的含义及使用,请参考相关的技术文档。 4) 检查属性 使用ReflectionProperty类的成员方法,查询类属性的相关信息。例如: $e = new Employee('李木子'); //上述1)中Employee类 $reflector = new ReflectionClass($e); $properties = $reflector->getProperties(); echo $p[0]->getName(); //输出name var_dump($p[0]->isPrivate()); //输出true $p[0]->setAccessible(true); //设置可返回属性 echo $p[0]->getValue($e); //输出"李木子" 5) 反射API的使用 使用PHP的反射API可以动态地调用对象中的方法。 例如,假设需要根据用户的请求来调用控制器的不同方法,可以使用如下的示例代码。 class Controller{ //测试用控制器 public function index() { echo 'index'; } public function login() { echo 'login'; } public function register() { echo 'register'; } } $action = 'login'; //用户请求的控制器方法 $class = new ReflectionClass('Controller'); $controller = $class->newInstance(); if ($class->hasMethod($action)) { //若请求的方法存在,则执行该方法 $class->getMethod($action)->invoke($controller); }else{ //若请求的方法不存在,则执行控制器的index方法 $class->getMethod('index')->invoke($controller); } 3.3.5数据库操作 在PHP中,使用面向对象的方法与MySQL数据库进行交互,既可以使用mysqli扩展,也可以使用PDO扩展。 1. 使用mysqli扩展 打开PHP的配置文件php.ini,开启mysqli数据库扩展。 extension = php_mysqli.dll 1) 连接数据库 使用面向对象方法连接MySQL,需要实例化mysqli扩展中的mysqli类,该类的对象表示了PHP和MySQL数据库之间的一个连接。 使用mysqli类的对象连接MySQL,可以使用以下两种形式。 (1) 构造方法。其语法格式为: $link = new mysqli($host = null, $username = null, $passwd = null, $dbname = null, $port = null, $socket = null)); (2) 成员方法。其语法格式为: $objLink = new mysqli(); $link = $objLink->connect($host = null, $user = null, $password = null, $database = null, $port = null, $socket = null); 从上述面向对象的两种格式可以看出,不管是使用构造方法,还是使用connect()成员方法,需要的参数都是一样的,这些参数也都与mysqli_connect()函数参数相同。其实,mysqli_connect()只是mysqli类的connect对象方法的别名而已。 例如,假设需要连接本地MySQL的mydatabase数据库,登录用户名为root,密码为123456,则连接代码为: $link = new mysqli('localhost', 'root', '123456', 'mydatabase'); 或 $link = new mysqli(); $link->connect('localhost', 'root', '123456', 'mydatabase'); 2) 执行查询 使用mysqli类成员函数query()来执行一个SQL查询。该函数原型如下。 mixed mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] ) 其中,参数query为必选项,指定查询字符串,也就是SQL语句; 参数resultmode为可选常量,可以是MYSQLI_USE_RESULT与MYSQLI_STORE_RESULT中的任意一个。前者在需要检索大量数据时使用,后者一般情况下使用,为默认值。 该函数的返回结果分为两种情况,针对成功的 SELECT、SHOW、DESCRIBE 或 EXPLAIN 查询,将返回一个mysqli_result类的对象,如果查询执行不正确则返回FALSE; 针对其他成功的查询,则返回TRUE,如果失败,返回FALSE。非FALSE的返回值意味着查询是合法的,并能够被服务器执行。 例如,需要查询mydatabase数据库的数据表信息,可以使用如下的代码。 $link = new mysqli('localhost', 'root', '123456', 'mydatabase'); $query = 'show tables'; $result = $link->query($query); 3) 处理结果集 PHP查询语句执行成功以后,若返回的是mysqli_result结果集对象,则需要使用函数对结果集进行处理。例如,获取结果集中记录的总条数,获取一条或多条记录等。 例如,若需要获取上述2)代码结果集中的全部记录,并以数组的形式表示,可以使用下面的代码。 $data = $result->fetch_all(MYSQLI_ASSOC); 或者 $data = mysqli_fetch_all($result, MYSQLI_ASSOC); 若需要从结果集中获取一行,并以对象的形式表示,则代码为: $row = $result->fetch_object(); 或者 $row = mysqli_fetch_object($result); 在PHP中,处理结果集的方法还有很多,限于教材篇幅,这里只简单介绍这些,其他方法请参考相关的技术文档。 4) 使用准备语句查询 在PHP与MySQL的交互过程中,通常会重复执行一个查询,但每次使用的参数会有所不同。此时,若采用上述query()方法及传统的循环机制来实现操作,不仅系统开销大,而且编写代码也不方便。解决重复执行查询带来的问题,可以使用PHP对MySQL数据库准备(Prepared)语句的扩展支持。 MySQL数据库准备语句的基本思想是,可以向MySQL发送一个需要执行的查询模板,然后再单独发送数据。因此,可以向一个相同的准备语句发送大量的数据,大大提高了查询执行速度。这个特性对批处理的插入操作来说是非常方便的。 下面是使用准备语句实现多条数据插入,并进行数据查询的示例代码。 $link = new mysqli('localhost', 'root', '123456', 'demo'); $stmt = $link->stmt_init(); $query = 'insert into tb_user (username, password) values (?, ?)'; $stmt->prepare($query); $data = array( ['username'=>'aa','password'=>'11'], ['username'=>'bb','password'=>'22'], ['username'=>'cc','password'=>'33'] ); //插入数据 foreach ($data as $v){ $stmt->bind_param('ss', $v['username'], $v['password']); $stmt->execute(); } //查询数据 $query = 'select * from tb_user'; $stmt->prepare($query); $stmt->execute(); $stmt->bind_result($id, $username,$password); //输出查询数据 while ($stmt->fetch()) { printf('%s - %s - %s
',$id, $username,$password); } //释放资源 $stmt->close(); 关于准备语句应用的其他知识,请参考相关的技术文档。 2. 使用PDO扩展 PHP的PDO扩展,就是为PHP访问数据库定义的一个轻量级的一致接口。通过这个接口,PHP可以与各种不同的数据库进行交互。 打开PHP的配置文件php.ini,开启PDO扩展。 extension = php_pdo_mysql.dll 1) 创建PDO对象 使用PDO与不同数据库之间交互时,使用的操作函数都是相同的,都是PDO对象中的成员方法,所以在使用PDO与数据库交互之前,首先要创建一个PDO对象。 PDO类位于PDO.php文件中,与其相关的类还有PDOException、PDOStatement以及PDORow。 示例代码如下。 getMessage(); exit(); } ?> 这里创建了一个名为pdo的PDO对象,同时也创建了一个与MySQL数据库mydatabase的连接。 2) 执行查询 使用PDO对象的query()和exec()成员函数执行SQL查询。示例如下。 //数据插入 $statement = "insert into tb_user (username,password) values ('wp','888888')"; $pdo->exec($statement); //数据查询 $statement = 'select * from tb_user'; $result = $pdo->query($statement); 3) 获取数据 PDO的数据获取方法与前面介绍的mysqli数据库扩展中使用的方法非常相似,只是获取数据的函数都来自PDOStatement类的成员,如fetch()方法、fetchAll()方法等。 例如,对于上述2)中的select查询结果,可以通过下面的语句获取到全部数据。 //获取所有数据 $data = $result->fetchAll(); 4) 使用准备语句 PDO扩展中对数据库准备语句的支持,是通过PDOStatement类的对象来实现的。所以,首先必须创建PDOStatement类的对象,然后通过对象调用其成员方法,实现查询模板的导入、参数的绑定、查询的执行以及对结果集的处理等。 示例代码如下。 $statement = "insert into tb_user (username,password) values (?,?)"; $stmt = $pdo->prepare($statement); $data = array('wp','666666'); $result = $stmt->execute($data); … $statement = "insert into tb_user (username,password) values (:username, :password)"; $stmt = $pdo->prepare($statement); $stmt->bindParam(':username', $username); $stmt->bindParam(':password', $password); $username = 'wp'; $password = '888888'; $result = $stmt->execute(); 上述代码用两种方法,完成了单行数据的插入,注意它们数据绑定方式的区别。 视频讲解 3.4PHP扩展与应用 在PHP项目开发过程中,除了使用PHP的内置函数及类外,还经常使用由第三方开发的PHP扩展及应用。 3.4.1PEAR扩展库 PEAR(PHP Extension and Application Repository)是一个PHP扩展及应用的代码仓库,在PHP 4和PHP 5的应用项目开发中被广泛使用。 若要在项目开发中使用PEAR,需要先安装它。在Windows环境下,PHP默认情况是没有PEAR的,需要运行gopear.bat或gopear.phar文件进行安装。检查自己的PHP安装目录中是否存在上述文件,若不存在,到PEAR官网(https://pear.php.net/)下载,并将其存放在PHP的安装目录下。 安装了PEAR包以后,就可以在程序中使用包中的文件了。下面是使用PEAR DB包中的类,实现数据库查询的示例代码。 getMessage()); } //设置查询结果以关联数组形式表示 $dbCon->setFetchMode(DB_FETCHMODE_ASSOC); //执行查询 $sql = "select * from tb_user"; $result = $dbCon->query($sql); if (DB::isError($result)) { die ($result->getMessage()); } //输出查询结果 for($i=0;$i<$result->numRows();$i++) { $info = &$result->fetchRow(); echo "username:".$info['username'].' / '; echo "password:".$info['password']."
"; } //释放资源,断开连接 $result->free(); $dbCon->disconnect(); 3.4.2PDF扩展 在PHP中,有很多用于支持PDF文档的库,比如FPDF、TPDF、TCPDF等。这里使用较为流行且相对简单的FPDF库,该库是一个PHP的代码集,可以用包含的方式直接将其导入PHP代码文件中,不需要进行任何服务器端配置或支持。FPDF库的下载地址为http://www.fpdf.org。 下面是使用FPDF 1.81库进行PDF文档输出的示例代码。代码中的第1列为行号,是为了方便程序中语句的功能说明而设置的。 1AddPage(); 6$pdf->Image('images/fpdf_logo.jpg',5,5,30,10); 7$pdf->SetFont('helvetica','',10); 8$pdf->SetXY(160, 15); 9$pdf->Cell(50,20,'by Mashian, Weiwping'); 10$pdf->SetFont('courier','B',16); 11$pdf->SetXY(70, 10); 12$pdf->Cell(100,20,'FPDF Example 001'); 13$pdf->Line(5, 30, 200, 30); 14$pdf->SetFont('times','',12); 15$pdf->SetXY(10, 35); 16$content = <<Write(8, $content); 23$width = $pdf->GetPageWidth(); 24$height = $pdf->GetPageHeight(); 25$pdf->Line(5, $height-20, $width-10, $height-20); 26$pdf->Output(); 27?> 在上述代码中: 第2行,定义字体文件路径; 第3行,包含FPDF库文件; 第4行,创建一个PDF文档对象,该PDF文档为纵向页面方向、A4幅面,页面度量单位为mm; 第5行,在PDF文档中增加一个页面; 第6行,在页面中添加图像; 第7行,设置字体为helvetica体、普通字体、大小为10; 第8行,设置后续文本起始位置; 第9行,在页面中添加单元格,显示文本; 第10~12行,在页面中添加另一个单元格,显示文本; 第13行,绘制一条水平线; 第14~22行,添加文档正文到页面中; 第23~25行,为页面添加页脚分隔线,其中获取了文档页面尺寸; 第26行,将PDF文档输出到浏览器中。 使用第三方开发的库,是PHP项目开发中经常使用的方法。大家平时可以多收集一些优秀的资源,以提高项目打开的效率,提升项目性能及运行的稳定性。 3.5本 章 小 结 本章只是简单地总结了一下PHP程序设计语言的基本用法,更多详情请参见作者的另外一部教材《PHP Web程序设计与项目案例开发(微课版)》或其他的技术文档。