PHP-待续...

PHP

1. 认识PHP

1.1 什么是PHP

  • PHP 是 “PHP Hypertext Preprocessor(超级文本预处理器)” 的首字母缩略词,动态网页编程语言
  • PHP文件可包含文本,HTML,JavaScript代码和PHP代码
  • PHP代码在服务器上执行,结果以纯HTML形式返回给浏览器
  • PHP文件的默认文件扩展名是“ .php”

1.2 PHP做什么

  • PHP可以生成动态页面内容
  • PHP可以创建,打开,读取,写入,关闭服务器上的文件
  • PHP可以收集表单数据
  • PHP可以发送和接收cookie
  • PHP可以添加,删除,修改您的数据库中的数据
  • PHP可以限制用户访问您的网站上的一些页面
  • PHP可以加密数据

通过PHP,您可以不再输出HTML。您可以输出图像,PDF文件,甚至Flash电影。您还可以输出任意的文本,例如XHTML和XML

1.3 为什么使用PHP

  • PHP可在不同的平台上运行(Windows,Linux,Unix,Mac OS X等)
  • PHP与当前几乎所有的正在被使用的服务器相兼容(Apache,IIS等)
  • PHP提供了广泛的数据库支持
  • PHP是免费的,可从官方的PHP资源下载它: www.php.net
  • PHP易于学习,尽可能高效地运行在服务器端

1.4 架构

  • bs架构: 基于浏览器的,无需安装与升级,性能低安全低
  • cs架构: 需要下载不同的安装包,更新不方便,安全,性能高

总结: 不管是bs架构或者cs架构都会有一个客户端和服务端

1.4 模拟服务器

wampServer这个集成了Apache,mysql,php等服务,先现在然后传统安装,安装完成进入文件bin目录,就可以看见apache,mysql,php三个目录进入Apache目录,然后在进去,找到conf目录,在这个目录下有文件httpd.conf,打开

httpd.conf文件中第178行有: DocumentRoot "D:/SQLUI/wamp/www/",把这里面的路径修改自己代码示例的路径,还有205行<Directory "D:/SQLUI/wamp/www/">这里面的路径保持一样,保存然后重启服务,浏览器中输入127.0.0.1,如果目录中的文件有index开始的文件,就会启动index,如果没有就会展示目录

在浏览器中输入: localhost会展示出You don't have permission to access / on this server也是要在上面的配置文件中的234行Allow from 127.0.0.1下添加Allow from all显示的就会和127.0.0.1显示的页面一样

如果想要展示多个文件,就把httpd.conf的文件注释打开,在468行,然后去当前文件夹的extra文件中的httpd-vhosts.conf这个文件,并且把localhost的文件改成要屏蔽网站的域名

<VirtualHost *:80>
    DocumentRoot "E://./././" //这里的目录一定要和前面的`httpd-vhosts.conf`修改后的路径保持一致
    ServerName jd.com
    ServerAlias www.jd.com
</VirtualHost>

解析: http://www.jd.com/文件,首先解析的是C盘文件的host文件, 使用文件中的127.0.0.1 jd.com实际上找的是127.0.0.1实际上找本机,然而是访问apache修改的的根目录下的文件,如果根目录下的文件httpd.conf下的468行未打开,那么就直接访问修改目录,如果打开就进入当前文件(extra)下的httpd-vhosts.conf文件下,但是httpd-vhosts.conf里面的DocumentRoot这个路径必须和httpd.conf要修改的路径必须一致,访问的就是这里的链接

1.5 资源

客户端去请求服务器,实际上请求的是服务器上面的资源,资源就是一些文件

  • 资源分为两种类型资源
    • 静态资源: 可以直接被浏览器解析的html,css,js,img,video
    • 动态资源: php,jsp,asp

客户端请求服务器,实际上请求的是服务器上面的资源,资源就是一些文件
服务器就会根据我访问的地址进行查找
如果找到的是静态资源就直接响应给浏览器客户端
如果找到的是动态资源,就会在服务器把动态资源转换为静态资源,响应给客户端浏览器

静态资源是客户端浏览器运行的
动态资源是服务器解析运行的

1.6 get与post请求区别

1: get 发送的数据都在地址栏当中,不安全
2:get 发送的数据对数据大小由限制。
3:get 没有请求体
4:post 发送的数据在请求体当中,相对安全
5:post 对请求的数据的大小没有限制
6:post 有一个特殊的请求头 Content-Type:application/x-www-form-urlencoded
7: get 的请求头相对较少,性能稍微要高一些.

2. 基本数据类型

2.1 编写位置

PHP脚本可以放在文档中的任何位置

  • PHP脚本以 <?php开始, 以?>结束

2.2 注释

  • # 单行注释
  • // 单行注释
  • /* */ 多行注释

2.3 输出

  • echo - 输出简单数据类型
    • echo 是一个语言结构,使用的时候可以不用加括号,也可以加上括号: echo 或 echo()。
  • print - 只能输出一个字符串,并始终返回 1
    • print 同样是一个语言结构,可以使用括号,也可以不使用括号: print 或 print()。
  • print_r() - 输出复杂数据类型
  • var_dump() - 输出详细信息,如数组,对象
    • var_dump() 是一个函数。向括号()中间插入变量。这个函数会打印出来数据类型,还会对应显示变量的长度和值。

注意echo比print稍微快一点,因为不返回任何东西

<?php
	// 此处文件默认是PHP代码
	/* 
		多行注释
	*/
	# 单行注释
    // 添加响应头告诉浏览器以"utf-8"的格式解析
    header("content-type:text/html;charset=utf-8");
	echo "Hello World";  // 网页输出Hello World
?>

2.4 变量

变量是存储信息的容器

PHP 变量规则:

  • 变量以 $ 符号开头,其后是变量的名称
  • 变量名称必须以字母或下划线开头
  • 变量名称不能以数字开头
  • 变量名称只能包含字母数字字符和下划线(A-z、0-9 以及 _)
  • 变量名称对大小写敏感($y 与 $Y 是两个不同的变量)

**注释:**PHP 变量名称对大小写敏感!

PHP 没有创建变量的命令。变量会在首次为其赋值时被创建

<?php
	$a = 2;
	$b = 5;
	$c = $a + $b;
	echo $c; // 7

2.5 变量作用域

PHP有四种不同的作用域: local, global, static, parameter

局部和全局作用域局部和全局作用域(loacal global)

在所有函数外部定义的变量,拥有全局作用域。除了函数外,全局变量可以被脚本中的任何部分访问,要在一个函数中访问一个全局变量,需要使用 global 关键字。

<?php
	header("Content-type:text/html;charset=utf-8");
	$a = 5; // 全局作用域
	function myTest() {
        // global $a; // 添加这一句,里层可以访问外层变量a
		$b = 10;
		if(true) {
			// echo "<p>函数内部的if上层输出c的值: $c</p>"; // 报错: 未定义
			echo "<p>函数内部的if上层输出b的值: $b</p>"; // 输出: 10
			// echo "<p>函数内部的if上层输出a的值: $a</p>"; // 报错: 未定义
			$c = 20;
			echo "<p>函数内部的if中输出c的值: $c</p>"; // 输出: 20
			echo "<p>函数内部的if中输出b的值: $b</p>"; // 输出: 10
			// echo "<p>函数内部的if中输出a的值: $a</p>";  // 报错: 未定义
		}
		echo "<p>函数内部的if上层输出c的值: $c</p>"; // 输出: 20
		echo "<p>函数内部的if上层输出b的值: $b</p>"; // 输出: 10
		// echo "<p>函数内部的if上层输出a的值: $a</p>"; // 报错: 未定义
         echo "<p>函数内部的if上层输出a的值: {$GLOBALS['a']}</p>";
		echo $GLOBALS['a'];
	}
	myTest();
	// echo "<p>函数外部输出c的值: $c</p>"; // 报错
	// echo "<p>函数外部输出b的值: $b</p>"; // 报错
	echo "<p>函数外部输出a的值: $a</p>"; // 输出5
?>

由上面可知

  • 函数中的变量不存在变量提升
  • 作用域嵌套,外层和内层不能相互访问
  • 作用域不是块级作用域,是函数作用域
  • 如果内层想要访问外层,必须在内层的函数下面声明global $a

a 也 可 以 写 成 a 也可以写成 aGLOBALS[‘a’]

PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中。 index 保存变量的名称。这个数组可以在函数内部访问,也可以直接用来更新全局变量。

Static作用域: 当一个函数完成时,它的所有变量都会被删除。有时不希望某个局部变量不要被删除。那就在变量前加上static , 然后,每次调用该函数时,该变量将会保留着函数前一次被调用时的值。

<?php
	function myTest() {
		$x = 0; // static  $x = 0;
		echo $x;
		$x++;
	}
	myTest(); 
	myTest(); 
	myTest(); 
	// 没有加static输出: 000
	// 加上static输出: 012
?>

参数作用域: 参数是通过将值传递给函数的局部变量。参数是在参数列表中声明的,作为函数声明的一部分

<?php
function myTest($x){
    echo $x;
}
myTest(name);
?>

2.6 数据类型

整数、浮点数、字符串、布尔、数组、对象、NULL、resource(资源)

  • gettype() : 参数1: 传入一个变量,能够获得变量类型
  • var_dump(): 参数1: 传入一个变量,输出变类型和值 (最常用)
<?php
	$a = 'b';
	$b = 15;
	$c = true;
	echo gettype($a); // string
	echo gettype($b); // integer
	echo gettype($c); // boolean
	echo '<hr />';
	echo var_dump($a); // string 'b' (length=1)
	echo var_dump($b); // int 15
	echo var_dump($c); //boolean true
?>

2.7 整形

	$a = 123; // 整形(十进制)
	$b = -123; // 负数
	$c = 012; // 8进制
	$d = 0xff; // 16进制
	echo var_dump($a); // int  123
	echo var_dump($b); // int -123
	echo var_dump($c); // int 10
	echo var_dump($d); // int 255

2.8 字符串

在PHP语言中声明字符串有三种方式:

  1. 用单引号声明

  2. 用双引号声明

  3. 用字界符声明(需要输入非常大段的字符串时使用)

<?php
	header("Content-type: text/html;charset=utf-8");
// <<<开始然后跟大写英文标记,然后回车输入信息,以大写因为标记结束,结束必须在一行的开始,前面不能有空格
	$a = <<<ABC
		<h1>how are you</h1>
		我在
			这  里
		啊!!!
ABC;
	echo $a;
?>

双引号与单引号有什么区别(面试题)

1.双引号解析变量,但是单引号不解析变量。

2.在双引号里面插入变量,变量后面如果有英文或中文字符,它会把这个字符和变量拼接起来,视为一整个变量。一定要在变量后面接上特殊字符,例如空格,感叹号等分开。

3.如果在双引号里面插变量的时候,后面不想有空格,可以拿大括号将变量包起来。

4.双引号解析转义字符,单引号不解析转义字符。但,单引号能解析’ 和\

5.单引号效率高于双引号,尽可能使用单引号

6.双号和单引号可以互插!!!双引号当中插入单引号,单引号当中插入变量,这个变量会被解析。

7.神奇的字符串拼接胶水——(.)点,用来拼接字符串。

8.我们将定界符声明字符串视为双引号一样的功能来看待。

<?php
	header("content-type: text/html;charset=utf-8");
	// 1. 双引号解析变量,单引号不解析变量
	$name = "张三";
	// 2. 如果变量后面不加空格,那么默认把整体字符串当成变量,缺陷变量名后面有空格
	echo "$name 在吃葡萄"; // 张三 在吃葡萄 双引号解析变量成功
	echo '$name 在吃葡萄'; // $name 再吃葡萄 单引号解析失败
	// 3. 用大括号解决空格
	echo "{$name}在吃葡萄"; // 张三再吃葡萄
	// 4. 解析转义字符
	echo "制\t表符"; // 制 表符   双引号解析转义字符成功
	echo '制\t表符'; // 制\t表符  双引号解析转义字符失败
	// 5. 相互嵌套
	echo "'$name'在吃葡萄"; // '张三'在吃葡萄  ,外双内单解析变量
	echo '"$name"在吃葡萄'; // "$name"在吃葡萄
	// 6. '.'拼接字符串
	echo $name."在吃葡萄"; // 张三在吃葡萄
?>

2.9 浮点型

echo和print分别输出浮点类型

	$a = 123.4567891234;
	print $a; // 123.4567891234
	echo '<br />';
	echo $a; // 123.4567891234
	echo '<br />';
	var_dump($a); // float 123.4567891234

2.10 布尔型

boolean : false / true

<?php
	$a = true;
	print $a; // 1
	echo $a; // 1
	var_dump($a); // boolean true
?>

2.11 数组(Array)

数组就是在一个变量中存储多个值

	$a = array("green","red","blue");
	var_dump($a);
	/*
		array
		  0 => string 'green' (length=5)
		  1 => string 'red' (length=3)
		  2 => string 'blue' (length=4)
	*/
	echo $a; // Array
	echo $a[0]; // green
	var_dump(Array(1));
	/*
		array
		0 => int 1
	*/

2.12 对象(Object)

对象是存储数据和有关如何处理数据的信息的数据类型。

在 PHP 中,必须明确地声明对象。首先我们必须声明对象的类。对此,我们使用 class 关键词。类是包含属性和方法的结构。然后我们在对象类中定义数据类型,然后在该类的实例中使用此数据类型:

<?php
	class Car {
		var $a;
		function f($a = 'red') {
			$this->color = $color;
		}
		function fn(){
			return $this->color;
		}
	};
$obj = new Car();
?>

2.13 NULL(空值)

空在英文里面表示是null,它是代表没有。空(null)不是false,不是0,也不是空格。

主要有以下三空情况会产生空(null)类型:

  1. 通过变量赋值明确指定为变量的值为NULL

  2. 一个变量没有给任何值

  3. 使用函数unset()将变量销毁掉

  • **empty()**可以向括号中间传入一个变量。这个变量的值如果为false或者为null的话,返回true。
  • **isset()**可以向括号中间传入一个或者多个变量,变量与变量间用逗号分开。只要有有一个变量为null,则返回false。否则,则返回true。
  • **unset()**这个函数的功能是毁掉变量。unset(变量)括号中间插入想要毁掉的变量名,这个变量就会被毁掉。
<?php
	$a = null;
	echo $a; 
	echo '<hr/>';
	var_dump($a); // 这两个只会下面一个输出null,但是把下面的代码去掉,上面也会输出null
	echo '<hr/>';
	var_dump($b);// $b是一个不存在的变量,会警告输出null
	$iphone = '乔布斯';
	// unset销毁一个变量
	unset($iphone);
	var_dump($iphone); // 警告输出: null
?>

2.14 资源类型

资源类型打印出来只能够看到一个英文的resource, 资源类型就是文件,电影,电视,音乐,数据库等文件

2.15 判断数据类型

我们使用is_* 系列函数。 is_types这一系列的函数,来进行判断某个东西是不是某个类型。如果是这个类型返回真,不是这个类型返回假。

  • is_int() 是否为整型
  • is_bool() 是否为布尔
  • is_float() 是否是浮点
  • is_string() 是否是字符串
  • is_array() 是否是数组
  • is_object() 是否是对象
  • is_null() 是否为空
  • is_resource() 是否为资源
  • is_scalar() 是否为标量,标量: 布尔值,整数浮点数,字符串
  • is_numeric() 是否为数值类型
  • is_callable() 是否为函数

注:is_types 很好记。is_ 在前后面跟类型即可。

变量:整型(int) 浮点(float)、布尔(bool)、字符串(string)

混合类型: 数组(array)、对象(object)

特殊类型:空(null)、 资源(resouce)、回调(callback)

2.16 自动类型转换(PHP7)

自动类型转换,就是数据类型在某些情况下,自动会变为其他的类型参与运算。自动类型转换的发生时机是:运算和判断的时候某些值会自动进行转换。

下面的情况是布尔值判断时的自动类型转换

1,整型的0为假,其他整型值全为真

2, 浮点的0.0,布尔值的假。小数点前为0,小数点后只要有一个非零的数值即为真。"0.0"转为字符串0.0返回true

3,空字符串为假,只要里面有一个空格都算真。

4,字符串的0,也将其看作是假。其他的都为真

5,空数组也将其视为假,只要里面有一个值,就为真。

6,空也为假

7, 未声明成功的资源也为假

8, null也会转为假

<?php
//布尔变整型参与运算
$fo = true;
$result = $fo + 10;
//$result 结果为整型的11,因为$fo布尔的true变为了1
//如果$fo的值为0
var_dump($result);
//字符串类型,字符串前面是字符串和数字相加=数字本身,字符串变为0,两个字符串相加都会转为0
$str = '419不要爱';
$result = $str + 1;
//结果为420。因为将$str变为了整型的419参与运算
//将419放在字符串中间和结尾试试
var_dump($result);
?>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzKfRfkL-1586340423656)(C:\Users\a4244\Desktop\img\27.png)]

2.17 强制类型转换(PHP7)

强制类型转换有三种方式:

1.用后面的三个函数可以完成类型转换,intval()、floatval()、strval()

2.变量前加上()里面写上类型,将它转换后赋值给其他变量

3.settype(变量,类型) 直接改变量本身

强制类型转换三种方法

  • (int)$* 、(float)$*、(array)$*,$*、(string)$*、(object)$
  • intval()、floatval()、strval()
  • settype(变量,‘类型’) 会更改原来的数据类型
<?php
	header("Content-type: text/html;charset=utf-8");
	$a = 1.123;
	$b = true;
	$c = "123.45abc";
	$d = "abc123.456abc";
	var_dump(intval($a)); // int 1
	var_dump(intval($b)); // int 1
	var_dump(intval($c)); // int 123
	var_dump(intval($d)); // int 0
	var_dump((int)$a); // int 1
	
	var_dump(floatval($a)); // float 1.123
	var_dump(floatval($b)); // float 1
	var_dump(floatval($c)); // float 123.45
	var_dump(floatval($d)); // float 0
	var_dump((float)$c); // float 123.45
	
	var_dump(strval($a)); // string '1.123' (length=5)
	var_dump(strval($b)); // string '1' (length=1)
	var_dump(strval($c)); //string '123.45abc' (length=9)
	var_dump(strval($d)); // string 'abc123.456abc' (length=13)
	var_dump((string)$d); // string 'abc123.456abc' (length=13)
	
	var_dump((array)$a,$c);
	/*
		array
			0 => float 1.123
			string '123.45abc' (length=9)
	*/
	settype($a,'int');
	var_dump($a); // int 1
?>

以下是强制类型转换时的特点,

1.空转为整型会为整型的0

2.空转为浮点会为浮点的0

3.空转为字符串会为空字符串‘’

4.浮点的123.0转为字符串会为字符串123

5.浮点的123.2转为字符串会为字符串的123.2

6.浮点即使小数点再大,它都会被干掉,会舍掉小数点后面的值

7.如果字符串转为整型的时候,如果数值在前面,会将前面的数值拿出来做为整型的转换值。

8.settype(变量,‘null’); 等价于 unset()一个变量,毁掉变量

9.$目标变量 = (类型)$操作变量 只会改变目标变量的类型,不会改变原变量的类型,Settype是改变原值

2.18 常量define

define(常量名,常量值)

<?php
define('MY_NAME','PHP');
echo MY_NAME; // PHP
echo "我的名字是 'MY_NAME'"; // 我的名字是 'MY_NAME'
echo "我的名字是{MY_NAME}"; // 我的名字是{MY_NAME}
echo "我的名字是 MY_NAME"; // 我的名字是 MY_NAME
echo '我的名字是'.MY_NAME; // 我的名字是PHP
// 也可以这样
$res = constant("MY_NAME");
echo $res;
?>

define和const的区别:

  1. const是一个语言结构;而define是一个函数,可以通过第三个参数来指定是否区分大小写。true表示大小写不敏感,默认为false, 例子:define(‘PI’, 3.14, true);
  2. const简单易读,编译时要比define快很多。
  3. const可在类中使用,用于类成员常量定义,定义后不可修改;define不能在类中使用,可用于全局变量
  4. const是在编译时定义,因此必须处于最顶端的作用区域,不能在函数,循环及if条件中定义;而define是函数,也就是能调用函数的地方都可以定义
  5. const只能用普通的常量名,define常量名中可以有表达式
  6. const定义的常量只能是静态常量,define可以是任意表达式
  7. 此外,系统还为我们准备了一些内置的常量。这些常量都是规定好的

常量与变量的区别:

  1. $ :常量前面没有($)
  2. define: 常量只能用define()函数定义,而不能通过赋值语句
  3. 作用域: 常量可以不用理会变量的作用域而在任何地方定义和访问
  4. 重定义: 常量一旦定义就不能被重新定义或者取消定义
  5. 标量类型:常量的值只能是标量
  6. 命名空间:常量和(全局)变量在不同的名字空间中
常量名说明
_ LINE_当前所在的行
_ FILE_当前文件在服务器的路径
_ FUNCTIOIN_当前函数名
_ CLASS_当前类名
METHOD当前成员方法名
PHP_OSPHP运行的操作系统
PHP_VERSION当前PHP的版本
TRAITTrait 的名字,php5.4新加
DIR文件所在的目录
NAMESPACE当前命名空间的名称(区分大小写)
M_PI圆周率常值
FALSEfalse
TRUEtrue
M_E科学计数e
M_LOG2E代表log2
E_ERROR最近的错误处
E_WARNING最近的警告处
E_PARSE剖析语法存在问题之处
–METHOD –类方法名,比如B::test

2.19 defined函数来做安全机制

defined(): 主是是为了防止其他人绕过安全检查文件。

函数:defined(常量)
功能:向函数的括号后面传入常量,如果常量定义了就返回true,否则返回false

【情景模拟】假设,我们的这套在线电子商城的软件需要付钱,检查是否付费是通过对软件授权检查来完成的,而文件version.php中就有检查授权的功能,我们在软件中规定,没有授权检查文件version.php就不能使用这个软件。所有的代码都包含了version.php。并且为了防止有人盗版,我还可以把version.php的代码进行了加密。

我们有两个文件:

1.一个文件中间有版本号,版本声明和授权声明。文件名为version.php

2.一个文件中有具体的业务功能。例如:用户注册、登陆等,文件名为users.php

我们该怎么做呢?——也就是说不包含 version.php文件就不让,执行users.php之后的代码。

函数:include(‘传入文件路径和文件名’)
功能:这个函数的功能是传入指定路径的文件,让PHP包含进来执行
注意:在后面的章节中会专门讲解和实验include

我们来进行实验:version.php文件

<?php

//此处是检查是否是否授权的业务部份代码xxxx
define('AUTH',true);
//略过模拟代码xxx行

?>

users.php

<?php
//尝试将include 'version.php'这一行代码注释后再执行看看,对比结果
include 'version.php';

if(!defined('AUTH')){
   echo '非法!非法!你尝试跳过授权文件';
   exit;
}
//模拟后面用户注册和用户登陆的代码xxx行
echo '用户注册';
?>

实验结果可知:version.php必须要包含 ,不然不会显示后面的echo ‘用户注册’;

2.20 可变变量

可变变量其实就是——已声明的变量前,再上变量符。

<?php
	header("Content-type: text/html;charset=utf-8");
	$a = 'biao';
	$biao = "鼠标";
	echo $$a;  // 鼠标
?>

上面的过程说明: s h u 的 值 为 字 符 串 的 ′ b i a o ′ 。 我 在 shu的值为字符串的'biao'。我在 shubiaoshu前再加上一个$(美元符号),可以理解成为以下的变形过程:

$$shu
${$shu} 分成两块来看
${‘biao’} 把变量$shu解释成了biao
$biao 而$biao也是一个变量对应的值是:鼠标

2.21 外部变量

PHP的外部变量是PHP 在使用过程中规定好的一些变量。这个变量的规定是这样规定的,就这样使用

<!--Demo18.html-->
<!doctype html>
<html lang = "zh-cn">
	<head>
		<title></title>
	</head>
	<body>
		<!--<form action="http://localhost/Demo18.php" method="get">-->
		<form action="http://localhost/Demo18.php" method="post">
			<label>
			用户名: 
				<input type="text" name="uname">
			</label>
			<br />
			<label>密码: 
				<input type="password" name = "pass">
			</label>
			<input type="submit" value="提交">
		</form>
	</body>
</html>

在这段代码的主要意思是把用户和密码,采用get方法,将数据发送给Demo18.php。reg.php想办法接收用户传过来的uname和pass这两个值。

我们得出我们的第一个外部变量:$_GET。$_GET 的主要作用是将得到get传值的数据。

// Demo18.php
<?php
	header("content-type:text/html;charset=utf-8");
/*
	// get请求
	echo $_GET['uname'].'<br />';
	echo $_GET['pass'].'<br />';
*/
/*	
	// post请求
	echo $_POST['uname'].'<br />';
	echo $_POST['pass'].'<br />';
*/
/*
	// request请求,网页get请求
	echo $_REQUEST['uname'].'<br />';
	echo $_REQUEST['pass'].'<br />';
*/
	// request请求,网页POST请求
	echo $_REQUEST['uname'].'<br />';
	echo $_REQUEST['pass'].'<br />';
?>

链接地址: http://localhost/Demo18.php?uname=张三123&pass=1234567

从地址栏可以表单的用户名输入的是张三123,密码是:1234567中间&符号隔开,密码可见,伪类保证安全密码要用POST请求,这样密码就不可见

用了post的请求地址栏: http://localhost/Demo18.php,问好,用户名,密码等信息没有了

$REQUEST来接受数据

  • 网页get请求数据,地址栏: http://localhost/Demo18.php?uname=张三123&pass=1234567
  • 网页post请求数据,地址栏: http://localhost/Demo18.php

通过上面的实验你会发现$_REQUEST即可以接收get传值也可以接收post传值。

另外,我们总结一些外部变量,要求知识点的学习级别:了解含义,默写这个单词的写法和作用。

全局变量名功能说明
$_COOKIE得到会话控制中cookie传值
$_SESSION得到会话控制中session的值
$_FILES得到文件上传的结果
$_GET得到get传值的结果
$_POST得到post传值的结果
$_REQUEST即能得到get的传值结果,也能得到Post传值的结果

请再记一句话:以上这些变量全是超全局的。

2.22 环境变量

环境变量我们主要用的有$_SERVER和$_ENV两个环境变量 , 不过,$_ENV逐渐被PHP的新版本给废弃了。

我们来了解一些常用的环境变量的键名和值对应的意思:

phpinfo();打印出来了一批乱乱的东西,今天来看看其中的环境变量部份。

键名含义
$_SERVER[“REQUEST_METHOD”]请求当前PHP页面的方法
$_SERVER[“REQUEST_URI”]请求的URI
$_SERVER[“SERVER_SOFTWARE”]用的是哪一种服务器
$_SERVER[“REMOTE_ADDR”]客户的IP地址
$_SERVER[“SERVER_ADDR”]当前服务器的IP地址
$_SERVER[“SCRIPT_FILENAME”]主前请求文件的路径
$_SERVER[“HTTP_USER_AGENT”]当前访问这个网址的电脑和浏览器的情况
$_SERVER[“HTTP_REFERER”]上级来源(用户从哪个地址进入当前网页的)
$_SERVER[“REQUEST_TIME”]当前的时间

URI 和URL都是网址,但是URL带有了主机地址部份,而URI不带主机地址部份,例如:
http://www.php.cn/abc.php?username=php 上面是一个URL(统一资源定位符),而URI是不带主机和(http://)

协议的部份:abc.php?username=php

2.23 变量引用

<?php
$fo = 5;
//$fo的值为5,将5赋值
$bar = $fo;
//$bar的值原来为5,现在将值改为6
$bar = 6;
//$bar的结果为6
echo $bar.'<br />';
//$fo的结果为5
echo $fo.'<br />';
?>

在这里插入图片描述

<?php
$fo = 5;
//注意,加上了一个&符哟
$bar = &$fo; // 表示$bar 和 $fo 引用了同一个变量,&相当于C语言的指针:$bar = *$fo;
$bar = 6;
//$bar的结果为6
echo $bar.'<br />';
//$fo的结果为6
echo $fo.'<br />';
?>

在这里插入图片描述

3. 运算

3.1 算术运算

算数运算符,就是大家小学所学绝大多数知识:

符号说明举例
+加号$x + $y
-减号$x - $y
*乘号,乘以$x * $y
/除号,除以$x / $y
%取余也叫取模、求模$x % $y

3.2 赋值运算符

符号举例等价式
+=$x += $y$x = $x + $y
-=$x -= $y$x = $x - $y
*=$x *= $y$x = $x * $y
/=$x /= $y$x = $x / $y
%=$x %= $y$x = $x % $y
.=$x .= $y$x = $x . $y

3.3 自加自减

符号说明
$x++先赋值后加
$x–先赋值后减
++$x先加后赋值
–$x先减后赋值

3.4 比较运算符

说明符号
大于>
小于<
大于等于>=
小于等于<=
不等于!=
等于==(赋值是=号,所以==规定为等于)
全等(判断类型等于)===
全不等(判断类型不等于)!==

3.5 逻辑运算符

举例说明详细说明
$x and $y逻辑与(并且关系) x 和 x 和 xy 为真则返回真
$x && $y同上同上
$x or $y逻辑或 x , x, x,y均为false时为假,其他情况全为真
$a || $b同上同上
! $x逻辑非取反,即true变为false,false变为true
$x xor $y逻辑异或相同取false,相异为true

&&与&的区别

  • &&如果前面一句为假,后面的一句就会忽略,不进行计算
  • & 不管前面是真是假,前后都会计算

|| 与 | 的区别

  • || 如果前面是true,则后面的代码直接忽略,不进行计算
  • | 不管前后的返回值,前后都会计算
<?php // 典型的短路与
//如果为defined('AUTH')存在AUTH常量则为true,不访问后面的exit了。如果为false则执行exit
defined('AUTH') or exit('存在安全因素不准访问');
?>

exit 的意思是指在此处停止运行,退出。后面的PHP代码不再执行了。它有两种用法:
1,直接exit; 就是直接退出,终止程序
2,exit(‘提示内容’),退出的时候还给出一段提示内容

3.6 位运算

举例说明详细说明
$a & $bAnd(按位与)将把 $a 和 $b 中都为 1 的位设为 1。
$a | $bOr(按位或)将把 $a 和 $b 中任何一个为 1 的位设为 1。
$a ^ $bXor(按位异或)将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
~ $aNot(按位取反)将 $a 中为 0 的位设为 1,反之亦然。
$a << $b左移将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b右移将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。

3.7 三元运算符和其他运算符

符号说明
$x? 真代码段:假代码段判断是否为真假 ? 真情况 : 假情况;
``(反引号)反引号中间插代命令,执行系统命令,等价于shell_exec函数
@单行抑制错误,把这一行的错误不让它显示出来了,效率低不建议使用
=>数组下标访问符,array(‘sina’ =>‘新浪’ ,‘sohu’ => ‘搜狐’);
->对象访问符,$obj -> username = ‘PHP’;(相当于别的语言的obj.username)
instanceof判断某个对象是否来自某个类,如果是的返回true,如果不是返回false

3. 控制语句

  • if(判断条件){true:执行语句 }
  • if(判断条件){true:执行语句}else{false: 执行语句}
  • if(判断条件)…else if(判断条件)…else if(判断条件)else{} 条件相互弥补
  • switch(变量) {case 具体值: 执行语句;break;case 具体值: 执行语句;break;…;default:}
  • while(判断条件) {true:执行语句}
  • do{执行语句}while(条件判断) 先执行do,然后while判断
  • for(表达式1; 表达式2;表达式3){true:执行的代码}
    • exit(‘提示语’) : 从当前处停止后续执行 ,程序终止
    • break : 跳出循环或者跳出结构体执行后续代码
    • continue: 跳出此次循环,下次循环继续
  • goto: 使用 goto 来跳出循环
<?php
for($i=0; $i<100; $i++) {
    echo '第'. $i .'周往返北京大连<br />';
    if($i == 17){
            goto end; // 输出到17的位置,直接跳到,end:执行以下代码,不管中间有多少代码
     }
}

end:
echo '集团公司要求停止此项';
?>

**注意:**PHP 中的 goto 有一定限制,目标位置只能位于同一个文件和作用域,也就是说无法跳出一个函数或类方法,也无法跳入到另一个函数。也无法跳入到任何循环或者 switch 结构中。可以跳出循环或者 switch,通常的用法是用 goto 代替多层的 break。

4. 函数

4.1 自定义函数

function 函数名(参数[=值],参数[=值]) {函数功能体; [return 返回值]}

  • 函数以function开始
  • function后面接空格,空格后跟函数名
  • 函数名与变量名的规则基本一样,但是不同的是: 函数名不区分大小写
  • 所谓的参数其实就是变量
  • 函数名后跟括号,括号内跟参数, 函数体的参数若是定义了,未传参数,代码会报错
  • 如果有参数的话,参数后可以接(=)等号,等号接默认值 可选,如果是有默认值,函数可以不用传参,传参则会覆盖默认值,写参数时,无默认值的参数写在前面
  • 函数后的参数变量,主要功能是把函数体外的变量值,传入函数体内来使用,函数体的变量和函数体外的变量通常是两个不同的变量。
  • 函数中的具体功能(功能体)用大括号括起来,代表这是一个函数的功能区间
  • 函数可以有返回值也可以没有返回值,
  • return后接空格,空格后接返回值,若有return,return后的代码均不执行
  • 函数的执行没有顺序关系,可以在定义处之前的位置调用
  • 函数不能被定义两次,即函数不能被重载

4.2 回调函数

回调函数,可以配合匿名函数和变量函数实现更加优美、复杂的一种函数结构。

回调函数,就是在处理一个功能的时候,我让让这个功能自定义能力再强一些,我准许调用这个函数的时候,还可以传入一个函数配合、协助进行处理。

4.3 变量函数

可变函数仅仅是可变变量的一个变种、变形表达。

可变变量

<?php 
$hello = 'world';
$world = '你好';
//输出的结果为:你好
echo $$hello; 
?>

变量函数

<?php
function demo(){
    echo '天王盖地虎';
}
function test(){
    echo '小鸡炖蘑菇';
}
$fu = 'demo';
//把$fu变为了demo,把demo后加上了一个括号,就执行函数了
$fu();
//把$fu的值改为test字符串再试试?
?>

4.4 匿名函数

  • 所谓匿名,就是没有名字。
  • 匿名函数,也就是没有函数名的函数。
  • 匿名函数的第一种用法,直接把赋数赋值给变量,调用变量即为调用函数。
  • 匿名函数的写法比较灵活。

变量式匿名函数

<?php
$greet = function($name) // 匿名函数
{
 echo $name.',你好';
};
$greet('明天');
$greet('PHP');
?>

回调式匿名函数

<?php
function woziji($one,$two,$func){
       //我规定:检查$func是否是函数,如果不是函数停止执行本段代码,返回false
       if(!is_callable($func)){
               return false;
       }
       //我把$one、$two相加,再把$one和$two传入$func这个函数中处理一次
       //$func是一个变量函数,参见变量函数这一章
       echo $one + $two + $func($one,$two);
}
woziji(20,30,function( $foo , $bar){ // 回调式匿名函数
               $result = ($foo+$bar)*2;
               return $result;
           }
);
?>

4.5 内部函数

内部函数,是指在函数内部又声明了一个函数。

注意事项:

1.内部函数名,不能是已存在的函数名

2.假设在函数a里面定义了一个内部函数,不能定用两次函数a。

<?php
function foo()
{
 echo '我是函数foo哟,调一下我才会执行定义函数bar的过程<br />';
 function bar()
 {
 echo '在foo函数内部有个函数叫bar函数<br />';
 }
}

//现在还不能调用bar()函数,因为它还不存在
// bar();

foo();

//现在可以调用bar()函数了,因为foo()函数的执行使得bar()函数变为已定义的函数
bar();

//再调一次foo()看看是不是会报错?
// foo();
?>
  • foo() 调用两次会出错,连续,不间隔也会出错
  • 如果不调用foo()函数,就无法执行内部函数bar,因为bar是在foo内部,只要foo运行了,bar可以运行无数次

4.6 变量作用域

  • 函数定义时后括号里面接的变量是形式上的参数(形参),与函数体外的变量没有任何关系。仅仅是在函数内部执行

  • 函数内声明的变量也与函数外的变量没关系。

但是,我们实际的处理情况中会遇到这样的一个情况:

  • 我想在函数体内定义的变量在函数体外用

  • 我想把函数体外的变量拿到函数体内来使用

这个时候我们就需要用到超全局变量

全局变量名功能说明
$_COOKIE得到会话控制中cookie传值
$_SESSION得到会话控制中session的值
$_FILES得到文件上传的结果
$_GET得到get传值的结果
$_POST得到post传值的结果
$_REQUEST即能得到get的传值结果,也能得到Post传值的结果
<?php
header("Content-type: text/html;charset=utf-8");
$hello = 10;
echo $GLOBALS['hello'].'<br />'; // 10

$GLOBALS['hello'] = '我爱你';
echo $hello; // 我爱你
?>

你会发现 变 量 名 是 等 价 于 变量名是等价于 GLOBALS[‘变量名’] 。所有的变量都放到了 G L O B A L S 里 面 了 。 而 GLOBALS里面了。而 GLOBALSGLOBALS也是全局的

将函数体内的变量(局部变量)在函数外部使用。也可以让函数外的变量到函数里面来使用

  • 通过$GLOBLAS来读取外部变量
  • 通过$GLOBLAS在函数内修改变量
  • 通过$GLOBLAS,在函数内创建全局变量 ,需要访问,必须调用函数先
<?php
header('Content-type: text/html; charset=utf-8');
$hongniu = '我是一个兵,来自老百姓';
function test(){
   echo '执行了函数test哟<br />'; // 1. 执行了函数test哟
   //调用test()函数,将通过$GLOBALS['hongniu'],把$hongniu的值改变掉

	$GLOBALS['hongniu'] = '帮助别人很快乐'; 
	echo $GLOBALS['hongniu'].'<br/>';  // 2. 帮助别人很快乐;注意$hongniu访问不了

	$GLOBALS['a'] = '123456';  // 局部变量声明全局变量,有个限制,就是要调用这函数才能访问
}
test(); 
echo $hongniu.'<br/>'; // 3. 帮助别人很快乐
echo $a; // 123456
?>

4.7 参数的引用

变量引用

<?php
$a = 10;
$b = &$a; // $b = *$a
$a = 100;
echo $a.'---------'.$b;  // 100
?>

变量引用有讲述,是指变量 a 和 a和 ab指向到了同一个存储位置,来存值。而函数的参数引用,也是这个意思,将形参和实参指向到同一个位置。如果形参在函数体内发生变化,那么实参的值也发生变化。我们来通过实验来看看:

<?php
$foo = 100;
//注意:在$n前面加上了&符
function demo(&$n){ // 形参与全局变量指向同一地址引用
       $n = 10;
       return $n + $n;
}
echo  demo($foo).'<br />';
//你会发生$foo的值变为了10
echo $foo;
?>

4.8 递归函数

自己调用自己, 递归在实际工作中主要是用在:文件和文件夹操作的时候有使用到。

1.代码是从上到下执行的,所有代码没有exit等停止符,函数必须执行完。

2.如果函数从函数A跳至函数B后,必须把函数B执行完成再执行函数A余下的代码。

3.递归函数必须要能执行完有结束条件,不然函数就会限入死循环。函数会永远的自我执行下去。

4.9 静态变量

函数内声明:static $a = 0;

静态变量的特点是:声明一个静态变量,第二次调用函数的时候,静态变量不会再初始化变量,会在原值的基础上读取执行。

5.10 文件包含函数

在实际开发中,常常需要把程序中的公用代码放到一个文件中,使用这些代码的文件只需要包含这个文件即可。这种方法有助于提高代码的重用性,给代码的编写与维护带来很大的便利。在PHP中, 有require、require_once、include、include- once四种方法包含一个文件。

函数包含失败特点
Inlcude返回一条警告文件继续向下执行。通常用于动态包含
Require一个致命的错代码就不会继续向下执行。通常包含极为重要的文件,整个代码甭想执行
Include_once返回一条警告除了原有include的功能以外,它还会做once检测,如果文件曾经已经被被包含过,不再包含
Require_once一个致命的错除了原的功能一外,会做一次once检测,防止文件反复被包含
<?php
//functions.php文件
function demo(){ echo 'aaaa';}
function test(){ echo 'cccdddd';}
?>
<?php
//user.php
include 'functions.php';
//可以直接调用
demo();
test();
?>

require和include都是导入模块,如果include导入不存在的模块,会警告并且会继续执行后面的代码,但是require会直接报错,后面代码就无法执行

  • include_once: 检测是否重复包含一个模块文件,如果包含在重复包含一次,意思是只会执行一次., 而include_once不报错的原因是因为:他检测了functions.php曾经包含过,不再进行包含引入了。
  • include: 不管有没有包含,会再执行一遍,重复包含会报错

5.11 获取时间信息

  • 设置时区

    • date_default_timezone_get()
    • date_default_timezone_set()
  • 获取时间戳

    • time()
  • date函数用于将一个时间进行格式化输出,以方便时间的显示或存储

string date ( string $forrnat [, int $tirnestamp] )

$timestamp是一个时间戳,函数将这个时间戳按$format规定的格式输出 , 如果$timestamp没有输入值,则默认为当前的时间

$format是一个时间输出格式的字符串,需要使用规定的字符构造输出格式。 API,date查询

<?php
	header('Content-type: text/html;charset=utf-8');
	echo date_default_timezone_get().'<br/>'; // 获取时区: UTC

	// 定义时区常量: Asia 亚洲上海
	define('TIME_ZH','Asia/shanghai');
	date_default_timezone_set(TIME_ZH);
	echo date('Y-m-d H:i:s').'<br/>'; // 2020-02-28 11:06:31

	echo time(); //获取当前nuix事件戳: 1582859258
?>
  • getdate用来获取当前系统的时间,或者获得一个时间戳的具体含义。时间戳是一个长整数

array getdate ([ int $timestamp = time() ] )

函数的返回值是一个根据timestamp得到的包含有时间信息的数组。如果没有参数,则会返回当前的时间。getdate返回的数组,键名包括时间和日期的完整信息。

<?php
    echo getdate().'<br/>'; // Array
	print_r(getdate()); // print_r()输出复杂数据类型
	echo '<br/>';
	/* 
	Array(
		[seconds] => 1 // 秒
		[minutes] => 21  // 分
		[hours] => 11  // 时
		[mday] => 28   // 日
		[wday] => 5  // 星期中的第几天
		[mon] => 2  // 月
		[year] => 2020  // 年
		[yday] => 58  // 年中第几天
		[weekday] => Friday  // 星期
		[month] => February  // 月份
		[0] => 1582860112 // 事件戳
	)
	*/
	$timer = getdate();
	echo $timer['minutes'].'<br/>';
?>

5.12 日期验证函数

checkdate可以判断一个输出的日期是否有效 ,在实际的工作中,我们需要经常用于检测常用于用户提交表单的数据验证。例如:验证用户输入的时间是否正确。

函数的语法格式如下:

bool checkdate ( int $month , int $day , int $year )

// 判断2020年2月有没有29,30日
var_dump(checkdate(2,29,2020));  // boolean true
var_dump(checkdate(2,30,2020));  // boolean false

5.13 指定时间

mktime()简称:make time.创建时间,可以对一个日期和时间获得一个本地化时间戳

int mktime (int $hour [, int $minute [, int $second [, int $month [, int d a y [ . i n t day [. int day[.intyear [, int $.is_dstl.l } ] ] 31 )

函数的参数分别表示:时、分、秒、月、日、年、是否为夏令时

<?php
	// 2020-2-27 11:38:25 到1970-1-1 0:0:0的时间毫秒差
	echo mktime(11,38,25,2,27,2020).'<br/>';  // 1582774705
	echo date("Y-m-d h:i:s")."<br/>"; // 2020-02-28 11:02:53
	// 参数1: 时间格式,mktime(时,分,秒,现在年,现在月,现在日)
	echo date("Y-m-d h:i:s",mktime(10,1,59,date('m'),date('d'),date('Y'))).'<br />';
	// 2020-02-28 10:02:59
	echo date("Y-m-d h:i:s",mktime(11,1,59,date('m'),date('d'),date('Y'))).'<br/>';
	// 2020-02-28 11:02:59
?>

strtotime() 它能将将英文文本的日期时间描述解析为 Unix 时间戳。

int strtotime ( string $time [, int $now = time() ] )

  • 参数1: 传入一个字符串的时间

  • 参数2: 可选参数为是否传入unix时间戳,如果不传则是当前的unix时间戳。

//now为现在的当前时间
echo strtotime("now")."<br />";  // 1582862251
//2000年9月10日
echo strtotime("10 September 2000")."<br />"; // 968515200
//当前时间加一天
echo strtotime("+1 day")."<br />"; // 1582948651
//当前时间加一周
echo strtotime("+1 week")."<br />"; // 1583467051
//当前时间加一周2天4小时2秒
echo strtotime("+1 week 2 days 4 hours 2 seconds")."<br />"; // 1583654253
//下一个星期四
echo strtotime("next Thursday")."<br />";  // 1583337600
//上一个星期一
echo strtotime("last Monday")."<br />"; // 1582473600

5.14 程序执行时间

microtime()这个函数,能够返回当前 Unix 时间戳和微秒数。

mixed microtime ([ bool $get_as_float ] )

如果你传入true的话,将会返回一个浮点类型的时间,这样方便参与运算。

<?php
//开始时间
$time_start = microtime(true);
//循环一万次
for($i = 0 ; $i < 10000 ; $i++){
}
//结整时间
$time_end = microtime(true);
//相减得到运行时间
$time = $time_end - $time_start;
echo "这个脚本执行的时间为 $time seconds\n"; // 0.00019502639770508 seconds
?>

mktime() 生成一个昨天的时间,再用strtotime() 生成一个昨天的时间,对比两个函数认的效率高

$a = microtime(true);
	// 2020-02-27 12:14:18
	echo date('Y-m-d h:i:s',mktime(date('h'),date('i'),date('s'),date('m'),date('d')-1,date('Y'))).'<br/>';
	$b = microtime(true);

	$aa = microtime(true);
	// 2020-02-27 12:14:18
	echo strtotime("last day").'<br />';
	$bb = microtime(true);
	
	$c = $a - $b;
	$cc = $aa - $bb;
	
	if($c > $cc) {
		echo 'microtime 大于 strtitime执行时间';
	}else {
		echo 'microtime 小于 strtitime执行时间';
		// microtime 小于 strtitime执行时间
	}

5. 数组定义

5.1 基本操作

  • 数组可以存入多个不同类型的数据,是一个复合数据类型。
  • 数组的英文是array,学下最简单的数组声明。
  • 数组下标不一定从0,开始
  • 索引数组若不强制声明他的下标,他的下标是从0开始的。(我们的第一个数组的值:只有不断努力才能博得未来。这个值的下标为0)
  • 向索引数组中增加元素用: 数组变量名[]、数组变量名[键值]这两种方式来增加元素
  • 键值的增长规则与之前的规则一样。都是最大值加1的原则
  • 使用unset删除变量的方式来删除数组里面的值。
  • 删除了中间的值,并不会让后面的下标向前自动移动。而是原来的值为多少就为多少
  • 删除掉其中的某个值,新加入的值不会替换掉原来的位置,依然遵循最大值加1的原则
  • 用变量名[键] = 新值。就把数组中的值定的值修改了
<?php
	header('Content-type: text/html;charset=utf-8');
	$arr = array(1,1.5,true,'您好啊');
	var_dump($arr);
	/*
	数组 
  0 =>  整数 1 
  1 =>  浮点数 1.5 
  2 =>  布尔值 true 
  3 =>  字符串 '您好啊'  (length = 9)
	*/
	$arr01 = array(2=>'Hello',10 => 'NoAlike','PHP',19=>'Good','love');
	var_dump($arr01);
	/*
array
  2 => string 'Hello' (length=5)
  10 => string 'NoAlike' (length=7)
  11 => string 'PHP' (length=3)
  19 => string 'Good' (length=4)
  20 => string 'love' (length=4)
  */
	$minren = array('杨幂','王珞丹','刘亦菲', '黄圣依');
	$minren[] = '范冰冰';
	$minren[100] = '范爷';
	$minren[] = '李晨';
	var_dump($minren);
	/*
	array
	  0 => string '杨幂' (length=6)
	  1 => string '王珞丹' (length=9)
	  2 => string '刘亦菲' (length=9)
	  3 => string '黄圣依' (length=9)
	  4 => string '范冰冰' (length=9)
	  100 => string '范爷' (length=6)
	  101 => string '李晨' (length=6)
	*/
	unset($minren[3]);
	var_dump($minren);
	/*
array
  0 => string '杨幂' (length=6)
  1 => string '王珞丹' (length=9)
  2 => string '刘亦菲' (length=9)
  4 => string '范冰冰' (length=9)
  100 => string '范爷' (length=6)
  101 => string '李晨' (length=6)
	*/
?>

5.2 其他声明方式

**1. 直接用之前未声明的变量,用变量名后面接中括号的方式声明数组 **

<?php
    //直接写一个变量后面加上中括号,声明变量
    $qi[] = '可口可乐';
    $qi[10] ='百事可乐';
    var_dump($qi);
/*
array
  0 => string '可口可乐' (length=12)
  10 => string '百事可乐' (length=12)
*/
?>

**2. 每次用array()写的太麻烦了,还可以不用写array哟,更简单 **

<?php // php版本5.4以后有的
$qi = ['可口可乐',10 => '百事可乐']
    var_dump($qi);
/*
array
  0 => string '可口可乐' (length=12)
  10 => string '百事可乐' (length=12)
*/
?>

5.3 关联数组

  • 声明关联数组是 键名 => 值
  • 在关联数组可以有索引数组的元素
  • 关联数组中的索引数组的元素后再声明了无下标的元素,依然是最大值+1原则
	$qi[] = '可口可乐';
    $qi[10] ='百事可乐';
    var_dump($qi);
	$arr02 = array(
		'hello' => '超级玛丽',
		'住哪' => '蘑菇岛',
		'年龄' => '30岁',
		100 => '...继续中',
		'小矮人',
	);
	var_dump($arr02);
	/*
array
  'hello' => string '超级玛丽' (length=12)
  '住哪' => string '蘑菇岛' (length=9)
  '年龄' => string '30岁' (length=5)
  100 => string '...继续中' (length=12)
  101 => string '小矮人' (length=9)
	*/

5.4 数组计算

count — 计算数组中的单元数目,或对象中的属性个数,可以用于for循环

int count ( array,mode)

  • mode

    • 0 - 默认。不对多维数组中的所有元素进行计数
    • 1 - 递归地计数数组中元素的数目(计算多维数组中的所有元素)

对于数组,返回其元素的个数,对于其他值,返回 1。如果参数是变量而变量没有定义,则返回 0。

如果 mode 被设置为 COUNT_RECURSIVE(或 1),则会递归底计算多维数组中的数组的元素个数。

<?php
	$a[0] = 2;
	$a[1] = 3;
	$a[2] = 5;
	echo count($a).'<br/>'; // 3
	for($i = 0; $i < count($a); $i++) {
		echo $a[$i].' , ';  // 2,3,5,
	};

	$b[0]  = '迪奥和奥迪我都爱';
	$b[5]  = '努力开创未来';
	$b[10] = '为了未来而努力';
	echo count($b).'<br/>'; // 3
	
	$c = array(
		1 => array(
			1 => 'HTML',
			2 => 'CSS',
			3 => 'JS',
		),
		2 => array(
			1 => 'Java',
			2 => 'JavaWeb',
			3 => 'JSON',
		),
		3 => array(
			1 => '汇编',
			2 => 'C',
			3 => 'C++',
		),
		4 => array(
			1 => 'python',
		),
	);
	echo count($c,0).'<br />'; // 4 浅度,下面深度
	echo count($c,1).'<br />'; // 14 = 大数组4个 + 大数组中的小数组10个
?>

5.5 foreach遍历数组

for循环可以遍历连续下标数组,但是遍历不了关联数组和下标不联系的数组,会乱码警告

这时候亦可用foreach循环

foreach( 要循环的数组变量 as [键变量 =>] 值变量){ }

<?php
header('Content-type: text/html;charset=utf-8');
$arr01= array('李某',3 => '18','人妖');
foreach($arr01 as $key => $val) {
	echo $key.'-------'.$val.',';
	// 0 -------李某,3 ------- 18,4 -------人妖
}
// 二维数组
$arr02 = array(
       0 => array(
           '中国' => 'china',
           '美国' => 'usa',
           '德国' => ' Germany',
       ),
       1 => array(
           '湖北' => 'hubei',
           '河北' => 'hebei',
           '山东' => 'shandong',
           '山西' => 'sanxi',
       ),
);
echo '<br/>';
foreach($arr02 as $val){
	foreach($val as $k => $v) {
		echo $k.'-------'.$v.',';
		// 中国-------china,美国-------usa,德国------- Germany,
		// 湖北-------hubei,河北-------hebei,山东-------shandong,山西-------sanxi,
	}
	echo '<br />';
}
echo '<br />';
// 三维
$arr03=array(
	'教学部'=>array(
		 array('李某','18','人妖'),
		 array('高某','20','男'),
		 array('张某','21','妖人'),
	 ),
	 '宣传部'=>array(
		 array('李某','18','人妖'),
		 array('高某','20','男'),
		 array('张某','21','妖人'),
	 ),
	 '财务部'=>array(
		 array('李某','18','人妖'),
		 array('高某','20','男'),
		 array('张某','21','妖人'),
	 ),
);
foreach($arr03 as $ke => $val) {
	echo $ke.'<br/>';
	foreach($val as $value){
		foreach($value as $k => $v){
			// var_dump($value);
			// var_dump($k);
			echo "-----".$k.'-----'.$v.'<br />';
		}
		echo ' <br/>';
	}
	echo ' <br/>';
}
?>

5.6 list、each函数遍历数组

list ( mixed $变量1 [, mixed $变量n ] )

它的功能:将索引数组下标为0的对应变量1,下标1的对应变量2,依此类推。如果是没有的变量就会警告继续运行, 和JS里面对象解构赋值一样,

<?php
	header("Content-type: text/html;charset=utf-8");
	list($one,$two,$three) = array('张三','李四','王五');
	// 单引号不解析变量
	echo '$one----'.$one.'<br />';  // $one----张三
	echo '$two----'.$two.'<br />';  // $two----李四
	echo '$three----'.$three.'<br />';  // $three----王五

	list($one1,$two1,$three1) = array('芹芹',2=>'勤勤','琴琴');
	echo '$one1----'.$one1.'<br />';  // $one1----芹芹
	echo '$two1----'.$two1.'<br />';  
	echo '$three1----'.$three1.'<br />';  // $ three1 ----勤勤
?>

1.因为是一一对应原则,$one1找到标为0的数组元素,$two1找不到下标为1的数组元素,$three找到了下标为2的数组元素

3.在list($one1, $two1, $three1),我只写了三个变量。对应完成,而后面的’琴琴’对应的是4

array each ( array &$array )

传入一个数组。它会将其中的一个元素拆为个新数组。每次执行这样操作一个元素。执行一次先后移动一次,同样的方式操作下一个数组元素。执行到最后,返回false。

<?php
	header('Content-type: text/html;charset=utf-8');
	$kongjie=array(
	   'gao'=>'穿黑衣服的',
	   'shou'=>'退特别长特别细',
	   'mei'=>'好白',
	   'pl'=>'五官端正',
	   'type'=>'那就是女神',
	   '我是吊丝不敢跟女神搭讪'
   );
	echo each($kongjie); // Array
	var_dump(each($kongjie)); // 在执行一次,就会读取分解第二个
?>
/*
array
  1 => string '穿黑衣服的' (length=15)
  'value' => string '穿黑衣服的' (length=15)
  0 => string 'gao' (length=3)
  'key' => string 'gao' (length=3)    
*/

总结

  • 读取了$kongjie中的第一个元素,将第一个元素(‘gao’=>‘穿黑衣服的’)分解开了
  • 分解后第一个元素变成了一个新数组。
  • 在新数组里面,将原值(穿黑衣服的)放了索引下标1里面,同时放到了关联下标value里面
  • 在新数组里面,将原键(gao),放到了关联下标key里面,放到了索引下标0里面。

在这里插入图片描述

list和each配合

list( k e y , key, key,value) = each($array);

<?php
	header('Content-type: text/html;charset=utf-8');
	$arr = array(
		'name'=> 'nice',
		'age'=> 18,
		'adree' => '九江',
		);
	// list($key,$value) = each($arr);
	// echo $key.'---'.$value.'<br />';
	while(list($key,$value) = each($arr)){
		echo $key. '-----' .$value .'<br />';
		/*
			name-----nice
			age-----18
			adree-----九江
		*/
	}
?>

总结:

  • each 把变量拆成了4个元素
  • 而list把0 =>gao 赋值给了变量$key
  • list把1 => 穿黑衣服的 赋值给了变量 $value
  • 如果一直调用,调用完就会返回false
  • 可以通过each和list配合实现foreach一样的效果。

5.7 其他API

  • in_array(‘key’,arr) 判断数组中是否存在某个元素
  • array_key_exists(‘key’,arr) 检测数组是否存在key

6. 正则

6.1 定界符

定界符,就是定一个边界,边界已内的就是正则表达示,不能用a-zA-Z0-9\ 其他的都可以用。必须成对出现,有开始就有结束

例子说明
/中间写正则/正确
中 间 写 正 则 中间写正则 正确
%中间写正则%正确
中间写正则正确
@中间写正则@正确
(中间写正则)错误
A中间写正则A错误

6.2 原子

原子是正则表达示里面的最小单位,原子说白了就是需要匹配的内容。一个成立的正则表达示当中必须最少要有一个原子。

所有可见不可见的字符就是原子

说明:我们见到的空格、回车、换行、0-9、A-Za-z、中文、标点符号、特殊符号全为原子

preg_match

int preg_match ( string $正则 , string KaTeX parse error: Expected 'EOF', got '&' at position 14: 字符串 [, array &̲结果] )

功能:根据$正则变量,匹配$字符串变量。如果存在则返回匹配的个数,把匹配到的结果放到$结果变量里。如果没有匹配到结果返回0。

<?php
	header('content-type: text/html;charset=utf-8');
	$regexp = '/a/';
	$str = 'sahdjsahdjkklj';
	if(preg_match($regexp,$str,$match)){
		echo '匹配了';
		var_dump($match);
	}else {
		echo '再接再厉';
	}
/*
匹配了
array
  0 => string 'a' (length=1)
*/
?>
原子说明
\d匹配一个0-9
\D除了0-9以外的所有字符
\wa-zA-Z0-9_
\W除了0-9A-Za-z_以外的所有字符
\s匹配所有空白字符\n \t \r 空格
\S匹配所有非空白字符
[ ]指定范围的原子
^相当于非,对条件进行否定,不匹配该居间的字符

6.3 元字符

上面的原子只能匹配一个字符,想要匹配一堆字符只能使用元字符, 需要借助元字符来帮我们修饰原子,实现更多的功能。

字符功能说明
*是代表匹配前面的一个原子,匹配0次或者任意多次前面的字符。
+匹配一次或多次一个字符
?前面的字符匹配一次或者没有
.更标准一些应该把点算作原子。匹配除了\n以外的所有字符
|或者。注:它的优先级最低了。
^必须要以抑扬符之后的字符串开始
$必须要以$之前的字符结尾
\b词边界
\B非边界
{m}有且只能出现m次
{n,m}可以出现n到m次
{m,}至少m次,最大次数不限制
()改变优先级或者将某个字符串视为一个整体,匹配到的数据取出来也可以使用它
$zz = '/gg.+gg/'; 
// 中间点: 匹配一个字符\n除外
// 中间+: 匹配多个字符
// 结果: gg(任意多个字符,\n除外)gg

$zz = '/ABC\d?ABC/'
// \d: 0-9一个数字
// ? : 匹配一次或没有
// 结果: ABC(中间的数字只能出现一次要么不出现)ABC

$zz = '/\w*/';
// *: 匹配0次以上
// \w: A-Za-z0-9_: 只要有这个就正确不管多少次

$zz = '/abc|bcd/';
// | : 或者
// 只要字符串中有abc或者bcd就可以,不管在哪,但要连续

$zz = '/^猪哥好帅\w+/';
// ^: 以'猪哥好帅'字符串开始
// \w+: 匹配a-zA-Z0-9_,匹配一次以上

$zz = '/\d+努力$/';
// $: 以努力结尾
// \d+: 0-9 匹配一次以上 

$zz = '/\w+\b/';
// \w+: 匹配: 0-9a-zA-Z_,多次
// \b: 以空格分隔单词,单词开始以'\w'匹配
// 匹配不成功: "$sad $hja$"; \w不在词的边界

$zz = '/\w+\B/';
// \B: 以空格分隔单词,单词除去首尾字符,中间匹配\w
// 匹配不成功: "A----B B+++++A",\w在词的边界

$zz = '/喝\d{3}酒/';
// \d{3}: 匹配'\d'3次

$zz = '/喝\d{3,9}酒/'
// \d{3,9}: 匹配'\d'3-9次

$zz = '/喝\d{3,}酒/';
// \d{3,}: 至少3次,最多不限制

6.4 模式修正字符

用法:

/ 正则表达示/模式匹配符

模式匹配符功能
i模式中的字符将同时匹配大小写字母.
m字符串视为多行
s将字符串视为单行,换行符作为普通字符.
x将模式中的空白忽略.#后面的字符全部忽略
A强制仅从目标字符串的开头开始匹配.
D模式中的美元元字符仅匹配目标字符串的结尾.
U匹配最近的字符串.
$zz = '/ABC/i';
// '/ABC/'只要字符串里面有abc就可以了
// i : 不区分大小写

$zz = '/^a\d+/m';
// /^a\d+/: 以a开始,后面匹配\d
// m: 如果字符串换行,每一行尅是都进行匹配

$zz = '/新的未来.+\d+/s';
// 字符串内容之一: 新的未来(\n除外,其他都可以)(0-9,1次以上)
// s: 多行当成一行来识别,\n就不存在了

$zz = '/a b c /x';
// x: 忽略空白字符,匹配abc

preg_replace("/{(\w+) (\d+), (\d+)}/i","\$2","{April 15, 2003}")
// 正则,替换项,查找字符串
// 替换项: \$1-> (\w+), \$2 -> (\d+), \$3 -> (\d+)
// 替换时: /{(\w+) (\d+), (\d+)}/i -> /{(\w+) (\$2), (\d+)}/i,将匹配项提取出来

$zz = '/<div>.*<\/div>/U';
// 正则表达式有多少匹配多少,但是末尾加上U,就是匹配最前面的一个

$zz = '/this/A';// 以this开始,和^元子符,不是原子符

6.5 常用正则

我们常用的正则函数有:

函数名功能
preg_filter执行一个正则表达式搜索和替换
preg_grep返回匹配模式的数组条目
preg_match执行一个正则表达式匹配
preg_match_all执行一个全局正则表达式匹配
preg_replace_callback_array传入数组,执行一个正则表达式搜索和替换使用回调
preg_replace_callback执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace执行一个正则表达式的搜索和替换
preg_split通过一个正则表达式分隔字符串

7. 文件系统

7.1 读取文件

readfile读取文件

int readfile ( string $文件名)

功能:传入一个文件路径,输出一个文件。

文件分隔符: linux: / ; windows: ‘’\’ ; 单斜杠代表转义,双斜杠就行了

<?php
	header('Content-type: text/html;charset=utf-8');
	$rf = readfile('.//a//123.txt','r'); // 直接显示文件内容
?>

file_get_contents打开文件

string file_get_contents ( string filename)

功能:传入一个文件或文件路径,打开这个文件返回文件的内容。文件的内容是一个字符串

<?php
	$path = './/a//123.txt';
	$file = file_get_contents($path);
	echo $file; // 打开文件,输出文件内容
?>
<?php
	$path = './/a//123.txt';
	$fl = file_get_contents($path);// asdasjhdjkashfjksdhajkfsdh
	// 字符串以a分隔,a就不会在显示了
	$flString = explode('a',$fl);
	var_dump($flString);
	while(list($key,$val) = each($flString)){
		++$key;
		 $val = trim($val);
		 print $key .':'.  $val.'<br />';
		 /*
			1:
			2:sd
			3:sjhdjk
			4:shfjksdh
			5:jkfsdh
		 */
	}
?>

fopen、fread、fclose操作读取文件

resource fopen ( string $文件名, string 模式) 打开文件

  • 参数1: 打开文件的路径
  • 参数2: 打开文件的参数

返回类型是一个资源类型,基础类型的时候讲到的资源类型。资源类型需要其他的函数来操作这个资源。所有的资源有打开就要有关闭。

string fread ( resource $操作资源, int 读取长度)

读取打开的文件资源。读取指定长度的文件资源,读取一部份向后移动一部份。至到文件结尾。

bool fclose ( resource $操作资源 )

关闭资源。资源有打开就有关闭

资源类型的通常操作:

  • 打开资源
  • 使用相关函数进行操作
  • 关闭资源
模式说明
r只读方式打开,将文件指针指向文件头。
r+读写方式打开,将文件指针指向文件头。
w写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建
w+读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建
a写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建
a+读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之
x创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建
x+创建并以读写方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建

其他注意事项:

模式说明
twindows下将\n转为\r\n
b二进制打开模式
<?php
	header('Content-type:text/html;charset=utf-8');
	$path = './a/123.txt';
	// fopen('打开文件路径','模式');
	$openfile = fopen($path,'r');
	echo $openfile; // 打印资源:Resource id #3
	// fread('操作打开的资源', 文件读取的长度);
	$readfile = fread($openfile,50);
	echo $readfile;  // 打印出内容
	// fclose(操作资源);
	fclose($openfile);
?>

7.2 创建和修改文件内容

file_put_contents 写入文件

int file_put_contents ( string $文件路径, string $写入数据])

功能:向指定的文件当中写入一个字符串,如果文件不存在则创建文件。返回的是写入的字节长度

<?php
	header('Content-type: text/html; charset=utf-8');
	// 写入的数据
	$str = '这是我写入的数据';
	// 文件路径
	$path = './a/123.txt';
	// 把数据写入文件中,成功与否
	$bool = file_put_contents($path, $str);
	if($bool) {
		echo '写入成功我们读取以下试试<br/>';
		// echo file_get_contents($path);
		$open = fopen($path, 'r');
		$read = fread($open, 50);
		fclose($open);
		echo $read;
	}else {
		echo '写入失败或者是没有权限,中途发生错误';
	}
?>

fwrite配合fopen进行写入操作

fwrite的别名函数是fputs

int fwrite ( resource $文件资源变量, string $写入的字符串 [, int 长度])

<?php
	header('Content-type: text/html; charset=utf-8');
	$path = './a/123.txt';
	$str = 'fwrite与fopen一起操作';
	$open = fopen($path,'r+'); // r+可读写,r只能读
	$write = fwrite($open,$str);
	fclose($open);
	$read = file_get_contents($path);
	echo $read;
?>

7.3 创建临时文件

临时文件用完就删,不需要去维护这个文件的删除状态

resource tmpfile ( )

功能:创建一个临时文件,返回资源类型。关闭文件即被删除。

<?php
	header('Content-type:text/html;charset=utf-8');
	// 创建一个临时文件
	$timer = tmpfile();
	// 往里面写数据
	$write = fwrite($timer,'写入临时变量'); // 18字节
	// 关闭临时文件
	fclose($timer);
	echo '向临时变量里面写入了: '.$write.' 字节';// 一文字3字节
?>

7.4 文件移动、拷贝、删除

重命名,移动文件

bool rename( 旧 名 , 旧名, ,新名);

这个函数返回一个bool值,将旧的名字改为新的名字。,填路径就是剪切

<?php
	header('Content-type: text/html; charset=utf-8');
	// 旧文件
	$filename = './a/123.txt';
	// 新文件
	$newfile = './b/123.txt';
	$newname = './b/456.txt';
	// 不会创建文件夹,如果文件存在就会报错
	rename($filename,$newfile); 
	rename($newfile,$newname);
	// 剪切$filename文件到$newfile文件中,然后修改名字
?>

复制文件

bool copy(源文件,目标文件)

功能:将指定路径的源文件,复制一份到目标文件的位置。

<?php
	header('Content-type: text/html;cahrset=utf-8');
	// 旧文件
	$file = './a/123.txt';
	// 新文件名
	$target = './b/123.txt';
	// 有同名文件则会覆盖,没有则会创建文件,但是不会创建目录
	copy($file,$target);
?>

删除文件

删除文件就是将指定路径的一个文件删除,不过这个删除是直接删除。使用的是windows电脑,你在回收站看不到这个文件。

bool unlink(指定路径的文件)

<?php
	header('Content-type: text/html;charset=utf-8');
	$file = './a/123.txt';
	// 文件不存在就会报错
	unlink($file);
?>

7.5 检测文件属性

  • bool file_exists ( $指定文件名或者文件路径) 功能:文件是否存在。
  • bool is_readable ( $指定文件名或者文件路径) 功能:文件是否可读
  • bool is_writeable ( $指定文件名或者文件路径) 功能:文件是否可写
  • bool is_executable ( $指定文件名或者文件路径) 功能:文件是否可执行
  • bool is_file ( $指定文件名或者文件路径) 功能:是否是文件
  • bool is_dir ( $指定文件名或者文件路径) 功能:是否是目录
  • void clearstatcache ( void ) 功能:清楚文件的状态缓存

7.6 文件常用的函数和常量

内置分隔符,windows上是’\’,’/’,linux上是’/’,要在不同的系统上呈现不同的分隔符就需要下面常量

DIRECTORY_SEPARATOR

由于FILE是PHP的预定义常量,所以没办法改变,如果需要让FILE也自适应操作系统。
那么就是不要用FILE,可以用自定义的常量,并且把FILE处理一下,如下

<?php
// str_replace:(参数3中的部分字符替换成参数2,参数2被替换的字符,参数3原始字符) 替换字符串
// __FILE__: 文件绝对路径
// DIRECTORY_SEPARATOR: windows显示\,linux显示/
$_current_file = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, __FILE__);
// 整体意思就是: 在window上,__FILE__绝对路径,DIRECTORY_SEPARATOR参数为\,把arr参数里面的\\替换文件路劲的DIRECTORY_SEPARATOR
define('__CUR_FILE__', $_current_file);// 

echo __CUR_FILE__;

?>

7.7 文件指针操作

rewind(resource handle)

功能:指针回到开始处

fseek ( resource handle, int offset [, int from_where])

功能:文件指针向后移动指定字符

<?php
	header('Content-type: text/html;charset=utf-8');
	$fp = fopen('./a/a.txt','r+');
	// 文件指针读取10字节位置
	echo fread($fp, 10).'<br />'; // abcdeefghi
	// 文件指针回到开始
	rewind($fp);
	// 在此读取10字节
	echo fread($fp,10).'<br />'; // abcdeefghi
	// 文件指针移动到10字节位置
	fseek($fp,10).'<br />';
	// 移动指针后读取
	echo fread($fp,10); // jklk opqr  空格占两个节
/*文件内容
abcdeefghijklkopqrst
uvwxyz
12345678
*/
?>

filesize检测文件大小

<?php
	header('Content-type: text/html;charset=utf-8');
	$filepath = './a/a.txt';
	echo filesize($filepath); // 40KB
?>
函数名功能
file把整个文件读入一个数组中
fgets从文件指针中读取一行,读到最后返回false
fgetc从文件指针中读取一个字符,读到最后返回false
ftruncate将文件截断到给定的长度
函数功能说明
filectime文件创建时间
filemtime文件修改时间
fileatime文件上次访问时间

7.8 文件锁机制

bool flock ( resource $handle , int $operation)

功能:轻便的咨询文件锁定

锁类型说明
LOCK_SH取得共享锁定(读取的程序)
LOCK_EX取得独占锁定(写入的程序)
LOCK_UN释放锁定(无论共享或独占)
<?php
$fp = fopen("demo.txt", "r+");
// 进行排它型锁定
if (flock($fp, LOCK_EX)) { 
   fwrite($fp, "文件这个时候被我独占了哟\n");
  // 释放锁定
    flock($fp, LOCK_UN);    
} else {
   echo "锁失败,可能有人在操作,这个时候不能将文件上锁";
}
fclose($fp);
?>

7.9 目录处理函数

处理文件夹的基本思想如下:

1.读取某个路径的时候判断是否是文件夹

2.是文件夹的话,打开指定文件夹,返回文件目录的资源变量

3.使用readdir读取一次目录中的文件,目录指针向后偏移一次

4.使用readdir读取到最后,没有可读的文件返回false

5.关闭文件目录

函数名功能
opendir打开文件夹,返回操作资源
readdir读取文件夹资源
is_dir判断是否是文件夹
closedir关闭文件夹操作资源
filetype显示是文件夹还是文件,文件显示file,文件夹显示dir

7.10 文件权限设置

函数功能说明
chmod修改读取模式
chgrp修改用户组
chown修改权限
<?php
//修改linux  系统/var/wwwroot/某文件权限为755
chmod("/var/wwwroot/index.html", 755);  
chmod("/var/wwwroot/index.html", "u+rwx,go+rx"); 
chmod("/somedir/somefile", 0755); 
?>

7.11文件路径函数

函数名功能
pathinfo返回文件的各个组成部份
basename返回文件名
dirname文件目录部份
parse_url网址拆解成各部份
http_build_query生成url 中的query字符串
http_build_url生成一个url
<?php
	header('content-type: text/html;charset=utf-8');
	var_dump(pathinfo('E:/WorkingSpace/WEB/PHP/Demo26.php'));
/*
array
// 文件目录
  'dirname' => string 'E:/WorkingSpace/WEB/PHP' (length=23)
  // 文件名
  'basename' => string 'Demo26.php' (length=10)
  // 文件扩展名
  'extension' => string 'php' (length=3)
  // 文件名不包含扩展名
  'filename' => string 'Demo26' (length=6)
  */

	var_dump(parse_url('http://localhost/Demo28file.php?name=zhangsan&age=15'));
	/*
array
  'scheme' => string 'http' (length=4) 
  'host' => string 'localhost' (length=9)
  'path' => string '/Demo28file.php' (length=15)
  'query' => string 'name=zhangsan&age=15' (length=20)
	*/
	
	//生成query内容
	echo http_build_query(array('username'=>'zhangsan','age'=>'18'));
	// username=zhangsan&age=18
?>

8. 文件上传

8.1 文件上传需要注意php.ini文件

配置项功能说明
file_uploadson为 开启文件上传功能,off为关闭
post_max_size系统允许的POST传参的最大值
upload_max_filesize系统允许的上传文件的最大值
memory_limit内存使用限制

建议尺寸: file_size(文件大小) < upload_max_filesize < post_max_size < memory_limit

另外,需要注意的是脚本执行时间。

max_execution_time

这个参数是设定脚本的最大执行时间。 单位是秒

8.2 文件上传步骤

文件上传六大步:

  • 一、判断是否有错误码
错误码说明
0无误,可以继续进行文件上传的后续操作。
1超出上传文件的最大限制,upload_max_filesize = 2M php.ini中设置,一般默认为2M。可根据项目中的实际需要来修改
2超出了指定的文件大小,根据项目的业务需求指定上传文件的大小限制
3只有部分文件被上传
4文件没有被上传
6找不到临时文件夹,可能目录不存在或没权限
7文件写入失败,可能磁盘满了或没有权限
  • 二、自定义判断是否超出文件大小范围

在开发上传功能时。我们作为开发人员,除了php.ini中规定的上传的最大值外。我们通常还会设定一个值,是业务规定的上传大小限制。

例如:
新浪微博或者QQ空间只准单张头像图片2M。而在上传图册的时候又可以超过2M来上传。所以说,它的系统是支持更大文件上传的。此处的判断文件大小,我们用于限制实际业务中我们想要规定的上传的文件大小。

  • 三、判断后缀名和mime类型是否符合

在网络世界里面也有坏人。他们会把图片插入病毒,在附件中上传病毒,他们会在网页中插入病毒或者黄色图片。我们需要对于上传的文件后缀和mime类型都要进行判断才可以。

MIME(Multipurpose Internet Mail Extensions)是多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

在判断后缀和MIME类型的时候,我们会用到PHP的一个函数in_array(),该函数传入两个参数。
第一个参数是要判断的值;
第二个参数是范围数组。

我们用这个函数来判断文件的后缀名和mime类型是否在允许的范围内。

  • 四、生成文件名

我们的文件上传成功了,不会让它保存原名。因为,有些人在原名中有敏感关键词会违反我国的相关法律和法规。

我们可以采用date()、mt_rand()或者unique()生成随机的文件名。

  • 五、判断是否是上传文件

文件上传成功时,系统会将上传的临时文件上传到系统的临时目录中。产生一个临时文件。同时会产生临时文件名。我们需要做的事情是将临时文件移动到系统的指定目录中。而移动前不能瞎移动,或者移动错了都是不科学的。移动前我们需要使用相关函数判断上传的文件是不是临时文件。is_uploaded_file()传入一个参数($_FILES中的缓存文件名),判断传入的名称是不是上传文件。

  • 六、移动临时文件到指定位置

临时文件是真实的临时文件,我们需要将其移动到我们的网站目录下面了。让我们网站目录的数据,其他人可以访问到。

我们使用:move_uploaded_file()。这个函数是将上传文件移动到指定位置,并命名。
传入两个参数:
第一个参数是指定移动的上传文件;
第二个参数是指定的文件夹和名称拼接的字符串。

form表单文件上传

<form action="file.php" method="post" enctype="multipart/form-data">
           <input type="file" name="file">
           <input type="submit" value="上传">
       </form>

注意事项:

  • form 表单中的参数method 必须为post。若为get是无法进行文件上传的
  • enctype须为multipart/form-data
<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>文件上传</title>
	</head>
	<body>
<!--enctype="multipart/form-data": 
	enctype: 编码类型
	multipart/form-data: 表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思
	默认值: application/x-www-form-urlencoded这个不能用于文本上传,只有上面的才能完整的传递文件
	上传文件必须是post请求
-->
		<form action="http://localhost/Demo26.php" method="post" enctype="multipart/form-data">
			<input type="file" name="file">
			<input type="submit" value="上传">
		</form>
	</body>
</html>
<?php
	header('Content-type: text/html; charset=utf-8');
	// $_FILES: 上传的所有数据都保存在这个系统函数里
	var_dump($_FILES);
	/*
array
  'file' => 
    array
		// 文件名
      'name' => string '2.png' (length=5)   
	  // 文件类型
      'type' => string 'image/png' (length=9)  
	  // 缓存文件,上传的图片暂时保存在这的
      'tmp_name' => string 'D:\SQLUI\wamp\tmp\phpB980.tmp' (length=29)
	  // 错误码,详细见上面
      'error' => int 0
	  // 上传文件大小
      'size' => int 88715
	*/
// 第一步: 判断错误码
if($_FILES['file']['error'] > 0) {
	switch($_FILES['file']['error']){
		case '1':
			echo '文件过大';
			break;
		case '2':
			echo '文件超出指定的大小';
			break;
		case '3':
			echo '只有部分文件被上传';
			break;
		case '4':
			echo '文件没有被上传';
			break;
		case '6':
			echo '找不到指定文件夹';
			break;
		case '7':
			echo '文件写入失败';
			break;
		default:
			echo '上传出错<br/>';
	}
}else { // 错误码为0,上传成功
// 第二步: 判断文件是否超出大小
	$MAX_FILE_SIZE = 204800; // 文件最大上传200KB
	if($_FILES['file']['size'] > $MAX_FILE_SIZE) {
		// 上传文件超出了我们最大的限制,退出,并产生提示
		exit('文件超出指定的大小');
	}
// 第三步: 判断文件的mime类型的正确
	$adminImg = array('jpg','png');
	$myImg = explode('.',$_FILES['file']['name']);
	var_dump($myImg);
	/*
array
  0 => string '3' (length=1)
  1 => string 'png' (length=3)
	*/
	/*
		array_pop(): 弹出数组中的最后一个单元(出栈),
		in_array() 检测数组中是否有这一项,参数2包含参数1
	*/
	$lastImg = array_pop($myImg);
	if(!in_array($lastImg,$adminImg)){
		exit('后缀名不符合,需要jpg,png格式');
	}
	// 有时候文件名不对应,用户直接修改文件后缀,导致文件不可用,mime类型也必须做出限制检查
	$allowMime = array("image/jpg","image/png");
	if(!in_array($_FILES['file']['type'],$allowMime)){
		exit('文件格式不对');
	}
// 第四步: 生成指定路径和文件
	/*
		根据当前时间生成随机文件名,本行代码是使用当前时间 + 随机一个0-9的数字组合成文件名,后缀即为前面取到的文件后缀名
	*/
	$path = 'C:\\Users\\a4244\\Desktop\\'; // 指定上传文件夹
	$name = date('Y').date('m').date("d").date('H').date('i').date('s').rand(0,9).'.'.$lastImg;
// 第五步: 判断是否是上传文件
	// is_uploaded_file()函数是专用的函数,来判断目标文件是否是上传文件。
	if(is_uploaded_file($_FILES['file']['tmp_name'])){    
// 第六步 移动文件到指定位置
		// move_uploaded_file()移动上传文件至指定位置,第一个参数为上传文件,第二个参数为我们在前面指定的上传路径和名称 
		if(move_uploaded_file($_FILES['file']['tmp_name'], $path.$name)){
			echo $path.$name;
			echo '上传成功';
		}else {
			echo '上传失败';
		}
	}else {
		echo '不是上传文件';
	}
}
?>

8.3 文件上传进度处理

  • session.upload_progress.enabled 是否启用上传进度报告(默认开启) 1为开启,0为关闭
  • session.upload_progress.cleanup 是否在上传完成后及时删除进度数据(默认开启, 推荐开启)
  • session.upload_progress.prefix[=upload_progress_] 进度数据将存储在_SESSION[session.upload_progress.prefix._POST[session.upload_progress.name]]
  • session.upload_progress.name[=PHP_SESSION_UPLOAD_PROGRESS] 如果_POST[session.upload_progress.name]没有被设置, 则不会报告进度.
  • session.upload_progress.freq[=1%] 更新进度的频率(已经处理的字节数), 也支持百分比表示’%’.
  • session.upload_progress.min_freq[=1.0] 更新进度的时间间隔(秒级)

9. 图像处理

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

var_dump(gd_info());

第一步: 创建画布

$img = imagecreate(500,500);

第二步: 添加颜色

$color = imagecolorallocate(resource $图片资源,int $红,int $绿, int $蓝)

第三步: 将颜色添加到背景进行填充

imagefiledrectangle(resource $图片资源 , int $点1x轴, int $点1y轴 , int $点2x轴 , int $点2y轴 , int $color)

第四步: 画线

imagline(resource $图片资源 , int $点1x轴, int $点1y轴 , int $点2x轴 , int $点2y轴 , int $color)

第四步: 画圆

imagefilledellipse(resource $图片资源 , int $圆心x , int $圆心y , int $圆的宽 , int $圆的高 , int $圆的颜色)

第五步: 保存图片

bool imagejpeg(resource $image [,string $filename])

  • $imagetype = ‘jpeg’;
  • $imagetype = ‘png’;
  • $imagetype = ‘gif’;

第六步: 销毁图片资源

imagedestroy($img);

图像缩放

函数名函数说明
imagecopyresampled重采样拷贝部分图像并调整大小
imagecopyresized拷贝部分图像并调整大小
  • bool imagecopyresampled ( resource $目标图 , resource $来源图 , int $目标开始的x位置 , int $目标开始的y位置 , int $来源开始的x位置 , int $来源开始的y位置 , int $目标图片的宽 , int $目标图片的高, int $来源图片的宽 , int $来源图片的高 )

  • bool imagecopyresized ( resource $目标图 , resource $来源图 , int $目标开始的x位置 , int $目标开始的y位置 , int $来源开始的x位置 , int $来源开始的y位置 , int $目标图片的宽 , int $目标图片的高, int $来源图片的宽 , int $来源图片的高 )

图片缩放和裁剪的方法都是一样的,不同的是拷贝时拷贝的是整张图片还是部份部片。

操作方式说明:
从来源图片的开始点(x,y)起,指定的宽高的大小图片。放至到目标图片的起点(x,y),指定宽高大小的图片中。

图像水印

bool imagecopymerge ( resource $目标图片 , resource $来源图片, int $目标开始的x , int $目标开始的y, int $来源的x , int $来源的y , int $来源的宽 , int $来源的高 , int $透明度)

透明度的值为0-100的整数。imagecopy和imagecopymerge的区别在于一个有透明度,一个没有透明度。

10. 错误处理

一般出现错误都会出现在网页中,但是不想显示在网页中,就必须在php.ini文件中的display_errors这个选项设置1或者true显示在网页中,如果设置false或者0则不会显示,也可以用ini_set方法设置

ini_set(‘display_errors’,0);

错误类型说明
E_ERROR错误,文件直接中断
E_WARNING警告,问题比较严重。但是还会继续向下运行
E_NOTICE提示,有些小问题不会影响到程序。常发生在项目未定义
E_PARSE编译时语法解析错误。解析错误仅仅由分析器产生。
E_ALL所有的错误
E_STRICT启用PHP对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
E_DEPRECATED启用后将会对在未来版本中可能无法正常工作的代码给出警告。
错误类型错误说明
E_CORE_ERROR在PHP初始化启动过程中发生的致命错误。该错误类似E_ERROR,但是是由PHP引擎核心产生的
E_CORE_WARNINGPHP初始化启动过程中发生的警告 (非致命错误) 。类似 E_WARNING,但是是由PHP引擎核心产生的。
E_COMPILE_ERROR致命编译时错误。类似E_ERROR,但是是由Zend脚本引擎产生的。
E_COMPILE_WARNING编译时警告(非致命错误)。类似E_WARNING,但是是由Zend脚本引擎产生的
E_USER_ERROR用户自定义错误
E_USER_WARNING用户自定义警告
E_USER_NOTICE用户自定义提示
E_USER_DEPRECATED用户产少的警告信息。类似E_DEPRECATED,但是是由用户自己在代码中使用PHP函数trigger_error()来产生的。
E_RECOVERABLE_ERROR可被捕捉的致命错误。它表示发生了一个可能非常危险的错误,但是还没有导致PHP引擎处于不稳定的状态。

如果想要把所有的错误类型设置一下

error_reporting = 错误类型

显示所有错误,但是排除提示

error_reporting = E_ALL & ~ E_NOTICE

显示所有错误,但排除提示、兼容性和未来兼容性。可写为:

error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

关闭了所有的错误显示

error_reporting(0);

显示所有错误

error_reporting(E_ALL);

显示所有错误,但不显示提示

error_reporting(E_ALL & ~ E_NOTICE);

10.1 错误记录日志

参数配置项说明
log_errorson/off是否开启日志记录
log_errors_max_len整型,默认1024单行错误最大记录长度
error_logsyslog或者指定路径错误日志记录在什么地方

PHP还为我们专门准备了一个自定义的错误日志函数:

bool error_log ( string $错误消息 [, int $错误消息类型 = 0 [, string $存储目标]] )

这个函数可以把错误信息发送到web服务器的错误日志,或者到一个文件里。

常用的错误消息类型:

错误消息类型说明
0发送至默认的error_log指定位置
1发送到指定的邮件位置
3发送至指定的文件位置

用户自定义错误经常用到的两个函数:

set_error_handler ( callable $回调的错误处理函数)
设置一个用户定义的错误处理函数

trigger_error ( string $error_msg)
产生一个用户级别的 error/warning/notice 信息

10.2 cookie

1. 设置cookie

cookie 常用于识别用户。cookie 是一种服务器留在用户计算机上的小文件。每当同一台计算机通过浏览器请求页面时,这台计算机将会发送 cookie。通过 PHP,您能够创建并取回 cookie 的值。

设置cookie,setcookit()函数用于设置cookie,必须位于html标签之前

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

  • name 必需。规定 cookie 的名称。
  • value 可选。规定 cookie 的值。
  • expire 可选。规定 cookie 的有效期。
  • path 可选。规定 cookie 的服务器路径。
  • domain 可选。规定 cookie 的域名。

对于这个函数,我们一般这么用: setcookie(cookie名,cookie值,cookie有效期),三个就够了

<?php
setcookie("user","Alex Porter",time()+3600);
?>

在发送 cookie 时,cookie 的值会自动进行 URL 编码,在取回时进行自动解码(为防止 URL 编码,请使用 setrawcookie() 取而代之)

2. 取回cookie

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

在下面的实例中,我们取回了名为 “user” 的 cookie 的值,并把它显示在了页面上,创建了名为php的cookie:

// 输出 cookie 值
echo $_COOKIE["user"] ."<br/>";
// 查看所有 cookie
print_r($_COOKIE); // Array (   [pgv_pvi] => 9622684672   [user] => php ) 

3. 删除cookie

当删除 cookie 时,只要使到期日期变更为过去的时间就可以

setcookie("user","",time()-3600);

10.3 Session

PHP session 变量用于存储关于用户会话(session)的信息,或者更改用户会话(session)的设置。Session 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的。

您在计算机上操作某个应用程序时,您打开它,做些更改,然后关闭它。这很像一次对话(Session)。计算机知道您是谁。它清楚您在何时打开和关闭应用程序。然而,在因特网上问题出现了:由于 HTTP 地址无法保持状态,Web 服务器并不知道您是谁以及您做了什么。

PHP session 解决了这个问题,它通过在服务器上存储用户信息以便随后使用(比如用户名称、购买商品等)。然而,会话信息是临时的,在用户离开网站后将被删除。如果您需要永久存储信息,可以把数据存储在数据库中。

Session 的工作机制是:为每个访客创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,或者通过 URL 进行传导。

1. 开启session

session_start(),这个函数没有参数。在php文件的开始使用

注释:session_start() 函数必须位于 html 标签之前:

<?php session_start(); ?>
<html>
	<body>
	</body>
</html>

2. 添加session数据

添加session数据

开启会话之后,那么在接下来的处理中,我们就可以使用 S E S S I O N 变 量 来 存 取 信 息 了 。 我 们 要 知 道 的 是 _SESSION变量来存取信息了。我们要知道的是 SESSION_SESSION变量是个数组。当我们要把信息存入session的时候应该这么写:

<?php
$_SESSION['userName'] = 'wang';
?>

3.读取session数据

读取很简单,就像我们使用数组一样,如下:

$userName = $_SESSION[‘userName’];

当然也可以 $_SESSION[‘userName’] 来用。和数组一样的使用。

4. 销毁session数据

我们可以使用很多种方式来销毁session数据。

a) unset函数

我们通过使用类似

unset($_SESSION[‘XXX’]);

来销毁session中的 XXX 变量。

PS:请不要!请不要!请不要unset( S E S S I O N ) , 会 导 致 后 续 无 法 使 用 _SESSION),会导致后续无法使用 SESSION),使_SESSION这个变量!!!

b) 空数组赋值给session变量

$_SESSION = array();

之前我们说过$ _ SESSOIN变量是个数组,那么空数组赋值的话也是相当于将当前会话的$_SESSION变量中的值销毁。

c) session_destory() 函数

这个函数会销毁当前会话中的全部数据,并结束当前会话。但是不会重置当前会话所关联的全局变量, 也不会重置会话 cookie。

5. 存储 Session 变量

实例

存储和取回 session 变量的正确方法是使用 PHP $_SESSION 变量:

<?php
 session_start();
 // 存储 session 数据
 $_SESSION['views']=100;
 ?>
 
 <html>
 <head>
     <meta charset="utf-8">
     <title>php中文网(php.cn)</title>
 </head>
 <body>
 
 <?php
 // 检索 session 数据
 echo "浏览量:". $_SESSION['views']; // 100
 ?>
 
 </body>
 </html>

11. MySQL

11.1 基本sql语法

  • 启动服务: net start mysql57
  • 登录数据库: mysql -h localhost -P 33060 -u root -p123456
  • 显示数据库: use databases;
  • 创建数据库: create database name;
  • 创建表:
mysql> create table Demo01(
    -> id INT(10) primary key, // 定义主键: 唯一,不为空,和外键关联,查询快
    -> name varchar(10),
    -> sex varchar(6),
    -> primary key(id) // 一个参数就是单字段组建,多个就是多字段组建
    -> );
Query OK, 0 rows affected (0.04 sec)
mysql> create table Demo04(
    -> id int(2) primary key auto_increment,
    // auto_increment: 自动增加
    -> name varchar(30),
    -> sex varchar(5) not null,// not null:这一字段不能为空
    -> waijian1 int(11),
    -> constraint waijian01 foreign key(waijian1) references Demo01(id) // 创建外键语法: <waijian01>: 外键名;<waijian1>: 字段名
    // Demo01: 主表名; id: 主键列
    -> );
Query OK, 0 rows affected (0.04 sec)
  • 查看当前所在的表: select database()
  • 进表: use 表名;
  • 查看表结构: desc 表名;
  • 删除表: drop table 表名;
  • 修改字段数据类型:alter table 表名 modify gender 修改后的类型
  • 修改字段名: alter table 表名 change gender 修改后字段名 修改后类型
  • 删除字段: alter table 表名drop 字段名;
  • 在指定字段后添加数据: alter table 表名 add 添加字段名 字段类型 after 在那个表后添加
  • 在表第一列添加: alter table 表名 add 添加字段名 字段类型 first
  • 表约束
约束条件说明
proimary key唯一,不为空,和外键关联,查询快
foreign key外键约束
not null非空约束
unique唯一性约束
default默认约束,用于设置字段默认值
auto_increment自动增加,从1开始
  • 插入数据: insert into 表名 (name,age,work)values (‘value1’,‘value2’,‘valuen’)
  • 修改数据: update 表名 set name=‘value’ [where id = 2];
  • 删除数据: delete from 表名 where name = value1 [AND id = value2];
  • 查询数据: select name,age from 表名;
  • 统计长度: select count(*) from 表名;

11.2 连接MySQL

11.2.1 注册界面
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="http://localhost/Demo33register.php" method="post">
        <label>
            用户名: 
            <input type="text" name="username">
        </label>
        <br /><br />
        <label>
            密码:
            <input type="text" name="password">
        </label>
        <br /><br />
        <label>
            登录名:
            <input type="text" name="loginname">
        </label>
        <br /><br />
        <input type="submit" value="注册">
    </form>
</body>
</html>
11.2.2 注册php界面
<?php
    // 解决乱码
    header('Content-type: text/html;charset=utf-8');
    // 接受请求,处理请求,完成响应
    $username = $_POST['username'];
    $password = $_POST['password'];
    $loginname = $_POST['loginname'];

    // 处理请求 把客户端的数据往数据库中放
	// 注意: 建立连接时,必须先要在数据库中创建数据库和表与创建字段,然后php操作
    // 第一步建立连接
    $connect = mysql_connect('localhost:33060','root','123456');
    if(!$connect) {
        die('Could not connect: ' .mysql_error());
    }
    // 连接那个数据库
    mysql_select_db('php',$connect);

    // 把客户端的数据往表里面添加
    $sql = "INSERT INTO user(username, password, loginname) 
        values('$username','$password','$loginname')";

    // 通过连接发送sql语句
    if(!mysql_query($sql,$connect)) {
        die('Errot: '.mysql_error);
    }
    // 关闭跟数据库的连接
    mysql_close($connect);
    echo '注册成功';
	// header("Refresh:3;url=login.html");// 3秒后跳转登录界面
?>
11.2.3 登录界面
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <form action="http://localhost/Demo33login.php" method="post">
        <label>
            登录名: 
            <input type="text" name="loginname">
        </label>
        <br />
        <label>
            密码:
            <input type="text" name="password">
        </label>
        <br />
        <input type="submit" value="登录">
    </form>
</body>
</html>
11.2.4 登录php界面
<?php
    // 解决乱码
    header('Content-type:text/html;charset=utf-8');
    // 接受请求, 处理请求,响应数据 
    $loginname = $_POST['loginname'];
    $password = $_POST['password'];

    // 处理请求。 获取到用户名跟密码,到数据库里面进行查询,有没有这条记录
        // 建立数据库连接,跟那个库进行连接,准备sql语句,发送sql语句,等待响应的结果,根据结果进行响应
        $connect = mysql_connect('localhost:33060','root','123456');
        if(!$connect) {
            die('Could not connect: ' .mysql_error());
        }
        // 连接那个数据库
        mysql_select_db('php',$connect);
        
        // sql语句查询数据库中的数据
        $sql = "select loginname,password from user where 
            loginName = '$loginname' and password = '$password'";
        
        // 查询,响应一个结果。返回的结果都在这里
        $result = mysql_query($sql);
        $item = array();
        // 获取结果
        if($row = mysql_fetch_array($result)){
            // 拿数据: $row: 代表一行记录,里面有多列
            $item = array(
                "loginname" => $row['loginname'],
                "password" => $row['password'],
            );
        }
        // 根据结果进行判断
        if(count($item)>0) {
            echo '登录成功';
        }else {
            echo '用户名或者密码错误';
        }
?>

12. cookie

12.1 cookie原理

Cookies就是服务器暂时存放在你的电脑里的资料(.txt格式的文本文件),好让服务器用来辨认你的计算机。当你在浏览网站的时候,Web服务器会先送一小小资料放在你的计算机上,Cookies 会把你在网站上所打的文字或是一些选择都记录下来。当下次你再访问同一个网站,Web服务器会先看看有没有它上次留下的Cookies资料,有的话,就会依据Cookie里的内容来判断使用者,送出特定的网页内容给你。

cookie是http协议定义的规定

cookie是服务器发送到客户端的响应数据:(响应首行,响应头,响应空行,响应体)

cookie大小是4kb,各个浏览器大小不同;当cookie满了,会删除前面的数据

怎么去使用:

服务端:怎么发送cookie (setcookie() 函数用于设置 cookie );

setcookie("user", "Alex Porter", time()+3600); 服务端向客户端设置cookie

客户端:怎么获取cookie

var cookies=document.cookie;

演示:

  • 第一次: 客户端请求服务器
  • 第二次: 服务器响应一个cookie发送到客户端,并保存到客户端,以后每次访问服务器,都会把cookie携带到服务器
  • 第三次: 客户端通过 setcookie(‘username’,‘zhangsan’)把数据绑定到cookie上发送给服务器端,然后响应给客户端
  • 第四次: 客户端访问cookie里面username的值

01.客户端向服务器端发送cookie

<?php // 01.php文件
    // 向客户端发送cookie
    // cookie 输出到客户端,也是以键值对的方式输出到客户端的.
    setcookie('username','zhangsan')// 第一次客户端发送请求,服务器端响应给客户端cookie,这个cookie的值是通过响应头Set-Cookie响应头的值,是设置这个值发送到服务端;客户端拿到set-Cookie之后,会按照http协议的方式去解析,把cookie进行保存下来,接下来用02.php与03.php再次访问服务器,客户端会把cookie里面的数据以Cookie:username=zhangsan请求的方式发送到服务器
?>

02.访问服务器并携带cookie给服务器,然后向客户端输出

<?php // 02.php文件
    // 01.php发送cookie给服务器端,然后服务器给出响应并发送过来cookie
    // 访问服务器端并携带01.php的cookie,响应给客户端,内容在请求头里面
    echo $_COOKIE['username'];
?>
<script>
    // 上面访问服务器,并携带cookie过去,然后服务器端响应cookie给客户端,script刚好获取
    console.log(document.cookie);
</script>

03.访问服务器并携带cookie给服务器,然后向客户端输出

<?php // 03.php文件
    // 01.php发送cookie给服务器端,然后服务器给出响应并发送过来cookie
    // 访问服务器端并携带01.php的cookie,响应给客户端,内容在请求头里面
    echo $_COOKIE['username'];
?>

12.2 cookie生命周期

http协议是基于请求,请求 —》响应,服务器与客户端就会断开,http协议是无状态的,服务器不能记住客户端的状态,cookie它是用来记住用户状态,用来进行多个请求之间的数据共享,cookie是保存在客户端

  • cookie分为三种类型
    • 内存cookie: 服务器给客户端发送cookie,这个cookie保存在客户端浏览器的内存当中,当关闭浏览器,cookie就会消失掉
    • 硬盘cookie: 服务器端给客户端发送一个cookie,这个cookie保存在用户的硬盘上(例如: 历史记录),持久化。关闭电源,重启电脑,这个cookie还在除非卸载浏览器或者清除浏览器历史记录
    • 追杀cookie:把之前写到客户端的cookie给清除

内存cookie演示

新建三个php文件

<?php    // 三个文件都是这代码
    // 发送内存cookie
    setcookie('username','lisi');
?>

启动第一个文件会发现请求头是Set-Cookie: username=lisi,启动第二个,第三个文件会发现: 响应头是Cookie: username=lisi,关闭浏览器cookie就会被销毁,再次打开请求头里面就没有cookie

硬盘cookie

文件一:

<?php
	// 发送硬盘cookie,在硬盘上的存活时间一小时
    setcookie('age',20,time()+3600);
	//setcookie('age',20,time()+60*60*24);// 一天
?>

文件2,3保证在同一服务器下,有无内容都可以访问

设置文件3追杀cookie

<?
    //追杀cookie只是把客户端上面的cookie清除,并不会清除服务器上面的,所以请求服务器,服务器还是会发送cookie过来,只不过客户端不会响应cookie过去
    setcookie('username','',-1);
?>

13. session

13.1 概念

session代表的就是一次会话.会话在我们的现实过程当中有很多,比如和10086打电话,当10086接通时,代表我的会话开始,中间我可能发送多次动作交谈,直至挂断,代表会话结束.整个会话过程当中,我们可能发送多次请求,由多次请求组成一次会话.(一个会话由多次请求组成)

web会话: 当打开网站,访问我的网站时会话开始,在这个网站当中我可能发送多次请求,直至关闭浏览器会话借宿.这整个过程当中我们可以理解成一次会话.http协议是基于请求响应的,无状态的,一次会话当中包含多个请求,每个请求都是相互独立的,会话中的多次请求,需要在请求之间共享数据,所以这时候,我们需要使用到会话

一个网站的会话由多次http请求组成,http请求时无状态的,是基于请求响应的,每个请求都是相互独立的,一次会话范围内要进行数据共享,每个请求都是独立的,就不能进行数据共享

无状态: 请求—>响应 连接就会断开,我要在一个会话范围内进行数据共享,这个时候我们就需要使用session

13.2 使用

服务器获取一个session

session_start() 会话开始

获取到session对象

$_SESSION[] 获取到对象,往里面保存数据

01.php

<?php
    // 用户登录成功
    $username = 'zhangsan';
    // 我要把这个数据保存在会话中

    // 开始一次会话
    session_start();
    // 关联数组
    $_SESSION['username'] = $username;
?>

02.php

<?php
    header('Content-type: text/html;charset=utf-8');
    // 用户可能又来请求整个,我要把这个页面判断用户登录状态
    
    // 去获取zhangsan
    // 开始一次会话
    session_start();
    echo $_SESSION['username']
?>

13.3 原理

当客户端第一次访问服务器,客户端什么都没有携带只是单纯的访问01.php服务器的时候,服务器首先执行session_start();这个方法会到session池里面查找有没有一个session,如果服务器没有session,服务器就会创建session,把session放在session池当中,然后以关联数组的形式去存放sessionID作为key,session作为值进行存储,然后生成sessionID给cookie响应给客户端Set-Cookie: PHPSESSID=r48q7gfav4vp18e51q8ou1p8p3; path=/,第二次请求,cookie会携带sessionID(PHPSESSID=r48q7gfav4vp18e51q8ou1p8p3; path=/)响应给服务端,02.php服务端会获取到客户端cookie里面的sessionID,根据sessionID从session池当中获取session,获取到之后给$_SESSION的变量赋值,这个时候我们就可以从session中拿数据

开始会话

web会话并不是浏览器开始访问一个网站会话就开始.而是服务器运行session_start()创建了session,然后向客户端响应一个cookie,cookie里面保存了sessionId,这个时候会话开始

第二次客户端访问服务器,服务器通过session_start()找到session池中的session,从客户端发送过来的cookie中的sessionID在session池中找到会话

session池: 存储在服务器的内存当中,它有一个生命周期,php当中默认是1440秒,也就是24分钟; 但是在24分钟内重新访问一下就会重新刷新时间(心跳)

结束会话

  • 服务器端的session超时
  • 清除浏览器历史记录
  • 清理cookie

14. Ajax

14.1 Ajax介绍与应用

同步交互: 客户端给服务器端发送请求,服务器端给客户端一个响应,响应回来的数据会把客户端界面给覆盖,我们把这种交互叫做同步交互

异步交互: 客户端给服务器发送一个请求,服务器端给客户端响应一个数据,响应回来的数据不会把原来的客户端界面给覆盖

原理: 浏览器给我们提供一个js对象,这个对象XMLHttpRequest,通过这个对象我们可以去发送请求,接收请求处理请求

例如: 当点击一个按钮,触发一个事件,然后通过调用send()方法区发送请求.服务器返回数据给XMLHttpRequest对象.XMLHttpRequest对象拿到数据之后,直接将数据通过DOM放在页面上,从而达到页面不刷新就可以与服务器交互

演示:

php文件: Ajax.php

<?php
    header('Content-type: text/html;charset=utf-8');
    echo '服务器端响应数据';
?>

AjaxGet.html

<input type="submit" value="发送请求">
<span></span>
<script type="text/javascript">
    document.querySelector('input').onclick = function(){
        // 利用XMLHttpRequest对象进行交互
        const xhr = new XMLHttpRequest();
        // 打开链接
        xhr.open('get','http://localhost/Ajax.php?username=zhangsan');
        // 发送数据
        xhr.send();
        // 接收数据: 通过异步的方式,就是只能通过回调函数的方式
        // 监听这服务器端状态的改变
        xhr.onload = function() {
            // xhr.readyState: Ajax状态: 0,1,2,3,4(响应完成)
            // xhr.status: Http状态,200
            if(xhr.status == 200 && xhr.readyState == 4) {
                const span = document.getElementsByTagName('span')[0];
                // 接收服务器返回的数据
                var data = xhr.responseText;
                span.innerHTML = data;
            }
        }
        /*
            xhr.onreadystatechange = function() {

            }
            */
    };
</script>

AjaxPost.Ajax

<input type="submit" value="发送请求">
<span></span>
<script type="text/javascript">
    document.querySelector('input').onclick = function(){
        // 利用XMLHttpRequest对象进行交互
        const xhr = new XMLHttpRequest();
        // 打开链接
        xhr.open('post','http://localhost/Ajax.php');
        // post提交要发送特殊的请求头到服务器
        xhr.setRequestHeader('Content-type:application/x-www-form-urlencoded');
        // 发送数据
        xhr.send('username=zhangsan');
        // 接收数据: 通过异步的方式,就是只能通过回调函数的方式
        // 监听这服务器端状态的改变
        xhr.onload = function() {
            // xhr.readyState: Ajax状态: 0,1,2,3,4(响应完成)
            // xhr.status: Http状态,200
            if(xhr.status == 200 && xhr.readyState == 4) {
                const span = document.getElementsByTagName('span')[0];
                // 接收服务器返回的数据
                var data = xhr.responseText;
                span.innerHTML = data;
            }
        }
        /*
            xhr.onreadystatechange = function() {

            }
            */
    };
</script>

14.2 XML格式

XML是一种标记语言,很类似HTML,其宗旨就是用来传递数据,具有自我描述性(固定格式的数据).一般是软件配置文件

  1. 必须有一个根元素<?xml version="1.0" encoding="utf-8">
  2. 标签不可有空格,不可以数字或开头,大小写敏感
  3. 标签不可交叉嵌套
  4. 标签属性双引号(浏览器自动修正双引号)
  5. 特殊符号要使用实体
  6. 注释和HTML一样

案例:

xml.txt

<?xml version="1.0" encoding="utf-8">
<users>
    <user>
        <id>1</id>
        <username>张三</usename>
        <adress>中国江西</adress>
        <loginName>我是登录名</loginName>
        <password>123456</password>
    </user>
	<user>
        <id>2</id>
        <username>李四</usename>
        <adress>美国旧金山</adress>
        <loginName>我是登录名</loginName>
        <password>987654</password>
    </user>
</users>

xml.html

<input type="submit" value="发送请求">
<span></span>
<script type="text/javascript">
    document.querySelector('input').onclick = function(){
        const xhr = new XMLHttpRequest();
        xhr.open('get','http://localhost/xml.php');
        xhr.send();
        xhr.onload = function() {
            if(xhr.status == 200 && xhr.readyState == 4) {
                const span = document.getElementsByTagName('span')[0];
                var dom xhr.responseXML; // 得到的就是document对象: #document
                span.innerHTML = dom.querySelectorAll('user")[0].querySelector('username').innerHTML;// 张三
            }
        }
    };
</script>

xml.php

header('Content-type:text/html;charset=utf-8');
// 把user.txt文件内容读取出来
$data = file_file_get_contents('xml.txt');
// 响应给客户端
echo $data;

14.3 JSON格式

JSON(JavaScript Object Notation),它是一种轻量级的文本数据交换格式,独立于语言

  • json的数据格式是键值对形式存在的
  • 多条数据以逗号隔开
  • 花括号保存对象,方括号保存数组
  • 使用双引号

php将关联数组转为json数据格式: json_encode(); 需要设置响应头为: text/json

JavaScript可以解析JSON的字符串: eval() 或者 JSON.parse()

//设置data是JSON的字符串格式
	// eval()方法
	eval("("+data+")");
    JSON.parse(data); 

15 跨域

浏览器会拦截跨域,但是服务器与服务器可以跨域

15.1 jsonp跨域

360搜素的智能提示

<div id="app">
	<input type="text" autofocus>
	<ul></ul>
</div>

<script type="text/html" id="tp1">
	<%for(let i = 0; i < obj.result.length; i++){%>
		<li><%=obj.result[i].word%></li>
	<%}%>
</script>
<script type="text/javascript">
function suggest_so(obj){
	html = template('tp1',{obj});
	const ul = document.getElementsByTagName('ul')[0];
	ul.innerHTML = html;
}
(function(){
	// 当input内容变化就会触发
	document.getElementsByTagName('input')[0].oninput = function() {
	const script = document.createElement('script');
	script.src=`https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=${this.value}&huid=11LyPV%2F40quxRkUykFdCqNwbOzOgMoUO7So0sL8w0LsRc%3D&llbq=A5%2CB5%2CC5%2CD5`;
	document.body.appendChild(script);

};
})();

模拟服务器处理suggest_so(),这个名字可以自定义

const express = require('express');
const server = express();
const path = require('path');
// 静态资源访问服务功能
server.use(express.static(path.join(__dirname,'public')))

server.get('/jd',(req,res) => {
    // 取到客户端getInfo请求的参数
    const getInfo = req.query.callback;
    // 向客户端输出: getInfo("我是京东首页")
    res.send(`${getInfo}("我是京东首页")`);
})
server.listen(3000);

jsonp的跨域,它只支持get方式请求,因为它是使用script标签去发送请求,而且服务端需要做处理,客户端也需要做处理.如果跨域的时候传递的数据非常多,jsonp的方式就不太可取

15.2 cors跨域

如果使用XMLHttpRequest有跨域限制,浏览器的数据接收不了,让服务器给客户端一个响应头Access-Control-Allow-Origin:https://www.jd.com,https://taobao.com,可以把后面的地址换成*,会变成所有的网站都可以

跨域资源共享,它的原理就是在请求服务器的时候,服务器给一个响应头,告诉客户端,这些数据可以访问

通过向客户端输出一个响应头
header("Axxess-Control-Allow-Origin:*"); // 跨域资源共享

这种方式是服务器直接给一个响应头Access-Control-Allow-Origin,告诉客户端浏览器,这些数据可以获取,这个Access-Control-Allow-Origin也是http协议规定的

15.3 jsonp与cors的区别

jsonp是最早的这种跨域解决方案,因为是使用script标签发送请求,所以兼容性比较好,但是只支持get方式

cors是后期的一种解决方案,它只需要改服务器的配置,设置一个响应;客户端不需要做任何处理.

其他方法: 通过后台服务器转发,通过设置代理服务器

16 前后端分离

如果前后端分离,服务端对外提供的都是json格式数据,都是提供的借口哦,提供的接口占用端口对外提供服务,就会存在接口安全问题,谁都可调用接口

解决接口安全问题: 对接口进行认证

- session认证
d>123456</password>
 </user>
	<user>
        <id>2</id>
        <username>李四</usename>
        <adress>美国旧金山</adress>
        <loginName>我是登录名</loginName>
        <password>987654</password>
    </user>
</users>

xml.html

<input type="submit" value="发送请求">
<span></span>
<script type="text/javascript">
    document.querySelector('input').onclick = function(){
        const xhr = new XMLHttpRequest();
        xhr.open('get','http://localhost/xml.php');
        xhr.send();
        xhr.onload = function() {
            if(xhr.status == 200 && xhr.readyState == 4) {
                const span = document.getElementsByTagName('span')[0];
                var dom xhr.responseXML; // 得到的就是document对象: #document
                span.innerHTML = dom.querySelectorAll('user")[0].querySelector('username').innerHTML;// 张三
            }
        }
    };
</script>

xml.php

header('Content-type:text/html;charset=utf-8');
// 把user.txt文件内容读取出来
$data = file_file_get_contents('xml.txt');
// 响应给客户端
echo $data;

14.3 JSON格式

JSON(JavaScript Object Notation),它是一种轻量级的文本数据交换格式,独立于语言

  • json的数据格式是键值对形式存在的
  • 多条数据以逗号隔开
  • 花括号保存对象,方括号保存数组
  • 使用双引号

php将关联数组转为json数据格式: json_encode(); 需要设置响应头为: text/json

JavaScript可以解析JSON的字符串: eval() 或者 JSON.parse()

//设置data是JSON的字符串格式
	// eval()方法
	eval("("+data+")");
    JSON.parse(data); 

15 跨域

浏览器会拦截跨域,但是服务器与服务器可以跨域

15.1 jsonp跨域

360搜素的智能提示

<div id="app">
	<input type="text" autofocus>
	<ul></ul>
</div>

<script type="text/html" id="tp1">
	<%for(let i = 0; i < obj.result.length; i++){%>
		<li><%=obj.result[i].word%></li>
	<%}%>
</script>
<script type="text/javascript">
function suggest_so(obj){
	html = template('tp1',{obj});
	const ul = document.getElementsByTagName('ul')[0];
	ul.innerHTML = html;
}
(function(){
	// 当input内容变化就会触发
	document.getElementsByTagName('input')[0].oninput = function() {
	const script = document.createElement('script');
	script.src=`https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word=${this.value}&huid=11LyPV%2F40quxRkUykFdCqNwbOzOgMoUO7So0sL8w0LsRc%3D&llbq=A5%2CB5%2CC5%2CD5`;
	document.body.appendChild(script);

};
})();

模拟服务器处理suggest_so(),这个名字可以自定义

const express = require('express');
const server = express();
const path = require('path');
// 静态资源访问服务功能
server.use(express.static(path.join(__dirname,'public')))

server.get('/jd',(req,res) => {
    // 取到客户端getInfo请求的参数
    const getInfo = req.query.callback;
    // 向客户端输出: getInfo("我是京东首页")
    res.send(`${getInfo}("我是京东首页")`);
})
server.listen(3000);

jsonp的跨域,它只支持get方式请求,因为它是使用script标签去发送请求,而且服务端需要做处理,客户端也需要做处理.如果跨域的时候传递的数据非常多,jsonp的方式就不太可取

15.2 cors跨域

如果使用XMLHttpRequest有跨域限制,浏览器的数据接收不了,让服务器给客户端一个响应头Access-Control-Allow-Origin:https://www.jd.com,https://taobao.com,可以把后面的地址换成*,会变成所有的网站都可以

跨域资源共享,它的原理就是在请求服务器的时候,服务器给一个响应头,告诉客户端,这些数据可以访问

通过向客户端输出一个响应头
header("Axxess-Control-Allow-Origin:*"); // 跨域资源共享

这种方式是服务器直接给一个响应头Access-Control-Allow-Origin,告诉客户端浏览器,这些数据可以获取,这个Access-Control-Allow-Origin也是http协议规定的

15.3 jsonp与cors的区别

jsonp是最早的这种跨域解决方案,因为是使用script标签发送请求,所以兼容性比较好,但是只支持get方式

cors是后期的一种解决方案,它只需要改服务器的配置,设置一个响应;客户端不需要做任何处理.

其他方法: 通过后台服务器转发,通过设置代理服务器

16 前后端分离

如果前后端分离,服务端对外提供的都是json格式数据,都是提供的借口哦,提供的接口占用端口对外提供服务,就会存在接口安全问题,谁都可调用接口

解决接口安全问题: 对接口进行认证

  • session认证
  • token认证(令牌)
在Java,泛型是一种强类型机制,它可以让你在编译时检查类型错误,从而提高代码的安全性和可读性。在使用泛型时,我们经常会遇到父类和子类的泛型转换问题。 首先,我们需要明确一点:子类泛型不能转换成父类泛型。这是因为Java的泛型是不协变的。例如,如果有一个类A和它的子类B,那么List<A>和List<B>之间是不存在继承关系的。 下面我们来看一个例子: ```java public class Animal { //... } public class Dog extends Animal { //... } public class Test { public static void main(String[] args) { List<Animal> list1 = new ArrayList<>(); List<Dog> list2 = new ArrayList<>(); list1 = list2; // 编译错误 } } ``` 在这个例子,我们定义了Animal类和它的子类Dog。然后我们定义了两个List,分别是List<Animal>和List<Dog>。如果将List<Dog>赋值给List<Animal>,会出现编译错误。这是因为List<Animal>和List<Dog>之间不存在继承关系。 那么,如果我们想要让子类泛型转换成父类泛型,应该怎么办呢?这时我们可以使用通配符来解决问题。通配符可以表示任意类型,包括父类和子类。例如,我们可以将List<Dog>赋值给List<? extends Animal>,这样就可以实现子类泛型转换成父类泛型了。 下面我们来看一个使用通配符的例子: ```java public class Animal { //... } public class Dog extends Animal { //... } public class Test { public static void main(String[] args) { List<Animal> list1 = new ArrayList<>(); List<Dog> list2 = new ArrayList<>(); list1 = list2; // 编译错误 List<? extends Animal> list3 = new ArrayList<>(); list3 = list2; // 正确 } } ``` 在这个例子,我们定义了List<? extends Animal>来表示任意继承自Animal的类型。然后我们将List<Dog>赋值给List<? extends Animal>,这样就可以实现子类泛型转换成父类泛型了。 总结一下,Java的泛型是不协变的,子类泛型不能转换成父类泛型。如果需要实现子类泛型转换成父类泛型,可以使用通配符来解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值