4--PHP基础
1.概述
PHP(Hypertext Preprocessor)超文本预处理器,是一种通用开源脚本语言。
一个PHP文件具有的特点:
- PHP 文件可包含文本、HTML、JavaScript代码和 PHP 代码
- PHP 代码在服务器上执行,结果以纯 HTML 形式返回给浏览器
- PHP 文件的默认文件扩展名是 “.php”
PHP的使用方法:
- PHP 可以创建、打开、读取、写入、关闭服务器上的文件
- PHP 可以添加、删除、修改数据库中的数据
- PHP 可以限制用户访问网站上的一些页面
- PHP 可以发送和接收 cookies
- PHP 可以生成动态页面内容
- PHP 可以收集表单数据
- PHP 可以加密数据
2.语法格式
PHP 脚本以 <?php 开始,以 ?> 结束
注释:
1 <?php 2 //单行注释 3 /* 4 多行注释 5 */
变量的命名:
- 变量以 $ 符号开始,后面跟着变量的名称
- 变量名必须以字母或者下划线字符开始
- 变量名只能包含字母、数字字符和下划线(A-z、0-9 和 _ )
- 变量名不能包含空格
1 //php的变量命名是以$开始的 2 $num = 3.14; 3 $str = "Hello";
static的关键字的使用:
- 当一个函数完成时,它的所有变量通常都会被删除
- 然而,有时候需要某个局部变量不要被删除
- 要做到这一点,就要在第一次声明变量时使用 static 关键字
1 function test(){ 2 static $n=0; 3 $n++; 4 echo "调用了一次".$n."\n"; 5 } 6 test();test();test();
常量:常量是一个简单值的标识符,该值在脚本中不能改变(在整个脚本中都能使用)
一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现 (常量名不需要加 $ 修饰符)
常量的命名:
- 设置常量,使用 define() 函数,函数语法如下:
- bool define ( string $name , mixed $value , [ bool $case_insensitive = false ] )
- 该函数有三个参数:
- name:必选参数,常量名称,即标志符
- value:必选参数,常量的值
- case_insensitive :可选参数,如果设置为 TRUE,该常量则不区分大小写,默认是区分大小写的
1 define("CL", "这是一个全局常量", true); 2 echo CL; // 默认为false区分大小写 3 echo cl; // 为true不区分大小写
3.数据类型
PHP一共支持8种原始类型:
- 4种标量类型:String(字符串), Integer(整型), Float(浮点型), Boolean(布尔型)
- 2种复合类型:Array(数组), Object(对象)
- 2种特殊类型:NULL(空值), resource(资源)
1 $a = "PHP基础";//字符串 2 $b = 1234;//整型 3 $c = -3.1415;//浮点型 4 $d = true;//布尔型 5 $e = array("A", "B", "C");//数组类型
预定义常量:PHP预定义了许多常量,这些常量无需使用define()函数定义,可直接在程序中使用。
- __ FILE __(FILE前后分别是两个下划线):当前正在处理的脚本文件名,若使用在一个被引用的文件中(include或require),那么它的值就是被引用的那个文件,而不是引用它的那个文件
- __ LINE __(LINE前后分别是两个下划线):正在处理的脚本文件的当前行数
- PHP_VERSION:当前PHP预处理器的版本,如8.1.13
- PHP_OS: PHP所在的操作系统的类型,如Linux
- TRUE:表示逻辑真。FALSE:表示逻辑假。NULL:表示没有值或值不确定
- DIRECTORY_SEPARATOR: 表示目录分隔符,UNIX或Linux操作系统环境时的值为“ / ”, Window操作系统环境时的值为 “ \ ”
字符串:字符串变量用于存储并处理文本。
1 $name = 'lxl'; 2 //双引号 里面有变量会输出变量的值 3 $str1 = "这是 $name ,这是PHP基础。"; 4 //单引号 里面有变量都作为字符串处理 5 $str2 = '这是 $name ,这是PHP基础。'; 6 echo $str1; 7 echo $str2;
字符串的操作函数:
- strpos — 查找字符串首次出现的位置(区分大小写)
- stripos — 查找字符串首次出现的位置(不区分大小写)
- strlen — 获取字符串长度
- substr — 返回字符串的子串
- md5 — 计算字符串的 MD5 散列值
- substr_replace — 替换字符串的子串
- strtolower — 将字符串转化为小写
- strtoupper — 将字符串转化为大写
1 $text1 = "hello"; 2 $text2 = "world"; 3 echo $text1 . " " . $text2; // "."是并置运算符(连接) 4 echo "返回字符串的长度:", strlen($text1); 5 echo "返回子串的第一次位置:", strpos($text2, "l");
4.运算符
基本运算符:
赋值运算符:
递增/递减运算符:
比较运算符:
逻辑运算符:
三元运算符:
1 (expr1) ? (expr2) : (expr3)
5.控制语句
5.1 条件控制语句
单向分支if:
1 <?php 2 if (expr) 3 {statement} 4 ?>
双向分支if...else:
1 <?php 2 if (expr) 3 {statement1} 4 else 5 {statement2} 6 ?>
多向分支if...elseif...else:
1 <?php 2 if (expr) 3 {statement1} 4 elseif (expr2) 5 {statement2} 6 else 7 {statement3} 8 ?>
多向分支switch:
1 <?php 2 switch ($i) { 3 case 0: 4 echo "i equals 0"; 5 break; 6 case 1: 7 echo "i equals 1"; 8 break; 9 case 2: 10 echo "i equals 2"; 11 break; 12 } 13 ?>
5.2 循环控制语句
while循环:
1 $d = 1; 2 while($d<=5){ 3 echo $d."<br>"; 4 $d++; 5 }
do-while循环:
1 $e = 6; 2 do{ 3 echo $e."<br>"; 4 $e++; 5 }while($e<=15);
for循环:
1 for($f=16;$f<=20;$f++){ 2 echo $f."<br>"; 3 }
foreach循环:
1 foreach (iterable_expression as $value) //第一种格式遍历给定的 iterable_expression 迭代器。每次循环中,当前单元的值被赋给 $value。 2 statement 3 foreach (iterable_expression as $key => $value) //第二种格式做同样的事,只除了当前单元的键名也会在每次循环中被赋给变量 $key。 4 statement
6.数组
数组是一个可以存储一组或一系列数值的变量。
在PHP中,数组中的元素分为两个部分,分别为键(Key)和值(Value)。
“键”为元素的识别名称,也称为数组下标,“值”为元素的内容。 “键”和“值”之间存在一种对应关系,称为映射。
根据下标的数据类型,可以将数组分为索引数组和关联数组两种类型。
索引数组:
- 索引数组是指下标为整数的数组
- 索引数组的下标从0开始,依次递增
- 当需要使用位置来标识数组元素时,可以使用索引数组
- 需要注意的是,索引数组的“键”可以自己指定,默认情况下,是从0开始的
关联数组:
- 关联数组是指下标为字符串的数组
- 通常情况下,关联数组元素的键和值之间有一定的业务逻辑关系
- 因此,当需要存储一系列具有逻辑关系的变量时,可以使用关联数组
6.1 数组的定义
使用赋值方式定义数组:$arrayName[key] = value
- “$arrayName”是数组名
- “key”是数组的下标,其类型可以是整型或字符串
- “value”可以是任意类型的数据
定义一个索引数组:
1 $arr[0] = 123; //整数 2 $arr[1] = "hello"; //字符串 3 $arr[2] = 4.56; //浮点数 4 $arr[3] = true; //布尔值 5 $arr[4] = null; //null
定义一个关联数组:
1 $arr["id"] = 1; 2 $arr["name"] = "lxl"; 3 $arr["address"] = "西安"; 4 $arr["email"] = "lxl@qq.com";
关联数组,数组元素的“键”都是字符串,并且“键”与“值”具有一一对应关系。
1 <?php 2 echo "<hr>"; 3 $stu=[ 4 "id"=>3456, 5 "name"=>"lxl", 6 "mobile"=>"1555555" 7 ]; 8 $stu["sex"]="男"; 9 print_r($stu); 10 ?>
使用array()函数定义数组:$arrayName = array( key1 => value1, key2 => value2, ...)
- 它接收数组的元素作为参数,多个元素之间使用英文逗号分隔
- 如果省略了key部分,则定义的数组默认为索引数组
定义一个索引数组:
1 $arr = array( 123, "hello", 4.56, true , null );
定义一个关联数组:
1 $arr = array( 2 "id"=> 1, 3 "name"=> "lxl", 4 "address"=> "西安", 5 "email"=> "lxl@tom.com" 6 );
6.2 数组的使用
获取数组:
由于数组中的键和值是映射关系,并且键是数组元素的唯一标识,所以可以根据元素的键来获取该元素的值。
具体语法格式如下: $数组名[键名]
除了可以使用方括号 “[]” 访问数组元素,还可以使用花括号 “{}” 。 例如,$arr[0]和$arr{0}的效果是一样的。
如果要查看整个数组的信息, 可以使用print_r()和var_dump()函数, 专门用于输出数组中的所有元素。
print_r()函数可以按照一定格式显示数组中所有元素的键和值。
var_dump()函数与print_r()函数的用法类似,但是var_dump()函数的功能更加强大,它可以在打印数组元素的同时打印元素中值的数据类型。
删除数组:
在实际开发中,有时需要删除数组中的某些元素。
在PHP中提供了unset()函数用于删除数组中的元素。
unset()函数不仅可以删除指定下标的元素还可以删除整个数组。
1 <?php 2 $a=[100,200,300,400,500]; 3 unset($a[2]); 4 var_dump($a); 5 ?>
遍历数组:
在操作数组时,经常需要依次访问数组中的每个元素,这种操作称为数组的遍历。
在PHP中,通常使用foreach语句实现数组的遍历, 其语法格式有两种,具体如下:
1 foreach ($arr as $value){//格式一 2 循环体 3 } 4 foreach ($arr as $key => $value){//格式二 5 循环体 6 }
以上两种语法格式都是通过foreach语句来实现对数组的遍历,不同的是,在格式一中,只是将当前元素的值赋给$value;而在格式二中,将当前元素的键名赋值给$key,值赋值给$value,这样可以同时获取当前元素的键名和值。
排序数组:
sort:对数组进行升序排序
1 <?php 2 $a=[66,64,90,88,76,100,94]; 3 sort($a); 4 print_r($a); 5 ?>
rsort:对数组进行降序排序
1 <?php 2 $a=[66,64,90,88,76,100,94]; 3 rsort($a); 4 print_r($a); 5 ?>
asort:对数组进行升序排序并保持索引关系
1 <?php 2 $a=["a"=>100,"b"=>50,"c"=>200,"d"=>190]; 3 asort($a); 4 print_r($a); 5 ?>
ksort:按照键名对数组进行升序排序
1 <?php 2 $a=["a"=>100,"b"=>50,"c"=>200,"d"=>190]; 3 ksort($a); 4 print_r($a); 5 ?>
arsort:对数组进行降序排序并保持索引关系
1 <?php 2 $a=["a"=>100,"b"=>50,"c"=>200,"d"=>190]; 3 arsort($a); 4 print_r($a); 5 ?>
krsort:按照键名对数组进行降序排序
1 <?php 2 $a=["a"=>100,"b"=>50,"c"=>200,"d"=>190]; 3 krsort($a); 4 print_r($a); 5 ?>
查找数组:array_search()
1 <?php 2 $score=[65,88,50,78,98,35]; 3 echo array_search("98",$score); 4 echo "<br>数组的长度是:".count($score); 5 ?>
6.3 数组的函数
is_array()函数:判断一个变量是否是数组,如果是数组,则返回true,否则返回false。
count()函数:用于计算数组中元素的个数。
array_unique()函数:移除数组中的重复元素。
array_search()函数:在数组中搜索给定的值,如果成功则返回相应的键名。
array_key_exists()函数:在给定的 key 存在于数组中时返回。
array_shift()函数:将 array 的第一个单元移出并作为结果返回,将 array 的长度减一并将所有其它单元向前移动一位。所有的数字键名将改为从零开始计数,文字键名将不变。
array_unshift() 函数:将传入的单元插入到 array 数组的开头,注意单元是作为整体被插入的,因此传入单元将保持同样的顺序。所有的数值键名将修改为从零开始重新计数,所有的文字键名保持不变。
array_unique()函数:接受 array 作为输入并返回没有重复值的新数组,注意键名保留不变。先将值作为字符串排序,然后对每个值只保留第一个遇到的键名,接着忽略所有后面的键名。这并不意味着在未排序的 array 中同一个值的第一个出现的键名会被保留。
in_array()函数: 检查数组中是否存在某个值 ,如果找到指定的值则返回 TRUE,否则返回 FALSE 。in_array()是区分大小写的。
7.函数
函数的构成部分:
- 关键字:function
- 函数名:与变量命名规则相同,以字母或下划线开头,其后跟上字母、下划线、数字
- 参数列表:($param1,$param2,……)
- 函数体:{ …… }
- 返回值:return $value
关于函数的返回值:
- return语句是可选的
- 函数不一定有返回值,如只显示相关信息的函数
- 或使用引用参数的方式来传递数据。值通过使用可选的返回语句返回,如果省略return,则默认返回值为null
- 返回值的类型包括数组和对象的任何类型
- 返回语句会立即中止函数的运行,并且将控制权交回调用函数的代码行
7.1 函数的定义与调用
函数的定义:
1 function getValue($a,$b) 2 { 3 return $a+$b; 4 }
函数的调用:
1 function getValue($a,$b) 2 { 3 return $a+$b; 4 } 5 6 $value = getValue(2,3); 7 echo $value; // 5
7.2 函数的参数
形参和实参:
- 函数定义时的参数是形式参数,名为$a或$a1意义相同,无差别
- 函数调用时使用的参数是实际要处理的数据,也称之为实参
1 //函数定义 2 function getValue($a,$b) //形参 3 { 4 return $a + $b ; 5 } 6 7 $a = 2 ; 8 $b = 3 ; 9 //函数调用 10 $value = getValue( $a , $b );//实参 11 echo $value; // 5
参数的默认值:
- PHP函数的参数在传递参数时,如果传入实参数量大于形参数量,多余的的将自动忽略
- 如果传入实参数量小于形参数量,PHP将报错。这种情况可以通过设置函数未传入参数默认值的方式来实现
1 //函数定义 2 function getValue($a,$b=1) //形参,设置第2个参数的默认值是2 3 { 4 return $a + $b ; 5 } 6 7 $a = 2 ; 9 //函数调用 10 $value = getValue( $a );//未传入第2个参数,$b将自动引入默认值 1 11 echo $value; // 5
注意:默认值只能是常量或常量表达式,设置默认值的1个或多个参数只能在最右侧,左侧的为未设置默认值的参数。
8.作用域
作用域:变量(常量)能够被访问的区域
变量可以在普通代码中定义,也可以在函数内部定义
8.1 全局变量
全局变量:就是用户普通定义的变量(函数外部定义)
所属全局空间:在PHP中只允许在全局空间使用(理论上函数内部不可使用)
脚本周期:直到脚本运行结束(最后一行代码执行完)
1 $global = "这是全局变量!"; //定义变量 2 3 function fun1(){ 4 5 $inner = __FILE__; //局部变量 6 7 echo $global; //函数内部访问不了全局变量 8 }; 9 fun1(); //调用函数
8.2 局部变量
局部变量:就是在函数内部定义的变量
所属当前函数空间:在PHP中只允许在当前函数内部使用
函数周期:函数执行结束(函数是在栈区中开辟独立内存空间运行)
1 $global = "这是全局变量!"; //定义变量 2 3 function fun2(){ 4 5 $inner = __FILE__; //局部变量 6 7 //echo $global; //函数内部访问不了全局变量 8 }; 9 fun2(); //调用函数 10 11 echo $inner; //访问局部变量,也是报错的
8.3 超全局变量
超全局变量:系统定义的变量(预定义变量:$_SERVER、$_POST等)
所属超全局空间:没有访问限制(函数内外都可以访问)
超全局变量会将全局变量自动纳入到$GLOBALS里面,而$GLOBALS没有作用域限制,所以能够帮助局部去访问
全局变量:但是必须使用数组方式
内部调用外部:
1 $global = "这是全局变量!"; //定义变量 2 3 function fun1(){ 4 5 $inner = __FILE__; //局部变量 6 7 echo $GLOBALS['global']; //将全局变量纳入$GLOBALS里面 8 }; 9 fun1();//调用函数
外部调用内部:
1 $global = "这是全局变量!"; //定义变量 2 3 function fun2(){ 4 5 global $inner; //定义变量,使用全局变量 6 7 $inner = __FILE__; //局部变量 8 }; 9 fun2(); echo $inner; //调用函数,并访问局部变量
8.4 静态变量
静态变量:就是在函数内部定义的变量,使用static关键字修饰,用来实现跨函数共享数据的变量
函数运行结束所有局部变量都会清空,如果重新运行一下函数,所有的局部变量又会重新初始化
基本语法:function 函数名 () {
//定义变量 Static $变量名 = 值; //通常会在定义的时候就直接赋值
}
1 function fun3(){ 2 3 $a = 2;//定义变量 4 5 static $b = 3;//定义静态变量 6 7 echo $a++;echo "<hr>"; 8 9 echo $b++;echo "<hr>"; 10 }; 11 fun3();//调用函数 12 13 fun3();//再调一次 14 15 fun3();//再调一次
9.类与对象
通过定义类可以描述对象:
- 将一系列特征相似的对象中的属性和方法抽象出来的一段特殊代码称为一个类
- 类使用class关键字来进行定义,后面跟上类的名称
面向对象的三大特征:
- 封装:是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体细节,这就是封装思想
- 继承性:主要描述的是类与类之间的关系,通过继承,可以无需重新编写原有类的情况下,对原有类的功能进行扩展
- 多态性:指的是同一操作作用于不同的对象,会产生不同的执行结果
类的概念:
描述:使用class关键字声明
语法:class 类名 {类成员}
注意:
- 类名可以是任何非 PHP 保留字的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线
- 一个类可以包含有属于自己的常量,变量(属性)以及函数(即方法)
1 class Person //类名 { 2 public $name; //这是一个成员变量 3 public function speak(){ 4 echo "我是一个好人" 5 }// 这是一个成员方法 6 }
完成类的定义后,创建对象
对象的概念:
描述:通过 new + 类名获取,并且类必须在实例化对象之前创建
语法: $变量 = new 类名 ()
说明:
- 对于创建对象的语句中,new后面的类名有没有小括号都可以
- 对象与对象之间的传值仍然是赋值传递,只不过传递的内容是一个内存地址
1 <?php 2 echo '<pre>'; 3 class Person { 4 public $pname='lxl'; 5 function showInfo(){ 6 echo 'my name is lxl'; 7 } 8 } 9 $name = new Person;//创建对象 10 print_r($name); 11 echo '<br>'; 12 $name->showInfo();//调用对象里的方法 13 echo '<br>'; 14 echo $name->pname;//调用并输出属性 15 ?>
类的封装:
所谓类的封装是指在定义一个类时,将类中的属性私有化,使用private关键字来修饰
私有化的属性只能在它所在类中被访问,为了能让外界访问私有属性,PHP提供了两种访问形式
- 通过getXxx(),setXxx方法访问私有属性
- 通过_get(),_set()方法访问私有属性
1 <?php 2 class Person { 3 private $name; // 将$name属性封装 4 private $age; 5 // 定义_get()方法用于获取Person的属性 6 public function _get($property_name){ 7 echo "自动调用_get()方法获取属性值<br>"; 8 if (isset($this->$property_name)) { 9 return($this->$property_name); 10 # code... 11 } 12 else{ 13 return(NULL); 14 } 15 } 16 // 定义一个_set()方法用于设置Person的属性 17 public function _set($property_name,$value){ 18 echo "自动调用一个_set()方法为属性赋值<br>"; 19 $this->$property_name=$value; 20 } 21 } 22 23 $p1 =new Person(); 24 $p1->name = "李华"; 25 echo "姓名:" .$p1->name."<br>"; 26 $p1->age = 20; 27 echo "姓名:" .$p1->age."<br>"; 28 29 ?>
对象一旦被创建,在对象的每个成员方法中都会存在一个特殊的对象引用“$this”,它代表当前对象,用于完成对象内部成员之间的访问
特殊的$this,用于完成:$this->属性名
构造方法:
修饰符 function _construct (参数列表) { // 初始化操作 }
构造方法名必须为 _construct () ,修饰符可以省略,默认为public
创建新对象后,系统就会自动调用该类的构造方法,不需要手动调用
1 class TestClass{ 2 function _construct(){ 3 echo 'hello'; 4 } 5 } 6 $obj = new TestClass();
析构方法:
是PHP5中新添加的内容,它在对象销毁之前就会被自动调用,用于释放内存
function _destruct () { // 清理操作 }
需要注意的是,析构方法的名称必须为 _destruct () ,且析构方法不带任何参数
类常量:
在类中,有些属性的值不能被改变,并且希望被所有对象共享
在定义时,需要用const关键字声明
1 <?php 2 class MathTool{ 3 const PI = 3.1415926; // 定义一个类常量 4 public function show(){ 5 echo MathTool::PI."<br>"; // 通过类名访问 6 } 7 public function display(){ 8 echo self::PI."<br>"; // 通过self关键字访问 9 } 10 } 11 echo MathTool::PI."<br>"; // 在类外部直接访问 12 $obj = new MathTool(); // 实例化一个对象 13 $obj ->show(); 14 $obj ->display(); 15 ?>
由于类常量PI是属于类本身而非对象的,因此需要使用范围解析操作符“ :: ”来访问
php中的“ :: ”是调用类中的静态方法或者常量、属性的符号,使用“ :: ”无需创建实例,可直接使用类名
- 需要注意的是,在类中定义常量只能是基本数据类型的值,而且必须是一个定值,不能是变量、类属性、数字运算的结果或函数
- 类常量一旦设置后就不能改变,如果试图在程序中改变他的值,则会出现错误,且在声明变量时一定要赋初始值,因为后期没有其他方式为其赋值
静态成员:
静态成员包括静态属性和静态方法
1 <?php 2 class Student{ 3 // 定义show 方法,输出学校名称 4 public static $SchoolName="传播"; // 静态方法 5 public function show (){ 6 echo "我的学校是:".self::$SchoolName."<br>"; 7 } 8 } 9 $stu1= new Student(); 10 $stu2= new Student(); 11 echo "学生1:<br>"; 12 $stu1->show(); 13 echo "学生2:<br>"; 14 $stu2->show(); 15 //Student::show(); 16 ?>
静态属性访问方法:类名::属性,如果在类的内部,可以使用self代替类名
- 在静态方法中,不要使用$this,因为静态方法是属于类的
- 在静态方法中,一般只对静态属性进行操作
继承:
在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系
在PHP中,类的继承是指一个现有类的基础上构建一个新的类,构建出来的新类被称作子类,现有类被称为父类,子类会自动拥有父类所有的可继承的属性和方法,在程序中,声明一个类继承另一个类,需要使用extends关键字
1 <?php 2 // 定义Animal类 3 class Animal{ 4 public $name; 5 public function shout(){ 6 echo "动物发出叫声<br>"; 7 } 8 } 9 // 定义Dog类继承Animal类 10 class Dog extends Animal{ 11 public function printName(){ 12 echo "name=".$this->name; 13 } 14 } 15 $dog=new Dog(); 16 $dog->name="沙皮狗"; 17 $dog->shout(); 18 $dog->printName(); 19 ?>
- 子类在继承父类的时候,会自动拥有父类的成员
- 子类默认继承了父类所有声明为public及protected的成员属性和方法,但是不能继承声明为private的成员属性和方法
- 子类中可以定义和父类同名的方法,此时子类中的方法会覆盖父类中的方法
- 在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类方法的重写
- 需要注意的是,在子类中重写的方法需要和父类中被重写的方法具有相同的方法名和参数
1 <?php 2 // 定义Animal类 3 class Animal{ 4 // 动物叫的方法 5 public function shout(){ 6 echo "动物发出叫声<br>"; 7 } 8 } 9 // 定义Dog类继承Animal类 10 class Dog extends Animal{ 11 // 定义狗叫的方法 12 public function shout(){ 13 echo '汪汪........'; 14 } 15 } 16 $dog=new Dog(); 17 $dog->shout(); 18 ?>
final关键字有“无法改变”或者最终的含义,因此被final修饰的类和成员方法不能被修改
抽象类:
抽象类和接口用于提高程序的灵活性,抽象类是一种特殊的类,而接口又是一种特殊的抽象类
定义抽象类需要使用abstract关键字来修饰
1 <?php 2 // 使用abstract关键字声明一个抽象类 3 abstract class Animal{ 4 // 在抽象类中声明抽象方法 5 abstract public function shout(); 6 } 7 // 定义Dog类继承自Animal类 8 class Dog extends Animal{ 9 // 实现抽象方法shout() 10 public function shout(){ 11 echo '汪汪........<br>'; 12 } 13 } 14 // 定义Cat类继承自Animal类 15 class Cat extends Animal{ 16 // 实现抽象方法shout() 17 public function shout(){ 18 echo '喵喵........<br>'; 19 } 20 } 21 $dog=new Dog(); 22 $dog->shout(); 23 $cat=new Cat(); 24 $cat->shout(); 25 ?>
- 抽象类不能被实例化
- 抽象类可以没有抽象方法,但有方法的重写类才有意义,一旦包含了抽象方法,则这个类必须声明为abstract
- 抽象类中可以有抽象方法、成员属性、常量,抽象方法不能有函数体,它只能存在于抽象类中
- 如果一个类继承了某个抽象类,则他必须实现该抽象类的所有抽象方法,除非它自己也声明为抽象类
接口:
如果一个抽象类中所有方法都是抽象的,则可以将这个类以另一种方式来定义,即接口,关键字为interface
- 定义一个接口与定义一个标准类类似,但其中定义的所有方法都是空的
- 需要注意的是接口中所有方法都是公用的,也不是使用final关键字来修饰
1 <?php 2 // 定义Animal接口 3 interface Animal{ 4 public function run(); 5 public function shout(); 6 } 7 // 定义Dog类,实现了Animal接口 8 class Dog implements Animal{ 9 public function run(){ 10 echo "狗在奔跑<br>"; 11 } 12 public function shout(){ 13 echo '汪汪........<br>'; 14 } 15 } 16 // 定义Cat类,实现了Animal接口 17 class Cat implements Animal{ 18 public function run(){ 19 echo "猫在奔跑<br>"; 20 } 21 public function shout(){ 22 echo '喵喵........<br>'; 23 } 24 } 25 $dog=new Dog(); 26 $dog->run(); 27 $dog->shout(); 28 $cat=new Cat(); 29 $cat->run(); 30 $cat->shout(); 31 ?>
多态:
例如,要实现一个动物叫的方法,由于每个动物的叫声是不同的,因此可以在方法中接收一个动物类型的对象参数
1 <?php 2 // 定义Animal接口 3 abstract class Animal{ 4 // 在抽象类中声明抽象方法 5 abstract public function shout(); 6 } 7 // 定义Dog类继承自Animal类 8 class Dog extends Animal{ 9 // 实现抽象方法shout() 10 public function shout(){ 11 echo '汪汪........<br>'; 12 } 13 } 14 // 定义Cat类继承自Animal类 15 class Cat extends Animal{ 16 // 实现抽象方法shout() 17 public function shout(){ 18 echo '喵喵........<br>'; 19 } 20 } 21 function AnimalShout($obj){ 22 // instanceof 用于确定一个PHP 变量是否属于某一类的class的实例 23 // 使用方法:子类son instanceof 父类father 24 if ($obj instanceof Animal) { 25 $obj->shout(); 26 }else{ 27 echo "Error: 对象错误!"; 28 } 29 } 30 $dog=new Dog(); 31 $cat=new Cat(); 32 AnimalShout($cat); 33 AnimalShout($dog); 34 ?>
10.include文件
在PHP中,有两种包含外部文件的方式:include和require
两者的区别主要在于,当包含的文件不存在或者发生错误时:
- require会报错,并且程序停止运行
- include会警告,并且程序继续执行
1 <?php 2 require 'out.php'; 3 echo 123;
程序报错不会输出123
1 <?php 2 include 'out.php'; 3 echo 123;
程序警告继续输出123
11.文件/目录处理
11.1 文件处理
打开/关闭文件:
php 打开/关闭文件使用 fopen()函数和 fclose()函数(注意不要误删文件)
1 resource fopen(string filename,string mode[,bool user_include_path]);
1 $fres=fopen('testFolder/test1.txt','r');//以指定模式打开文件 2 // 对文件进行操作 3 fclose($fres);//操作完成后关闭文件
读写文件:
从文件中读取数据:
fread()函数 按字符串长度读取文件
1 $fres=fopen('testFolder/test1.txt','r'); 2 $str=fread($fres,10); 3 echo $str;
fgets()函数 按行读取文件
1 // 打开文件资源 2 $fres=fopen('testFolder/test1.txt','r'); 3 while($str=fgets($fres)){ 4 echo $str; 5 } 6 fclose($fres);
file()函数 不需要调用 fopen 函数
1 $a=file('./testFolder/test1.txt'); 2 // 数组 每行的内容是数组的元素 3 var_dump($a);
file_get_contents()函数 不需要调用 fopen 函数
1 $a=file_get_contents('./testFolder/test1.txt'); 2 var_dump($a);
从文件中写入数据:
fwrite()函数
1 $resource=fopen('./testFolder/test1.txt','w'); 2 // 写入内容 3 $res=fwrite($resource,'php基础写入数据'); 4 var_dump($res); 5 fclose($resource);
file_put_contents()函数 覆盖写入
1 // 最常见的写入(覆盖写入) 2 $res=file_put_contents('./testFolder/test2.txt',date('y-m-d H:i:s')); 3 echo $res;
操作文件:
php 对文件本身也可以进行操作,例如复制、重命名、查看修改日期等
函数 | 说明 | 举例 |
php bool copy(string path1,string path2) | 将文件从 path1 复制到 path2,成功 true,失败 false | copy(‘test.txt’,‘./…/demo/new.txt’) |
php bool rename(string filename1,string filename2) | 把 filename1 重命名为 filename2 | rename(‘./1.txt’,‘./2.txt’) |
php bool unlink(string filename) | 删除文件,成功 true,失败 false | unlink(‘1.txt’) |
php is_file(string filename) | 判断是否为文件 | is_file(‘2.txt’) |
获取文件属性:
php 中提供了用来获取文件的一些常见属性的内置函数,例如文件的大小、类型、修改时间、访问时间以及权限等
11.2 目录处理
打开/关闭目录:
打开目录:
使用 opendir()函数打开目录
1 resource opendir(string path);
关闭目录:
使用 closedir()函数关闭目录
1 closedir(resource $res);
浏览目录:
使用 scandir()函数
1 $path='./../../文件夹1'; 2 $res=scandir($path); 3 echo json_encode($res);
使用 readdir()函数
1 $resource=opendir('./'); 2 while($res=readdir($resource)){ 3 echo $res.'<br>'; 4 }
操作目录:
函数 | 说明 | 举例 |
bool mkdir(string pathname) | 新建一个指定的目录 | mkdir(‘temp’); |
bool rmdir(string pathname) | 删除所指定的目录,该目录必须是空的 | rmdir(‘temp’); |
string getcwd() | 取得当前工作的目录 | |
bool rename(oldpath,newpath) | 修改目录 | |
fileatime(path) | 返回修改时间 | |
filectime(path) | 返回创建时间 | |
bool is_dir(path) | 判定path是否是目录 | |
bool is_file(path) | 判定path是否是文件 |
修改目录权限:
1 chmod($pathname,权限);
权限分别使用三个值:
11.3 文件上传
实现上传功能,要在 php.ini 文件里面去修改它的配置
- file_uploads:如果值为true,说明服务器支持上传,如果值为off,则不支持
- upload_tmp_dir:上传文件临时目录,文件被成功上传之前,文件先存放到临时目录中
- upload_max_filesize:服务器允许上传的文件的最大值,以MB为单位
- max_execution_time:php中一个指令所能执行的最长时间,以秒为单位
- memory_limit:php中一个指令所分配的内存空间,以MB为单位
预定义变量$_FILES:
$_FILES变量存储的是上传文件的相关信息,对于完成上传文件的功能提供一些参数信息
先在 html 页面完成表单元素的创建,使用元素提供上传文件的入口
文件上传函数:
move_uploaded_file(string filename,string destinationnpath) 函数上传文件存储到指定的位置
创建 upload.php 文件用来处理客户端上传过来的文件的信息,包括文件的存储
12.命名空间
概述:
命名空间是一种封装事物的方法,PHP 命名空间提供了一种将相关的类、函数和常量组合到一起,并与其他的同类隔离的途径。
在PHP中,命名空间用来解决用户在创建可重用的代码如类或函数或常量时,发生的用户代码与PHP内部的类/函数/常量或与第三方的类/函数/常量之间的命名冲突(重复)的问题;其次提供了为很长的标识符名称(通常是为了缓解命名冲突问题)创建一个别名的功能,以提高源代码的可读性。
12.1 定义
单个命名空间:
命名空间通过关键字 namespace 来声明,如果在一个文件中包含命名空间,那么在"<php?"标识符之前不得有任何内容(包括空格),而且必须在其它所有PHP代码之前声明命名空间,除了declare关键字以外
1 <?php 2 namespace MyName; 3 ?>
PHP 命名空间也允许指定层次化的命名空间的名称
1 <?php 2 namespace MyName\SubName; 3 ?>
全局空间
1 <?php 2 namespace { 3 //code goes here 4 } 5 ?>
虽然任意合法的PHP代码都可以包含在命名空间(同一个文件)中,但只有类(包括抽象类和traits)、接口、函数、常量元素会受命名空间的影响
其他代码语句如变量赋值、函数调用等,不管书写于哪个命名空间内,都作用于全局命名空间
多个命名空间:
在同一个文件中定义多个命名空间,有两种方法,但在实际编程中,不提倡在同一个文件中定义多个命名空间
第一种:顺序
1 <?php 2 namespace MyName1; 3 /* scope of MyName1 */ 4 5 namespace MyName2; 6 /* scope of MyName2 */ 7 ?>
第二种:大括号(在大括号之外不应有任何代码)
1 <?php 2 namespace MyName1{ 3 /* scope of MyName1 */ 4 } 5 6 namespace MyName2{ 7 /* scope of MyName2 */ 8 } 9 10 namespace { 11 /* scope of global namespace 12 全局命名空间 */ 13 } 14 15 namespace / { 16 /* Syntax ERROR */ 17 } 18 ?>
由此也可以引出命名空间作用域(scope)的概念,某个命名空间只在它的作用域以内有效。命名空间最大的作用域只基于一个文件之内
12.2 使用
一般:在PHP中,可通过三种方式引用命名空间:非限定名称、限定名称、绝对限定名称
- 如果以文件路径作类比的话,以上三者可分别对应:相对文件名,相对路径名,绝对路径名
- 另外,关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素,它等价于类中的 self 操作符
1 <?php 2 // file:/var/html/NS1.php 3 namespace MyName1\subName{ 4 const NUM=10; 5 } 6 7 namespace { //全局空间 8 const NUM=0; 9 } 10 ?> 11 12 <?php 13 // file:/var/html/NS2.php 14 namespace MyName1; 15 include("NS1.php"); //后续语句依然位于MyName1作用域内,不是MyName1\subName 16 const NUM=20; 17 18 echo NUM; //输出20,非限定名称引用,解析为\MyName1\NUM 19 echo subName\NUM; //输出10,限定名称引用,解析为\MyName1\SubName\NUM 20 echo \MyName1\SubName\NUM //输出10,绝对限定名称引用,解析为\MyName1\SubName\NUM 21 echo \NUM; //输出0,绝对限定名称引用,解析为\NUM 22 echo namespace\NUM; //输出20,namespace关键字引用,解析为\MyName1\NUM 23 ?>
别名/导入:允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征,类似于在类 unix 文件系统中创建的对其它的文件的符号连接
- 必须使用完全限定名称
- 前导的反斜杠是不必要的也是不推荐的,因为导入的名称必须是完全限定的,不会根据当前的命名空间作相对解析
- 另外,use 语句必须放在最外层
1 <?php 2 namespace NS2; 3 include('NS1.php'); //不会继承NS1.php中的use语句 4 const NUM=20; 5 //导入命名空间 6 use MyName\SubName as SubName; 7 use MyName\SubName; //和上一句作用一样 8 //导入一个全局类 9 use ArrayObject; 10 //导入一个函数(需要PHP 5.6+) 11 use function MyName\SubName\functionName; 12 use function MyName\SubName\functionName as fun; 13 //导入一个常量(需要PHP 5.6+) 14 use const MyName\SubName\CONSTANT; 15 16 echo NUM; //输出20,解析为\NS2\NUM 17 $obj=new SubName\myClass; //解析为\MyName\SubName\myClass 18 SubName\functionName(); //解析为\MyName\SubName\functionName() 19 $var=new ArrayObject; //解析为\ArrayObject 20 fun(); //解析为\MyName\SubName\functionName() 21 ?>
解析优先级:
对于命名空间中的类,如果使用非限定名称,那么解析后的类不存在时,会抛出异常错误
对于命名空间中的函数和常量,如果使用非限定名称,那么解析后的结果不存在时,会尝试使用全局空间中的同名元素,最后才抛出异常错误
动态语言特性:
- 必须使用完全限定名称,因为字符串中不会做相对解析
- 前导的反斜杠是非必要的
1 <?php 2 // file:/var/html/NS1.php 3 function fun1(){ //全局空间 4 echo __FUNCTION__; 5 } 6 ?> 7 8 <?php 9 // file:/var/html/NS2.php 10 namespace MyName; 11 include("NS1.php"); 12 function fun1(){ 13 echo __FUNCTION__; 14 } 15 16 $f='fun1'; 17 $f(); //输出 fun1 18 $f='\MyName\fun1'; 19 $f(); //输出 MyName\fun1 20 $f='MyName\fun1'; 21 $f(); //输出 MyName\fun1 22 ?>
13.正则表达式
语法(Perl风格):
模式规则:/php/ 字符串前后加上两条斜杠
匹配函数:preg_match(’/php/’,php) 参数1:匹配模式;参数2:字符串
元素:
- 正则表达式包含三种元素分别为:量词、元字符、修饰符
- 前导字符串:就是符号前面的一个字符或字符串
量词:
1 //preg_match()函数匹配成功返回1,失败返回0 2 echo preg_match('/a+/','abc');//返回1 3 echo preg_match('/a*/','abc');//返回1 4 echo preg_match('/a?/','abc');//返回1 5 echo preg_match('/./','abc');//返回1 6 echo preg_match('/a{2}/','aabc');//返回1 7 echo preg_match('/a{2,5}/','aaabc');//返回1 8 echo preg_match('/a{2,}/','aaaaabc');//返回1 9 echo preg_match('/^a/','bac');//返回0 10 echo preg_match('/^a/','abc');//返回1 11 echo preg_match('/a$/','abc');//返回0 12 echo preg_match('/a$/','cba');//返回1 13 echo preg_match('/a|b/','a');//返回1 14 echo preg_match('/a|b/','b');//返回1 15 echo preg_match('/(abc)+/','abcd');//返回1
元字符:
1 //preg_match()函数匹配成功返回1,失败返回0 2 echo preg_match('/[a-z]/','abc');//返回1 3 echo preg_match('/[A-Z]/','ABC');//返回1 4 echo preg_match('/[0-9]/','123');//返回1 5 echo preg_match('/[abc]/', 'a');//返回1 6 echo preg_match('/[^abc]/', 'd');//返回1 7 echo preg_match('/[a-zA-Z0-9_]/', 'aD45_');//返回1 8 echo preg_match('/\w/', 'aD45_');//返回1 9 echo preg_match('/\W/', 'aD45_');//返回0 10 echo preg_match('/\d/', '123456');//返回1 11 echo preg_match('/\D/', '123456');//返回0 12 echo preg_match('/\d/', '123456');//返回1 13 echo preg_match('/\s/', ' ');//返回1 14 echo preg_match('/\S/', ' ');//返回0 15 //单词尾部边界 16 echo preg_match('/at\b/', 'cat');//返回1 17 //头单词部边界 18 echo preg_match('/\bat/', 'attribute');//返回1 19 //没有到达边界 20 echo preg_match('/\Bat/', 'attribute');//返回0 21 //特殊字符 $ ^ * () + = {} [] | \\ : <> 22 echo preg_match('/\$/', '$');//返回1
修饰符:
1 //i 不区分大小写 2 echo preg_match('/abcd/','AbcD');//返回0 3 echo preg_match('/abcd/i','AbcD');//返回1 4 5 //m 多行识别 6 $str = '1a 7 1a'; 8 preg_match_all('/^1a/',$str,$arr); 9 print_r($arr); 10 //结果为Array ( [0] => Array ( [0] => 1a ) ) 11 //默认从头到尾匹配,所以只匹配到一个 12 13 preg_match_all('/^1a/m',$str,$arr);//返回1 14 print_r($arr); 15 //结果为Array ( [0] => Array ( [0] => 1a [1] => 1a ) ) 16 //每行都会使用规则,所以能匹配到二个,注意第二行前面不要有空格避免干扰 17 18 //x 忽略模式的空格 19 echo preg_match('/a b/','ab');//返回0 20 echo preg_match('/a b/x','ab');//返回1 21 22 //A 强制开头匹配 23 echo preg_match('/ab/','catabc');//返回1 24 echo preg_match('/ab/A','catabc');//返回0 25 echo preg_match('/ab/A','abcdef');//返回1 26 27 //U 禁止贪婪匹配 28 preg_match_all('/php\w+php/','php123phpphp456php',$arr); 29 print_r($arr); 30 //结果为Array ( [0] => Array ( [0] => php123phpphp456php ) ) 31 32 preg_match_all('/php\w+php/U','php123phpphp456php',$arr); 33 print_r($arr); 34 //结果为Array ( [0] => Array ( [0] => php123php [1] => php456php ) ) 35 //禁止贪婪匹配后,会就近匹配
Perl风格函数:
preg_grep():搜索数组中的所有元素,返回与某个模式匹配的字符串数组
preg_match():搜索模式,匹配返回true,不匹配返回false
preg_match_all():字符串匹配模式的所有出现,然后将所有匹配的全部放入数组
preg_quote():将特殊字符转义,特殊字符包含 $ ^ * () + = {} [] | \ : <>
定界正则,在每一个对于正则表达式语法而言有特殊含义的字符前插入一个反斜杠
preg_replace():替换模式的所有出现,然后替换成想要的字符串返回出来
preg_split():以不区分大小写将字符串划分不同的元素
1 //preg_grep() 2 $arr = array('php5','php6','php7','css','html'); 3 $out = preg_grep('/php[0-9]/', $arr); 4 print_r($out); 5 //结果为Array ( [0] => php5 [1] => php6 [2] => php7 ) 6 7 //preg_match() 8 echo preg_match('/php[0-9]/','php5');//返回1 9 10 //preg_match_all() 11 preg_match_all('/php[0-9]/','php5php6php7',$arr); 12 print_r($arr); 13 //结果为Array ( [0] => Array ( [0] => php5 [1] => php6 [2] => php7 ) ) 14 15 //preg_quote() 16 echo preg_quote(' $ ^ * () + = {} [] | \\ : <>'); 17 //结果为 \$ \^ \* \(\) \+ \= \{\} \[\] \| \\ \: \<\> 18 19 //preg_replace() 20 echo preg_replace('/php/','python', 'php1php2php3'); 21 //结果为 python1python2python3 22 23 //preg_split() 24 $str = preg_split('/a/', 'cbabc'); 25 print_r($str); 26 //结果为rray ( [0] => cb [1] => bc )
14.php与mysql
14.1 连接mysql服务器
1 mysqli_connect(host,username,password,dbname,port,socket);
参数:
- host:可选,规定主机名或IP地址
- username:可选,规定mysql用户名
- password:可选,规定mysql密码
- dbname:可选,规定默认使用的数据库
- port:可选,规定尝试连接到mysql服务器的端口号
- socket:可选,规定socket或要使用的已命名pipe
connID=@mysqli_connect($host,$username,$password)
@用来屏蔽数据库连接失败而显示的不友好的错误
1 <?php 2 $host = "localhost"; 3 $username = "root"; 4 $password = "root"; 5 // 创建连接 6 $con = new mysqli($host, $username, $password); 7 // 检测连接 8 if ($con->connect_error) { 9 die("Connection failed: " . $conn->connect_error); 10 }else{ 11 echo "Connected successfully"; 12 } 13 ?>
14.2 连接mysql数据库
1 mysql_select_db(mysqli link,string dbname)
参数:
- link:必选参数,应用mysqli_connect()函数成功建立mysql服务器后返回的连接标识
- dbname:必选参数,用户指定要选择的数据库名称
连接错误时的提示:
- mysqli_connect_errno(); //返回最后一次连接调用的错误代码
- mysqli_connect_error(); //返回一个字符串描述的最后一次连接调用的错误代码
1 if(mysqli_connect_errno()){ 2 exit(mysqli_connect_error()); 3 }
14.3 创建mysql数据库
建立名为mydb的数据库:
1 //生成sql语句,创建数据库mydb 2 $sql = " CREATE DATABASE mydb "; 3 //调用mysqli的query方法 4 if ($con->query($sql) == true){ 5 echo "创建成功"; 6 }else{ 7 echo "创建失败: " . mysqli_connect_error(); 8 } 9 //关闭连接 10 mysqli_close($con);
建立名为user的数据表:
1 $dbname = "mydb"; 2 // 创建连接,这里多的参数是数据库名称 3 $con =mysqli_connect("localhost","root","root", "mydb"); 4 // 检测连接 5 if (!$con) { 6 die("连接失败: " . mysqli_connect_error()); 7 }else{ 8 echo "连接成功"; 9 } 10 11 $sql = "CREATE TABLE user ( 12 id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 13 name VARCHAR(20) NOT NULL, 14 password VARCHAR(20) NOT NULL, 15 sex VARCHAR(20) NOT NULL, 16 email VARCHAR(50) NOT NULL 17 );"; 18 19 //调用mysqli的query方法 20 if ($con->query($sql) === true){ 21 echo "创建成功"; 22 }else{ 23 echo "创建失败: " . mysqli_connect_error(); 24 } 25 //关闭连接 26 mysqli_close($con);
插入数据:
1 // 生成sql语句,插入数据 2 $sql = "INSERT INTO user (id,name,password,sex,email) 3 VALUES ('01', 'lxl','123','男','test@example.com')"; 4 if (mysqli_query($con,$sql)) { 5 echo "插入成功"; 6 } else { 7 echo "插入失败: " .mysqli_connect_error(); 8 } 9 //关闭连接 10 mysqli_close($con);
数据的预处理:
插入数据时为了提高效率和防止注入使用预处理方式
1 INSERT INTO user 2 (id,name,password,sex,email) 3 VALUES 4 (?,?,?,?,?);
查询数据:
1 // 生成sql语句,查询数据 2 $sql = "SELECT * FROM user"; 3 $result = mysqli_query($con,$sql); 4 //输出数据 5 if($result->num_rows>0) { 6 while ($row = $result->fetch_assoc()) { 7 echo $row["name"] . "<br>"; 8 } 9 } 10 //关闭连接 11 mysqli_close($con);
更新数据:
1 //生成sql语句,更新数据 2 $sql = " UPDATE user SET name = 'lgd' "; 3 //调用mysqli的query方法 4 if ($con->query($sql) == true){ 5 echo "更新成功"; 6 }else{ 7 echo "更新失败: " . mysqli_connect_error(); 8 } 9 //关闭连接 10 mysqli_close($con);
删除数据:
1 //生成sql语句,删除数据 2 $sql = " DELETE FROM user WHERE id = 1 "; 3 //调用mysqli的query方法 4 if ($con->query($sql) == true){ 5 echo "删除成功"; 6 }else{ 7 echo "删除失败: " . mysqli_connect_error(); 8 } 9 //关闭连接 10 mysqli_close($con);
14.4 数据库函数
mysqli_real_escape_string():转义用于SQL语句中的特殊字符防止SQL语句出错
mysqli_fetch_row():以索引数组的方式获取一条记录的数据
mysqli_fetch_assoc():以关联数组的方式获取一条记录的数据
mysqli_fetch_array():以索引数组或关联数组的方式获取一条记录的数据
mysqli_fetch_all():以索引数组或关联数组的方式获取全部记录的数据
mysqli_nums_rows():取出结果中行的数量
mysqli_free_result():释放一个与结果集合相关的内存