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
GLOBALS[‘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语言中声明字符串有三种方式:
-
用单引号声明
-
用双引号声明
-
用字界符声明(需要输入非常大段的字符串时使用)
<?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)类型:
-
通过变量赋值明确指定为变量的值为NULL
-
一个变量没有给任何值
-
使用函数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的区别:
- const是一个语言结构;而define是一个函数,可以通过第三个参数来指定是否区分大小写。true表示大小写不敏感,默认为false, 例子:define(‘PI’, 3.14, true);
- const简单易读,编译时要比define快很多。
- const可在类中使用,用于类成员常量定义,定义后不可修改;define不能在类中使用,可用于全局变量
- const是在编译时定义,因此必须处于最顶端的作用区域,不能在函数,循环及if条件中定义;而define是函数,也就是能调用函数的地方都可以定义
- const只能用普通的常量名,define常量名中可以有表达式
- const定义的常量只能是静态常量,define可以是任意表达式
- 此外,系统还为我们准备了一些内置的常量。这些常量都是规定好的
常量与变量的区别:
- $ :常量前面没有($)
- define: 常量只能用define()函数定义,而不能通过赋值语句
- 作用域: 常量可以不用理会变量的作用域而在任何地方定义和访问
- 重定义: 常量一旦定义就不能被重新定义或者取消定义
- 标量类型:常量的值只能是标量
- 命名空间:常量和(全局)变量在不同的名字空间中
常量名 | 说明 |
---|---|
_ LINE_ | 当前所在的行 |
_ FILE_ | 当前文件在服务器的路径 |
_ FUNCTIOIN_ | 当前函数名 |
_ CLASS_ | 当前类名 |
METHOD | 当前成员方法名 |
PHP_OS | PHP运行的操作系统 |
PHP_VERSION | 当前PHP的版本 |
TRAIT | Trait 的名字,php5.4新加 |
DIR | 文件所在的目录 |
NAMESPACE | 当前命名空间的名称(区分大小写) |
M_PI | 圆周率常值 |
FALSE | false |
TRUE | true |
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; // 鼠标
?>
上面的过程说明:shu前再加上一个$(美元符号),可以理解成为以下的变形过程:
$$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 | 逻辑与(并且关系) | y 为真则返回真 |
$x && $y | 同上 | 同上 |
$x or $y | 逻辑或 | 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 & $b | And(按位与) | 将把 $a 和 $b 中都为 1 的位设为 1。 |
$a | $b | Or(按位或) | 将把 $a 和 $b 中任何一个为 1 的位设为 1。 |
$a ^ $b | Xor(按位异或) | 将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。 |
~ $a | Not(按位取反) | 将 $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[‘变量名’] 。所有的变量都放到了GLOBALS也是全局的
将函数体内的变量(局部变量)在函数外部使用。也可以让函数外的变量到函数里面来使用
- 通过$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
?>
变量引用有讲述,是指变量b指向到了同一个存储位置,来存值。而函数的参数引用,也是这个意思,将形参和实参指向到同一个位置。如果形参在函数体内发生变化,那么实参的值也发生变化。我们来通过实验来看看:
<?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 year [, 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(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以外的所有字符 |
\w | a-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 级别的错误信息。如果文件不存在则尝试创建 |
其他注意事项:
模式 | 说明 |
---|---|
t | windows下将\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_uploads | on为 开启文件上传功能,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_WARNING | PHP初始化启动过程中发生的警告 (非致命错误) 。类似 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_errors | on/off | 是否开启日志记录 |
log_errors_max_len | 整型,默认1024 | 单行错误最大记录长度 |
error_log | syslog或者指定路径 | 错误日志记录在什么地方 |
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数据
开启会话之后,那么在接下来的处理中,我们就可以使用_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(_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,其宗旨就是用来传递数据,具有自我描述性(固定格式的数据).一般是软件配置文件
- 必须有一个根元素
<?xml version="1.0" encoding="utf-8">
- 标签不可有空格,不可以数字或开头,大小写敏感
- 标签不可交叉嵌套
- 标签属性双引号(浏览器自动修正双引号)
- 特殊符号要使用实体
- 注释和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认证(令牌)
上一篇: Yii url重写自定义url显示样式
下一篇: 用PHP编程开发“虚拟域名”系统