/
2021/11/14 21:28
*/
PHP一种动态网站开发的脚本语言,弱类型语言
PHP_代码标记
ASP标记:<% php代码 %>
段标记:<? php 代码 ?>
脚本标记:<script language=”php”>php 代码</script>
标准标记(常用的):<?php 代码 ?>
PHP_注释
单行注释:// 和 #//这是一个单行注释
块注释:/ /
/*
*@作者:xxx
*@日期:xx:xx
*@计算俩个数的大小
*/
PHP_语句结束符
每一个PHP语句结束,都会和C、java等大多数语言一样,结尾会有分号“;”,来表示一行代码的结束echo"hello world";
但是一段PHP代码中的结束标记隐含表示了一个分号,所以在PHP代码的最后一行可以不用分号结束。echo"hello world";
echo"这是最后一个语句"?>
PHP_变量
变量来源于数学,是计算机语言中能存储计算结果或表示值的抽象概念,变量通过变量名访问,顾名思义 变量是可以变量的
PHP所有变量都必须使用 $ 符号
- 在系统中增加对应的变量名字(内存)
- 赋值:可以将数据赋值给变量名(在定义的同时完成)
- 通过变量名访问存储在内存中的数据
同时输出多个变量,之间用逗号分隔开
- 可以将变量从内存中删除
变量命名规则
- 在PHP中变量名必须以 $ 符号开始:
- 名字由大小写字母,数字,下划线构成,但是不能以数字开头
- PHP本身允许中文变量名,但不建议
预定义变量
预定义变量就是系统提前定义的变量,存储许多需要用到的数据(预定义变量都是数组)$_GET
: 获取所有表单以get方式提交的数据$_POST
:POST提交的数据都会保存在此$_REQUEST
:GET和POST提交的都会保存在这$GLOBALS
: PHP中所有的全局变量$_SERVER
: 服务器信息$_SESSION
: Session会话数据$_COOKIE
: Cookie会话数据$_ENV
: 环境信息$_FILES
: 用户上传的文件信息
可变变量
如果一个变量保存的值刚好是另一个变量的名字,那么可以直接通过访问一个变量得到另一个变量的值,在变量前面在多加一个$
符号
变量传值
将变量赋值给另一个变量叫做 变量传值
变量传值由俩种方式:
- 值传递
- 引用传递
值传递
:将变量a保存的值复制一份给变量b保存(俩个变量除了存得值相同没有任何关系)引用传递
:将变量a所存的值所在的内存地址,赋值给变量b,这样俩个变量都指向同一块内存空间的同一个值,一个改变了,另一个也会改变
PHP_常量
常量和变量一样,都是用来保存数据的
常量:const/constant,是一种在程序运行的时候,不可改变的量(数据)
常量一旦定义,通常数据不可改变(用户级别)
常量定义方式
- 使用
define
函数:
2. 使用const
关键字(PHP5.3之后版本)
//const PHP5.3以后关键字const eat ="吃炸鸡";
echo eat;
常量命名规范
- 常量不需要 $ 符号,如果使用系统会认为是变量
2. 常量的名字由大小写字母,数字和下划线组成,不能是数字开头
3. 常量的名字通常以大写字母为主(命名规范,用于区分变量)
4. 还可以使用define函数创建特殊常量
define和const定义的常量有区别,在于访问权限区别
定义常量通常不区分大小写,也可以区分,参考define函数的第三个参数
常量访问方式
常量的访问和变量大致相同
但是针对define
定义的特殊变量,要用特别的方法,constant()
系统常量
系统帮助用户定义的常量,用户可以直接使用
常用的系统常量:PHP_VERSION
: PHP的版本号PHP_INT_SIZE
: 整形能表示的大小(字节)PHP_INT_MAX
: 整形能表示的最大值
在PHP中还有一些特殊的系统常量,是双下划线开始的,双下划线结束,称之为魔术常量
魔术常量的值会随着环境变化而变化,但是用户改变不了
__DIR__:
当前被执行的脚本在电脑中的绝对路径__FILE__
:当前被执行的脚本在电脑中的绝对路径(包含本身文件的名字)__LINE__
:当前函数所在的脚本的行数__NAMESPACE__
:当前所属的命名空间__CLASS__
: 当前所属的类__METHOD__
:当前所属的方法
数据类型
PHP是一种弱类型的语言,变量本身没有数据类型,指的是数据本身的类型,而不是变量的类型,你给什么样的数据,变量就是什么样的类型
基本类型:
l 整型:int/integer
,系统分配四个字节存储,表示整数类型
l 浮点型:float/double
,系统分配八个字节存储,表示小数或者整型存不下的整数
l 字符串:string
,系统根据实际长度分配,表示字符串(引号引起来)
l 布尔类型:bool/boolean
,表示布尔类型
复合类型:
l 对象类型:object
,存放对象(面向对象)
l 数组类型:array
,存储多个数据的集合(一次性)
特殊数据类型:
l 资源类型:resource
,存放资源数据(PHP外部数据,如数据库,文件)
l 空类型:NULL
,只有一个值就是NULL(不能运算)
数据类转换
在很多条件下,需要指定的数据类型,需要外部数据(当前PHP取到的数据)转换成目标数据类型
有俩种类型转换方式:
- 自动转换:系统根据需求自己判定,自己转换(用的比较多,但是效率不高)
- 手动强制转换:根据需要的目标类型转换
$num1 = 54;
$str=(string)$num;
转换过程种,用的比较多的就是转布尔类型(用于判断)和转数值类型(算术运算)
其他类型转数值
- 布尔true为1,false为0
- 字符串转数值有自己的规则
- 字母开头的字符串,永远都是0
- 以数字开头的字符串,取到字符串之前(不会同时包含俩个小数点)
类型判断
通过一组类型来判断变量名的数据类型is_XXX(变量名)
:is就是是不是的意思,如果外面XXX(类型)与变量名的类型一致就返回True,否则返回False。 echo不能输出boolean类型的值,用到var_dump()
还有一组函数可以用来获取以及设定变量的类型:Gettype(变量名)
:获取类型,得到的是 该类型对象的字符串settype(变量名)
:改变数据的类型,和强制转换不同,这个会影响这个数据本身的类型:整数类型进制转换十进制
:逢10进1,只能出现0-9二进制
:逢2进1,只能出现0-1八进制
:逢8进1,只能出现0-7
十六进制:逢16进1,只能出现0-9,a-f,a代表10
浮点类型
小数类型以及超过整型能存储范围的整数(不保证精度,大概在15个有效数字左右s)PHP_INT_MAX +1
超过整型存储的大小后,会自动转化为浮点型
为什么浮点数同样的字节存储数据,但是能表示更大的数据呢?
00000000 00000000 00000000 00000000
11111111 11111111 11111111 11111111(整形最大值,所有位都是有效数据)
11111111 11111111 11111111 11111111(红色7位表示10的指数,后面三个字节存储表示具体数值)
尽量不要用浮点数做精确判断,浮点数保存的数据不够精确,而且在计算机中凡是小数基本上存得都不准确
布尔类型
俩个值:true
和false
,用于判断比较empty()
:用于判断变量的值是否位空,NULL不是空isset()
:用于判断变量的值是否存在
PHP_运算符
是一种将数据进行运算的特殊符号,在PHP中一共有十多种运算符
赋值运算符:
符号是=
,表示将右边的结果,保存到内存的某个位置,将位置的内存地址赋值给左侧的变量(常量)
算数运算符:+
、-
、*
、/
、%
、++
、--
比较运算符:
比较俩个数据的大小,或者俩个内容是否相同>
:左边大于右边,返回true,反之false>=
:左边大于或等于右边,返回true,反之false<
: 左边小于右边,,返回true,反之false<=
:左边小于或等于右边,返回true,反之false==
:左边的值等于右边,返回true,反之false!=
: 左边的值不等于右边,返回true,反之false===
:精确等于,左边的值完全等于右边(值大小和类型),返回true,反之false!==
:不精确等于,左边的值不完全等于右边(值的大小和类型),返回true,反之false
逻辑运算符:&&
:逻辑与,左边的条件同时成立时,返回true,反之false||
: 逻辑或,左边的条件有满足大于等于一个返回就true,反之false!
:逻辑非:对已有的条件取反,true取false,false取true
我们将逻辑与和逻辑或称之为短路运算,如果左边条件能决定整个式子的布尔型的时候,不用判断右边的条件
链接运算符:
是PHP中将多个字符串拼接的一种符号.
:将俩个字符串连接到一起.=
:复合运算,将左边的内容与右边的内容连接起来,然后重新赋值给左边变量
错误抑制符:
在PHP中有一些错误可以提前预知,但是这些错误可能无法避免,但是又不希望报错给用户看到,可以使用错误抑制符@
:在可能出现报错的语句前加上@错误抑制符
错误抑制符通常在生产环境(上线)时用到
三目运算符:
表达式1?表达式2:表达3
如果表达式1为真 执行表达式2否则执行表达式3
复合三目:表达式1 ? ( 表达式2 ? 表达式3 : 表达式4 ):( 表达式5? 表达式6: 表达式7)
自操作运算符:
顾名思义就是自己操作自己++
就是自加1,--
就是自减1;可以用作计数或者有规律改变的时候
例如:
但是自加(自减)操作符分前置和后置:
前置或者后置如果本身只有自操作,不参与其他运算,那么效果是一样的,但如果自操作同时还参与别的运算,那么效果就不一样
- l 前置
++$a;
先在原来的数上自加1,然后将改变后的数据,返回给操作的表达式
- l 后置
$a++;
先将自己的值复制一遍,然后自加1,将改变前的数据返回给操作的表达式
衍生符号,类似自操作:+=
:左边的结果与右边的结果相加,然后赋值给左边-=
: 左边的结果减去右边的结果,然后赋值给左边*=
:同上/=
: 同上%=
:同上
计算机码
计算机在实际存储数据的时候,采用的编码规则(二进制规则)
分别由原码
、反码
、补码
,
数据有正负之分,数据本身最左边一位充当符号位,正数为0,负数为1
- 原码:数据本身从十进制转换为二进制得到的结果
- 正数:左边符号位为0
- 负数:左边符号位为1
- 反码:针对负数,符号位不变,其他位取反
- 补码:针对负数,反码+1
正数的补码和反码都是自己本身
系统中存在俩个0,-0 +0+0
:00000000-0
:10000000 原码11111111
反码 00000000
补码 (反码+1=1 00000000 砍掉前面)
位运算符
对一个数据取出计算机最小的单位(位bit)进行位位运算
&:按位与,俩个位都为1结果为1,否则为0
//机器码
$a=5;
$b=-5;
/*
5的源码 00000101
-5的源码 10000101
取反: 11111010 //反码:符号位不变,其他位取反
补码: 11111011 //补码:反码+1
*/
//按位与
var_dump($a & $b); //所以结果应该是1
/
取出系统存储的结果进行与操作(存的是补码)
5 00000101
-5 11111011
& 00000001 //此时是最终结果还需要转换
转换:判断符号位,0为正数(此时存得就是源码),1为负数(负数此时存得就是补码)
不需要转换—》00000001=1
/
|
:按位或,俩个位有一个位1,结果为1
//按位或
var_dump($a | $b); //结果是-1
/
取出系统存储的结果进行与操作(存的是补码)
5 00000101
-5 11111011
| 11111111 //此时是最终结果还需要转换
符号位1,负数
转换 11111110—10000001=-1
/
~
:按位非,一个位如果本来是1就变成0,否则反之
//按位非
var_dump(~$b); //结果是4
/*
-5 11111011
~ 00000100
符号位0,正数
转换 00000100=4
*/
^
: 按位异或,俩个相同则为0,不同则为1
//按位异或
var_dump($a^$b); //结果是-2
/
-5 11111011 //补码
5 00000101
^ 11111110 //相同为0 不同为1
符号为1,负数
转换 11111101—10000010=-2
/
<<
:按位左移,整个位,向左移一个单位,右边补0
//按位左移和右移
var_dump($b<<1); //结果应该为-10
/
-5 11111011 //补码
<< 11110110 //右边补0
符号位为1,负数
转换 11110101—10001010=-10
/
>>
:按位右移,整个位,向右移一个单位,左边补符号位内容(正数0.符数1)
var_dump($b>>1); //结果应该为-3
/
-5 11111011 //补码
>> 11111101 //正数左边补0,负数补1
符号位为1,负数
转换 11111100—1000011==-3
/
注意:
通过上面的操作似乎发现了一些规律
按位左移:是乘以2的操作
按位右移:是除以2的操作,但也不完全正确,奇数除以2会出现小数
@亲测C、Python、Java 都支持按位运算,结果也一样
运算符优先级
下表按照优先级从高到低列出了运算符。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。
运算符优先级(从高到低) | ||
---|---|---|
结合方向 | 运算符 | 附加信息 |
无 | clone new | clone和 new |
左 | [ | array() |
右 | ** | 算术运算符 |
右 | ++—~(int)(float)(string)(array)(object)(bool)@ | 类型和递增/递减 |
无 | instanceof | 类型 |
右 | ! | 逻辑运算符 |
左 | */% | 算术运算符 |
左 | +-. | 算术运算符和字符串运算符 |
左 | <<>> | 位运算符 |
无 | <<=>>= | 比较运算符 |
无 | ==!====!==<><=> | 比较运算符 |
左 | & | 位运算符和引用 |
左 | ^ | 位运算符 |
左 | | | 位运算符 |
左 | && | 逻辑运算符 |
左 | || | 逻辑运算符 |
左 | ?? | 比较运算符 |
左 | ? : | ternary |
right | =+=-==*=/=.=%=&=|=^=<<=>>= | 赋值运算符 |
左 | and | 逻辑运算符 |
左 | xor | 逻辑运算符 |
左 | or | 逻辑运算符 |
PHP_流程控制
流程控制:代码执行的方向
- l 顺序结构:代码从上往下,顺序执行(代码执行的最基本结构)
- l 分支结构:给定一个条件,同时有多种可执行代码块,然后会根据条件执行某一段代码
- l 循环结构:在某个条件控制范围内,指定的代码块可以重复执行
分支结构:
在PHP中,分支结构主要右俩种:if分支
和switch分支
if分支:
给定一个条件,同时为该条件设置多种情况,根据条件判断来实现具体的代码段
if语句
if(关系表达式){
语句体;
}
//如果表达式为真,执行下面语句体,然后顺序执行
if else语句
if(关系表达式){
语句体;
}else if(表达式2){
语句体2;
}
//如果关系表达式为真,执行语句体,否则并列判断表达式2,为真执行语句体2,然后顺序执行
else语句
if(关系表达式){
语句体;
}else{
语句体2;
}
//如果关系表达式为真,执行语句体,否则执行语句体2,然后顺序执行
switc分支:
通过一个条件,通常有多个值,但是每一个值都会有不同的代码段要执行
Switch语句
switch(表达式){
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
.....
default:
语句体n+1
break;
}
循环结构:
代码段在一定的控制下,可以多次执行
l for循环
:通过条件、起始和终止判断执行
l while循环
:通过判断条件终止
l do….while循环
:和while循环大致相同,执行流程不同而已
l foreach循环
:针对数组的循环,PHP独有
for循环:
循环结构的组成:
#初始化语句:用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
#条件判断语句:反复执行的条件,判断循环是否能一直执行下去
#循环体语句:循环反复执行的内容
#条件控制语句:循环执行中每次变化的内容,用于控制循环是否能继续循环下去
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
这里也用到了前面学的自加操作符的后置,在条件控制语句的最后$ i
还是自加了1
- 执行初始化语句
- 判断条件语句,结果为True继续执行,为false循环结束
- 执行循环体语句
- 执行条件控制语句
- 回到2.继续
for特殊使用:无条件的for循环for(;;){} 这就是死循环
while循环:
初始化语句 ;
while(条件判断语句){
循环体语句;
条件控制语句;
}
利用while循环先写一个案例:
珠穆朗玛峰=8844.43m=8844430 一张纸厚度0.1毫米,需要折叠多少次=珠穆朗玛峰
执行流程:
- 执行初始化语句
- 执行条件判断语句,为真继续执行,为假结束循环
- .执行循环体语句
- 执行条件控制语句
- 回到2.继续
do….while循环:
初始化语句;
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
- 先执行初始化语句
- 执行do里的循环体语句
- 执行do里的条件控制语句
- 执行条件判断语句,为真继续执行2. 为假退出循环
和while的不同在于会先执行一次循环体语句,然后再做判断条件是否为真
循环控制:
在循环内部对循环本身进行控制continue
:在循环中,基于条件控制,跳过某次循环体的执行,继续跳到循环判断处依次执行break
:再循环中,基于条件控制,终止循环体内容的执行,结束当前的整个循环
也就是说continue
只能结束当前次的循环,重新跳到循环开始的条件判断处继续执行break
退出整个循环
流程控制代替语法
流程控制代替语法:分支和循环结构的代替语法
PHP本身是嵌入到HTML中的脚本语言,需要HTML中书写一些关于判断或者循环的结构语法,必须符合PHP标签规范,需要HTML与PHP进行混搭,如果使用原始的PHP代码会非常不美观<br />![1.png](https://cdn.nlark.com/yuque/0/2022/png/25811869/1645338352433-17f9b658-01d4-4340-a0f1-3ae796b080ad.png#clientId=u8aa025bb-6171-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=ub2148d5e&margin=%5Bobject%20Object%5D&name=1.png&originHeight=614&originWidth=892&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21783&status=done&style=none&taskId=u8f76f7c2-9b1a-4f47-bee1-b320a7fbcb6&title=)<br />![2.png](https://cdn.nlark.com/yuque/0/2022/png/25811869/1645338390327-3de1b977-794d-4434-954f-bd95480d5a09.png#clientId=u8aa025bb-6171-4&crop=0&crop=0&crop=1&crop=1&from=drop&height=525&id=uebf5e720&margin=%5Bobject%20Object%5D&name=2.png&originHeight=781&originWidth=905&originalType=binary&ratio=1&rotation=0&showTitle=false&size=51824&status=done&style=none&taskId=u2668f223-c275-4ba0-a8d7-41b6c85ee30&title=&width=608)<br />使用到了PHP、html相互嵌套的方式,在完整的PHP代码段里 ,执行html的代码
<?phpxxxxxxxxxx{?>
<td>
<?phpxxxxxxxxxxx?>
</td>
<?php }?>
不过这样吧PHP这样用大括号{}
写入html不是很好看,所以PHP提供了一种替代机制,让其可以不用书写{}
将大括号的左括号 用 :
代替,在反括号处用end+对于起始标记
代替,使其结构更加明了,后面还会有模板,会更简洁,更方便
PHP_文件包含
在一个PHP脚本中去将另一个文件(PHP)包含进来,去合作完成一件事情
文件包含的作用:
1. 要么使用被包含文件中的内容,实现代码共享(重用,类似Python函数封装):这种是向上包含(索要)
2. 要么自己有的东西可以交给别的文件使用,实现代码共享(重用,类似C函数定义):这种就是向下包含(给予),自己有部分代码需要别的脚本来实现
文件包含的四种形式:
l include
:包含文件
l include_once
:系统回自动判断文件包含过程中,是否已经被包含过(一个文件最多被包含一次)
l require
:与include相同
l require_once
:与include_once相同
包含语法:include “xxxx”;
include(“xxxx”);
<?php
/*
被导入文件
*/
$a="inlcude is nice";
?>
<?php
/**
* 源文件
*/
//导入外部php文件
include"include1.php";
echo $a;
?>
这种包含叫做向上包含,需要调用别的PHP文件来加以执行
/
被导入文件
/
<table>
<tr>
<td>
<?php
echo$a;?>
</td>
<td>
<?php
echo$b?> //最后一条PHP语句可以不加结束符
</td>
</tr>
</table>
/*
源文件
*/
<?php
$a="现在是向下包含文件";
$b="就是数据在本文件,调用在被导入文件中";
//导入外部php文件,调用
include"include1.php";
文件加载
PHP的执行流程:
读取代码文件(PHP)
将PHP代码转换为字节码 (opcode)
zendengine来解析opcode,按照字节码取进行逻辑运算
然后将字节码转换为HTML代码
- 在文件加载的时候,系统会自动将被包含的PHP文件中的代码嵌入到当前加载文件的代码处(include或者require)
2. 在PHP中被包含的文件是单独编译的,如何体现呢
我们都知道,在PHP文件被编译的时候,如果有报错会停止编译和运行,所以让被导入文件报错,可以看到源文件还是执行并输出了 hello world
inculde和require的区别
include和include_once的区别:
n include
编译器遇见一次 执行一次,如果对同一个文件进行多次加载,系统会执行多次
n include_once
:系统碰见多次,也只会执行一次
require和include的区别:
在于文件包含报错的时候:include
要求较低:如果报错也只是提示错误,不影响整个代码的执行(用的较多)require
要求较高:如果报错,那么程序就会停止下来
PHP_文件加载路径
文件在加载的时候需要指定文件路径才能保证PHP正确的找到对于的文件
路径分为绝对路径和相对路径
- 绝对路径:
- 从磁盘的根目录开始(本地绝对路径)
Windows
:盘符/路径/PHP文件Linux
:/路径/PHP文件
从网站根目录开始(网络绝对路径)
/
:相对于网站主机名字对应的路径
loacalhost/php/index.php àD:/phpstudy/PHPxxxx/www/php/index.php
- 相对路径:从当前文件所在目录开始的路径
./
:表示当前文件夹../
:表示上级目录(当前PHP代码所在文件夹的上一次文件夹)
绝对路径 相对于效率偏底,因为从头开始找,但是相对安全(除非自己写错了)
相对路径 相对于效率偏高,但是容易出错(相对路径发生改变)
PHP_文件嵌套包含
一个文件包含了另一个文件,另一个文件里又包含了另一个文件,比如:
A包含B,B包含了C
PHP_函数
函数:function
,是一种语法结构,将实现某一个功能的代码块(),封装到一个结构中,从而实现代码的重复利用
函数定义语法:
有几个关键点,function
关键字,函数名
,参数
(形参和实参),函数体
和返回值
基本语法如下:
function函数名(参数){
函数体
返回值:return
}
实现代码的重复利用,一个功能定义一个函数,要使用函数的话,通过访问函数的名字+()
:
//如果函数在定义的过程中有参数没那么在调用的时候就必须传入对于的参数
函数的参数
定义:function函数名(参数1,参数2,参数3…){}
定义多个参数时,参数之间用逗号隔开
#调用:
函数名(参数);
函数名(变量1/常量1,变量2/常量2);
- 形参:
形式参数,不具有实际意义的参数,时在函数定义时使用的参数
实参:
实际参数,举有实际数据意义的参数,是在函数调用时使用的参数
形参是实参的载体,实在低矮用时通常是需要传入到函数内部参与运算,那么需要在函数内部取找到实际数据所在的位置才能找到数据本身,需要实际调用的时候,将数据以实参的形式传递给实参,给形参赋值,从而使得函数内部可以用到外部的数据
一句话:
实参就是主调方法中的参数或者变量,形参就是被调方法中的参数
//定义函数
functionget($a,$b){ //形参有多个,使用逗号分隔即可
//函数体:可以直接使用形参运算
echo$a+$b;
}
//调用函数
$num=5;
get($num,20);
- 系统调用get函数,取寻找内存中是否有add函数,如果有:
2. 系统会在栈区开辟内存空间运行函数get
3. 系统会查看函数本身是否有形参,有,俩个
4. 系统会判断是否有实参,有,俩个
5. 系统会默认将实参的第一个值给形参的第一个值
6. 执行函数体:运行
7. 返回函数执行(返回值)
注意:
1. 在PHP中允许实际参数多余形参(个数),函数内部不用而已
2. 在PHP中理论上形参个数没有限制(实际开发不会用太多)
3. 实参个数不能少于形参
默认值:
指的是形参的默认值,在函数定义的时候,就给形参进行一个储时赋值,如果实际调用传入的参数(实参)没有提供,那么形参就会使用定义时的值来进入函数内部参与运算
通常默认值是用在一些,一定会有某个形参参与运算,但是可能这会实参没有给到,就和java默认数据类型一样
注意事项:
如果默认值存在,可以不用传入实参
默认值的定义是放在最后的(右边):不能左边形参有默认值,右边没有
引用传递:
基本函数的参数传递:
对于基本数据类型的参数,形式参数的改变,不影响实际原始数据实参的值,只是相当于实参的值赋值给了形参一份,是一种简单的值传递
引用函数传递:
但是有些时候,希望在内部拿到外部的数据,并且更改外部的数据,就需要明确告知函数(定义时),函数才会在调用的时候主动获取外部数据的内存地址,像是变量的引用传递
函数体
在函数内部({}里的)的所有代码是函数体
在函数体内,基本上所有代码都可以实现
1. 定义变量
2. 定义常量
3. 使用流程控制
4. 可以调用其他或本身函数
函数返回值
return
,指的是将函数实现的结果,通过return
关键字,返回给函数外部(函数调用处)
在PHP中所有函数都有返回值(如果没有明确reruen
使用,系统默认返回NULL
)
在函数内部return
代表函数的结束返回,return下的代码不会执行
在PHP文件中,return
代表整个文件的结束
PHP_函数作用域
所谓作用域就是 变量或常量能够被访问的区域
变量可以在普通代码中定义,也可以在函数内部定义
PHP作用域严格来说分俩种:但是PHP内部还定义一些在严格意义外的一种,所以算三种:
全局变量
:就是用户普通定义的变量(在函数外部定义)
所属于全局空间:在PHP种只允许在全局空间使用:理论上函数内部不可用
脚本周期:直到运行到脚本结束,最后一条代码执行完
局部变量
:就是在函数内部定义的变量
所属于当前函数空间:在PHP中只允许在当前函数自己内部使用,别的函数或外部无法调用函数周期
:在栈区,当前函数执行完,就会销毁,
超全局变量
:系统定义的变量(预定义变量:$_SERVER,$_POST
等)
所属超全局空间:没有访问限制
超全局变量会将全局变量自动纳入到$GLOBALS
里面,而$GLOBALS
没有作用限制,所以能够帮助局部区访问全局变量:但是必须使用数组方式
函数内部内部使用外部变量那么除了$GLOBALS
之外,通过参数传值(如果想统一战线还是可以使用引用传值)
在PHP中还有一种方式能够全局访问局部,也可以局部访问全局:通过global
关键字
1. 如果使用global
定义的变量名在外部存在(全局变量),那么系统在函数内部定义的变量直接指向外部全局便利所指的内存空间,某种意义上这俩个变量就是同一个变量了
2. 如果global
定义的变量名在外部不存在(全局变量),系统会自动在全局空间(外部)定义一个于局部变量同名的全局变量global 变量名; //不能赋值
变量名 = 值; //修改
//global关键字测试
<?php
$number=5;
functionadd(){
//global 修饰全局变量
global $number;
$number=10; //给全局遍历赋值
//global定义“局部”变量
global $num;
$num=5;
}
add(); //调用函数
echo"$number</br>$num";
?>
PHP_静态变量
static
,是在函数内部定义的变量,使用static
关键字修饰,用来实现跨函数共享数据的变量:函数运行结束所有局部变量都会清空,如果重新运行一下函数,所有的局部变量又会重新初始化
基本语法
function函数名(){
定义变量
static $变量名 = 值; //通常会在定义的时候就直接赋值
}
?>
静态变量的作用是为了跨函数共享数据(同一个函数被多次调用的时候)
PHP_可变函数
通常来说在PHP里,如果一个变量的值刚好是一个函数的名字,那么我们可以通过$num(参数1....);
来调用函数
可变函数在系统使用的过程中还是比较多的,尤其是使用很多系统函数的时候,需要用户在外部定义一个自定义函数,但是需要转入到系统内部使用
将用户定义的函数传入给另一个函数(函数名)去使用的过程,称之为回调过程,而被传入的函数称之为回调函数
PHP_匿名函数
匿名函数
:没有名字的函数
变量保存匿名函数,本质得到的是一个对象(Closure)
闭包
闭包:closure
,一词来源于以下两种的集合:
1. 要执行的代码块(由于自由变量被包含在代码块中,这些自由变量,以及他们引用的对象没有被释放)
2. 为自由变量提供绑定的计算环境(作用域)
函数内部有一些局部变量(要执行的代码块)在函数执行之后没有被释放,是因为在函数内部还有函数在引用(函数内部的函数à匿名函数)
如何证明函数的局部变量在函数使用完之后没有被是释放?
1. 使用内部匿名函数
2. 匿名函数使用局部变量use
;
3. 匿名函数返回给外部使用
//闭包函数
function display(){
//定义变量:局部变量
$name=__FUNCTION__;
//定义匿名函数
$inter=function() use($name){ //use就是将外部变量(也是局部的)保留给内部使用
//函数内部的函数
echo $name;
};
//返回匿名函数
return $inter;
}
$temp=display();
$temp();
在执行$temp();
语句时,display
函数运行结束了,理论上局部变量$name
应该被释放
主要是为了在特定的情况下 给外部使用内部函数的一种选择
PHP_伪类型
就是假类型,实际上在PHP中不存在的,但是通过伪类型可以帮助程序员更好的查看操作手册从而更方便学习伪类型
主要有俩种:在三大类八小类之外
PHP_常用系统函数
输出函数:
- l
print()
:类似echo
输出提供的内容,本质上是一种结构(不是函数),返回值为1,可以不需要括号 - l
print_r()
:类似于var_dump
,但是比var_dump简单,不会输出数据的类型,只会输出值,一般用于遍历数组的值
时间的函数:
date()
:按照指定格式对象的时间戳(从1970年格林威治时间开始计算的秒数)
如果没有指定时间戳,那么就是默认解释当前时间戳
time()
:获取当前时间对应的时间戳microtime()
:获取微妙级别的时间strtotime()
:按照规定格式的字符串转换为时间戳
有关数学的函数
max()
:指定参数中最大的值min()
:比较俩个数种的最小值rand()
:得到一个随机数,指定区间的随机整数mt_rand()
:与rand一样,只是底层结构不一样,效率会更高round()
:四舍五入ceil()
:向上取整floor()
:向下取整pow()
指定数字的指定次数的结果pow(2,8)==2^8==256
abs()
:绝对值aqrt()
:求平方根
有关函数的函数:
l function_exist()
:判断指定的函数名字是否在内存中存在(帮助用户不去使用一个不存在的函数,让代码安全性更高)
l func_get_arg()
:在自定义函数中获取指定数值对于的参数
l func_get_args()
:在自定义函数中获取所有的参数(数组)
l func_num_args()
:在自定义函数中获取所有参数
PHP_错误处理
系统或者用户对某些代码进行执行的时候,发现有错误,就会通过错误处理的形式告知程序员
错误分类
通常错误分为三类
1. 语法错误:用户书写的代码不符合PHP代码规范,语法错误会导致代码在编译得过程中不通过,所以代码不会执行(parse error)
2. 运行错误:代码编译通过,但是代码在执行的过程中会出现一些条件不满足导致的错误(runtime error)
3. 逻辑错误:开发者在写代码的时候不够规范,出现了一些逻辑性的错误,导致代码正常执行,但是由得不到预想的结果
将赋值运算符当成比较运算符
$a=1;
if($a=0){
//代码块
}
错误代号
所看到的错误代码在PHP中都被定义成了系统常量(可以直接使用)
l 系统错误E_PARSE
:编译错误,代码不会执行E_ERROR
:fatal error
,致命错误,会导致代码不能正确继续执行(出错的位置断掉)E_WARNING
:warning
,警告错误,不会影响代码执行,但是可以会得到意想不到的结果E_NOTICE
:notice
,通知错误,不会影响代码执行
l 用户错误:E_USER_ERROR
,E_USER_WARNING
,E_USER_NOTICE
l 其他E_ALL
:代码所有错误(通常在进行错误控制的时候使用比较多),建议在开发过程中使用
所有以E开头的错误常量(代号)其实都是由一个字节存储的,然后每一种错误占据一个对应的位,如果想进行一些错误控制,可以使用位运算进行操作
比如排除通知级别错误notice
->E_ALL
& ~E_NOTICE
(取notice
相反的位然后和总的错误集合去与运算)
错误触发:
人为触发:知道某些逻辑可能会出错,从而使用对应的判断代码来触发响应的错误提示
Trigger error(错误提示:)
如果想程序执行到这个报错后,后续代码不执行,可以这样echotrigger_error('除数不能为零'),E_USER_ERROR;
错误显示设置
用于设置那些错误需要显示,以及该如何显示
在PHP中,由两种方式来设置当前脚本的对于错误处理
1. 更改PHP的配置文件,是个全局配置方法:php.ini文件error_reporting
:显示何种类型的错误显示display_error
:是否显示何种错误显示
2. 可以在运行的PHP脚本中去设置,比在配置文件中的级别高error_reporting()
:设置对应的错误显示级别ini_set(‘配置选项’,配置值)
ini_set('error_reporting',E_USER_ERROR)
ini_set('display_errors',1);
错误日志设置:
在实际的生成环境中,不会直接让错误赤裸裸的展示给用户:
1. 不太友好
2. 不安全,会暴露很多网站的信息,会让不安分的人有可乘之机
所以在一般生产环境中,不显示错误(错误也会比较少),但是不可能避免会出现错误,这个时候不希望被看到,但是又希望捕捉到可以让后台程序员察觉并修改,就需要保存到日志文件中,需要在PHP配置文件(php.ini)或者当前代码文件(ini_set)设置对应的error_log配置项
error_log日志配置项:
-
自定义错误处理
最简单的错误处理:
trigger_error()
函数,但是该函数不阻止系统报错
所以:
PHP系统提供了一种用户处理错误机制,用户自定义错误处理函数,然后该函数增加操作系统的
下面自定义个用户的错误处理函数 定义用户错误处理函数
代码:
//自定义PHP错误显示函数
/**
* @param1 $errno,是系统提供的错误代码:E_ALL,E_NOTICE....
*/
//自定义PHP错误显示函数
/**
* @param1 $errno,是系统提供的错误代码:E_ALL,E_NOTICE....
*/
function my_error($errno,$errstr,$errfile,$errline){
//判断当前会遇到的错误有哪些
if(!(error_reporting()) & $errno){
//error_reporting()没有参数代表获取当前系统错误处理对应级别
return false;
}
//开始判断错误类型,返回不同的提示
switch($errno){
case E_ERROR:
case E_USER_ERROR:
echo "致命错误 在文件".$errfile.'在'.$errline.'行';
echo "错误在:".$errstr;
break;
case E_WARNING:
case E_USER_WARNING:
echo "警告错误 在文件".$errfile.'在'.$errline.'行';
echo "错误在:".$errstr;
break;
case E_NOTICE:
case E_USER_NOIICE:
echo "通知错误 在文件".$errfile.'在'.$errline.'行';
echo "错误在:".$errstr;
break;
}
return true;
}
- 注册自定义函数修改错误处理机制
//修改错误机制set_error_handler('my_error');
PHP_字符串
字符串的定义语法:
- 单引号字符串
- 双引号字符串
- nowdoc字符串
引入了 分界符的概念
是一个没有单引号的单引号字符串
4. heredoc字符串
是一个没有双引号的的双引号字符串
查看网页源代码后 ,发现实际的结构,是原封不动的,这是对结构的保证性
结构化定义字符串变量的规则:
- 结构化定义字符串对应的边界符有条件
- 上边界符后面不能跟任何内容,包括空格
- 下边界符必须定格写,最左边
- 下边界符后面通用只能跟
;
,不能跟其他任何内容
- 结构化定义字符串的内部(上下边界符之间)的所有内容都是输出字符串本身
字符串转义:
在计算机的通用协议中,有一些特定的方式定义的字母,系统会特定处理:通常这些方式都是使用反斜杠+字母的特性:
PHP在时别转义字符的时候也是使用相同的模式:反斜杠+字母\'
: 在单引号字符串中显示单引号\"
: 在双引号字符串中显示双引号\n
: 在字符串中显示换行\t
: 在字符串中显示出一个制表符\r
: 在字符串中显示回车(理论上是回到当前行的首地址)\$
: 在字符串中显示美元符$
\\
: 在字符串中显示\
在单引号或双引号在使用转义字符的时候,是有区别的,单引号字符串只能识别 \'
双引号字符串只是识别不了\'
因为双引号能够识别**$**
符号,所以双引号可以解析变量,而单引号不行
双引号识别变量的规则:
1)变量本身系统能够与后面的内容区分,应该包子变量的独立性
或者使用变量专业标识符用来区分:给变量加上一组大括号{}
字符串长度
1)基本函数strlen()得到字符串长度
2)多字节字符串的长度问题:包含中文的长度
3)多字节字符串扩展模块:mbstring
扩展(mb:multi Bytes
)
需要加载mbstring
扩展
可以使用mb扩展带来的很多函数echomb_strlen($str1)."</br>".mb_strlen($str2);
mbstring扩展针对的是一些字符统计:strlen()
只能针对标准交换码ASCII
,mbstring
会针对不同的字符集echomb_strlen($str1)."</br>".mb_strlen($str2, "utf-8");
字符串相关函数
- 转换函数
implode(连接方式,数组)
:将数组中的元素俺找某个规则连成一个字符串explode(分割字符,目标字符串)
:将字符串按照某个格式进行分割,变成数组str_split(目标字符串,字符长度)
:按照指定长度拆分字符串得到数组
2. 截取函数trim(字符串,指定字符)
:默认用来去除两边的空格(中间不行),按照指定的内容循环去除俩边指定的内容ltrim()
:去除左边的rtrim()
:去除右边的
3. 截取函数substr(字符串,起始位置从0开始[,长度])
:指定位置开始截取,截取指定长度strstr(字符串,匹配字符)
:从指定位置开始,截取到最后(用来取后缀名)
4. 大小写转换函数strtolower()
:全部小写strtoupprt()
:全部大写ucfirst()
:首字母大写
5. 查找函数strpos()
:查找字符在字符串首次出现的地址,返回位置信息,没找到返回falsestrrpos()
:字符在目标字符串最后出现的地址,返回位置信息,没找到返回false
6. 替换函数str_replace(匹配目标,替换的内容,字符串本身)
:将字符串本身指定的目标替换成指定的内容
7. 格式化函数printf/sprintf()
:格式化输出字符串内容
8. 其他函数str_repeat(字符串本身,重复次数)
:重复某个字符串N次str_shuffle(字符串本身)
:随机打乱字符串本身
PHP_数组
数组:array
数据的组合:指将一组数据存储到一个指定容器中,用变量指向该容器,然后可以通过变量一次性得到该容器中的所有数据
数组定义语法:
l 使用array
关键字,是最常用的$变量=array(元素1,元素2,元素3...);
l 可以使用中括号来包裹数据$变量=[元素1,元素2,元素3...];
l 隐形定义数组:给变量增加一个在括号,系统自动变成数组$变量{}=值1; //不提供下标,默认0开始
$变量[下标]=值;
中括号里面的内容称之为下标kay,该下标看意识字母(单词)或者数字,与变量命名的规则相似
可以看到 不管后面定义的下标顺序定义还是定义的字符,在数组排序都是依次往后加,
数组特点:
1)可以整数小标或者字符下标
如果数组下标都为整数:索引数组
如果数组下标都为字符串:关联数组
2)不同下标可以混合存在,混合数组
3)数组元素的顺序以放入顺序为准,与下标无关
4)数字下表的自增长特性
默认递增,如果手动改变顺序,那下一个默认就从最大下标数字+1开始
5)特殊值下标的自动转换false
和true
作为下标的时候会变成0和1NULL
就会变成空字符串
6)PHP中数组元素没有类型限制
7)PHP中数组元素没有长度限制
多维数组
指的就是数组的元素又是数组,像是俄罗斯套娃
二维数组:
一维数组就是最普通的数组,类似$变量=[元素1,元素2,元素3...];
这样定义的
二维数组就是数组元素都是若干个一维数组
多维数组:
无非就是在二维数组的基础上继续嵌套数组,理论上可以嵌套无数个,但是不建议,最好直到三维,多了会增加访问的困难程度
异型数组:
就是数组里面不一定嵌套的数组,可能第一个元素是数组,第二个元素是数字,第三个元素是字符串等等,诸如此类
数组遍历:
普通数组的数据访问都是通过数组里元素下标来实现访问元素,如果说数组中所有数据都需要依次输出出来,就需要用到一些简化的规则来获取下标以及输出下标对应的数组元素$arr=array(0=>'name',1=>'age',3=>array("name"=>'tom'),4=>array("age"=>18)); //二维数组
//访问一维数组就是 $arr[一维下标]var_dump($arr[1]);
//访问二维数组里的值 $arr[一维下标][二维下标]
foreach函数遍历数组
基本语法如下:
foreach ($old_arr as $key => $value) {
echo $value."</br>";
}
$old_arr:原数组
$key:数组下标
$value: $key下标对应的值
有点类似于Python的字典,一个键值对,主要还是PHP不规定下标必须为数字,
如果是关联数组(全是字符串为下标),就需要访问对应字符下标
PHP_数组遍历
foreach数组遍历:
foreach
遍历的原理:本质是数组的内部有一颗指针,默认指向数组元素的第一个元素,foreach
就是利用指针取获取数据,同时移动指针
foreach ($old_arr as $key => $value) {
//循环体;
}
foreach
会重置指针,让指针指向第一个元素
2. 进入foreach
循环,通过指针取得当前第一个元素,然后将下标取出放到对应的下标变量$key
中(如果存在),将值取出来放到对应的值变量$value
中(指针下移)
3. 进入循环内部,执行循环体
4. 重复2和3,直到2的时候遇到指针取不到内容(指针指向最后一个数组元素的后面)
for循环遍历数组
for
循环基于已知边界条件(起始和结束)然后又条件的变化(规律)
因此 for
循环遍历数组又对应条件
1. 获取数组的长度:count
(获取数组长度)来决定循环多少次
2. 获取数组下标的顺序,只能用于索引数组,且下标规律
while配合each和list遍历数组
while
在判断的时候 就执行了一次each($arr)
,导致指针后移,然后循环体执行一次后又判断 执行了一次each($arr)
,所以只取到了 1,3的数
这样子 就好了,当each($arr)
取不到数组值后,说明到了数组最后一个,也就返回false
了,也终止了while循环
数组排序函数:
对数组元素进行排序,按照ASCII码进行比较,可以进行英文比较sort()
:顺序排序rsort()
:逆向排序asort()
:还是顺序排序,不会改变原来的下标和值的对应关系arsort()
:逆序排序,不会改变原来的下标和值的对应关系ksort()
:顺序排序:按照键名(也就是下标)排序krsort()
:逆序排序,按照键名shuffle()
:随机打乱排序
值会随机打乱排序,下标保留
数组指针函数
reset()
:重置指针,将数组指针回到首位,返回第一个值end()
:重置指针,将数组指针指向最后,返回最后一个值next()
:指针下移,获取下一个元素的值prev()
:指针上移去,获取上一个元素的值current()
:获取当前指针对应的元素值key()
:获取当前指针对应的下标
注意:如果通过上移或者下移,超出了数组的首地址和最后一个元素地址,(数字之外)就无法再次通过上移或者下移指针,使其重新指入当前数组,只能通过reset和end重置指针
其他数组函数
count()
:统计数组中元素的数量array_push()
:从数组后面加入一个元素array_pop()
:从数组后面取出一个元素array_shift()
:从数组前面取出一个元素array_unshift()
:从数组前面加入一个元素
PHP模拟数据结构:
栈:先进后出(FILO)
队列:先进先出(FIFO)array_keys()
:获取一个数组的所有下标,返回一个索引数组array_values()
:获取一个数组的所有值,返回一个索引数组in_array(指定的值,数组本身)
:在给定的数组中寻找指定的值
PHP_编程思想
如果利用数学模式,来解决对应的需求问题,然后利用代码实现对应的数据模型(逻辑)
算法就是利用代码实现对应的数学模型,从而解决对应的业务问题
递推算法
递推算法是一种简单的算法,通过已知条件利用特定关系得出中间推论,直至得到结果的算法
#案例:斐波拉契数列:1,1,2,3,5,8,13……通常需求求指定n的对应值是多少?
找规律:
1. 第一个数是1
2. 第二个数也是1
3. 从第三位开始,数是前俩个数的和
递归算法:
递归算法世把问题转化为规模缩小了的同类问题的子问题,然后递归调用函数(或过程)来表示问题的解
1. 简化问题,找到最优子问题
2. 函数自己调用自己
还是#案例:斐波拉契数列:1,1,2,3,5,8,13……通常需求求指定n的对应值是多少?
找规律:F(N)=F(N-1)+F(N-2)
F(N-1)=F(N-2)+F(N-3)
…
F(2)=F(1)=1
递归中有俩个非常主要的点;
递归点
:发现当前问题可以有解决当前问题的函数,取解决规模比当前小一点的问题来解决
F(N)=F(N-1)+F(N-2)
递归出口
:,当问题以及解决,以及到达最优子问题,不能再次调用函数
因为函数自己调用自己,自己里面又调用自己,如果没有递归出口,会陷入死循环
递归的本质是函数调用函数:一个函数需要开辟一块内存空间,递归会出现同时调用N个自己,递归的本质就是牺牲空间换时间
/2021/11/27 00:49/