PHP简介
php定义
php是一种服务器端的HTML脚本/编程语言,是一种简单的、面向对象的、解释型的、健壮的、安全的动态的脚本语言。
尤其适合web开发并可以嵌入HTML的多用途脚本语言。它的语法接近C,Java和Perl且容熙学习。
该语言让WEB开发人员快速的书写动态生成的网页
php前身
Personal HomePage:个人主页,使用Perl语言开发的一种写个人主页的语言
PHP:PHP Hypertext Preprosessor,php超文本预处理器,底层使用C语言
静态网页特点
- 静态网页就是实实在在存放在服务器上的文件
- 内容相对稳定,容易被服务器检索
- 没有数据库的支持
- 交互性差,功能局限性大
动态网站特点
- 交互性:根据用户的要求动态的改变和相应
- 自动更新HTML文档
静态网页URL后缀一般是HTML,xml等,动态网页一般以asp,jsp,php等为后缀,并且动态网页有一个标志性的后缀: ?
网站基本概念
服务器概念
服务器是提供计算机服务的设备,根据服务器提供的服务类型不同,分为文件服务器,数据库服务器,应用程序服务器,WEB服务器等
服务器的类型取决于服务器上安装的软件
如WEB服务器需要tomcat,apache等服务软件
IP的概念
计算机网络实现互联而设计的协议
域名的概念
域名就是IP的面具
DNS的概念
DNS作为IP和对应域名相互映射的一个分布式数据库,使用户通过域名就能找到对应IP地址,这个过程叫做域名解析或主机名解析
端口的概念
端口可以看做设备与外界通讯的出口。端口分为虚拟端口和物理端口
- 其中虚拟端口值计算机内部或交换机路由器内的端口,不可见。例如计算机中的80端口,21端口,23端口等。
- 物理端口又叫接口,如键盘USB
软件设计结构:C/S和B/S
C/S:Client客户端/Server服务端,用户需要安装特定的客户端产品才能访问服务器,且只能访问该软件特定的服务器
B/S:Browser浏览器/Server服务端,用户只需安装浏览器,就可以访问所有支持B/S架构的服务器
静态网站访问过程
用户输入域名localhost:端口->DNS解析(localhost127.0.0.1)->服务器电脑->服务软件

- 用户在浏览器输入URL-(Uniformed Resource Location)统一资源定位-互联网里的绝对路径
- 通过DNS先检查本地DNS的hosts文件是否符合要求,不符合则寻找网络DNS的hosts文件,将IP地址返回给用户机
- 用户机通过IP地址访问找到的服务器,通过端口访问服务器里的服务软件,如apache
- apache通过用户给予的URI(Uniformed Resource Identifer)-统一资源标识(如/index.html),即目标服务器上某个文件夹的相对路径去搜索服务器文件夹里的内容,将搜索的结果返回给用户
动态网站访问过程
动态网站访问比静态多了两个内容:
- 服务器端解析
- 数据库

动态网站和静态网站区别:
- 标识符后缀由html相关后缀边为.php后缀,或者以?为后缀
- apache还要通过php引擎解析php文件或者从另一台服务器上获取数据,然后将这些数据和HTML代码返回给用户机
阿帕奇apache服务软件介绍
Apache目录介绍
- bin目录 存放二进制文件,一般是windows可执行的exe程序
- conf目录 存放配置文件
- htdocs 默认网站根目录
Apache配置默认站点
- 让Apache确定服务器上访问的位置,即网络文件夹所在位置
httpd.conf里的document配置 - 方便用户使用名字访问对应的网站:给文件夹一个别名
httpd.conf里的severname
- 可以单独设置端口:httpd.conf里的Listen设置
- 实现DNS域名解析:通常默认站点都是本地DNS:host文件
C:\Windows\System32\drivers\etc里将127.0.0.1 的值修改为localhost - 凡是涉及到配置文件的更改,都要重启apache
用xmapp打开apache发现一启动就闪退,cmd运行httpd.exe报错:
(OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 : AH00072: make_sock: could not bind to address [::]:443
(OS 10048)通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 : AH00072: make_sock: could not bind to address 0.0.0.0:443
AH00451: no listening sockets available, shutting down
AH00015: Unable to open logs
由此可知443端口被占用了,我们去配置文件将443端口修改为别的端口即可
为什么需要php
如果直接让Apache将php文件传递给用户,那么用户接受到了将是一堆乱码,因为浏览器是不认识php文件的
因此我们要安装php,并将php放到Apache的兄弟目录,这样apache就能通过php来解析php文件为html代码,这样浏览器就能呈现出想要的效果
配置Apache加载php模块
我们需要对Apache和php文件进行配对才能实现Apache对php代码的解析
(如果是用的xampp安装套件,则无需配置)
- 1.在Apache的主配置文件中加载对应的php提供的模块:
#加载php //这一句是注释
LoadModule php7_module ‘C:/xampp/php/php7apache2_4.dll’
//第二句分三部分
LoadModule:加载模块
php7_module:表示php7版本的模块
‘C:/xampp/php/php7apache2_4.dll’:放入该dll文件的目录
- 2.Apache分配工作给php模块:
如果是php代码就交给php处理(文件后缀判断.php结尾肯定是php代码)依然在httpd.conf中添加
AddType application/x-httpd-php .php
- 3.将php的配置文件加载到Apache的配置文件中,共同生效
①php的配置文件即php.ini本来是不存在的,是以development和production格式存在,因此我们将php.ini-development文件复制一份并更名为php.ini
②在Apache中指定php配置文件所在路径:
PHPIniDir ‘php.ini所在路径’
MySql安装
去http://mirrors.sohu.com/mysql/MySQL-8.0/下载msi的win64位版本
- 选择custom自定义安装
- 文件安装目录选择xampp/mysql
- 数据安装目录选择xampp/mysql/data(新建)
bin目录详细
- mysqld.exe:mysql的启动文件
- mysql.exe:访问mysql服务的客户端
- mysqldump.exe:mysql备份软件客户端
mysql的连接(不使用套件的情况下)
- 启动mysql.exe
- mysql客户端访问服务端需要进行匹配认证
- 连接:IP和端口确认,如果是本地则都可以省略
-h 主机地址 -hlocalhost(可以是ip地址)
-p 端口号 -p3306 - 认证:通过用户名和密码进入服务器
-u用户名 -uroot不可以省略
-p密码 -proot - 退出命令-q
php操作mysql
PHP本身不具备操作mysql数据库的能力,需要借助php扩展来实现
- php加载mysql扩展:php.ini中将extension=php_mysql.dll前的注释符去掉
- php中所有的扩展都是在ext文件中,需要指定扩展的所在路径:extension_dir = “php_mysql.dll文件所在所在路径”
- 重启Apache
- 设置php系统时区:在php.ini中将date.timezone的值改为 PRC
配置虚拟主机
一台服务器很贵,如果只能部署一个网站是非常浪费的,所以需要通过其他渠道来实现一台主机上部署多个网站
什么是虚拟主机
虚拟主机:Virtual machine,并不存在真实的主机,但是可以提供真实主机所实现的功能
通俗来说,虚拟主机就是将计算机中不同的文件夹进行不同的命名,然后可以实现让服务器(Apache)根据用户的需求从不同的文件夹(网站)中读取不同的内容
虚拟主机的分类
在Apache中,可以将虚拟主机划分为两类
- 基于ip的虚拟主机:一台主机上有多个ip,每个ip对应一个网站
原理:电脑默认只有一个IP,因为通常只配有一个网卡;但是有的电脑(服务器居多)可以配置多个网卡,每个网卡可以绑定一个IP地址 - 基于域名的虚拟主机:一台电脑上只有一个IP,但是IP下可以制作多个网站,但是需要给每个网站不同的名字(虚拟主机名)
搭载基于域名的虚拟主机
在Apache中,虚拟主机的搭建有两种方式:
1.在主配置文件中搭建:需要手动开启虚拟主机(基于域名)
NameVirtualHost *:80 (较少使用)
2. 在专门的虚拟主机配置文件中配置
2.1 在主配置文件中加载虚拟主机配置文件:虚拟主机配置文件已经开启了虚拟主机NameVirtualHost
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
2.2 虚拟主机配置文件中配置虚拟主机
①增加一个对应的站点文件夹位置:DocumentRoot
②增加主机名
<VirtualHost *:80>
#增加站点
DocumentRoot ‘E:/discuz’
#增加主机名
ServerNamewww.mydiscuz.com
③增加域名解析DNS:hosts
去host文件中添加:
127.0.0.1 www.mydiscuz.com
④需要给当前设定的站点(目录)访问权限
格式:
<Directory ‘站点目录’>
Order Deny,Allow
Deny from 指定的范围
Allow from 指定范围
<Directory>
继续接着上面的VirtualHost *:80的代码后面添加
#配置权限
<Directory ‘E:/discuz’> //开始为该目录配置权限
#设定方式:代表匹配权限的顺序
Order Deny,Allow //先执行Deny,在执行Allow,所以允许
#限定范围:按照顺序执行
Deny from all
Allow frow all //先执行上面Deny,再执行Allow,所以结果也是允许
<Directory>
此时已经可以访问E盘下的discuz文件夹里的index.html了,但是如果discuz文件夹里是空的或者没有html文件,就会报错,因此我们还需要进一步的配置
⑤配置访问列表
当访问时一个目录的时候(没有指定具体要访问的文件),
也就是只输入了www.discuz.com,但没有输入后面的/index或者其他文件,此时会自动跳转的页面需要我们来设置
依然继续在VirtualHost *:80中添加:
Optopms Omdexes FollowSymLinks,该代码意思是将根目录所有文件夹列出,一般只在生产环境下使用,如果项目已经部署,则千万不要用DirectoryIndex index.html index.php如果只输入了根目录,没有输入文件,则默认访问这两个文件,可根据需要添加
如果说网站中整个网站根目录允许访问,但是其中还有其他文件夹不允许访问,可以增加多个<Directory>标签,针对不同的文件夹
localhost虚拟主机配置
如果我们在主机上搭建了其他的虚拟主机,则localhost就会失效,所以我们要为localhost也搭建一个虚拟主机,和上面的方法一样,再添加一组<Directory>进行相关的配置即可
PHP基础
php语法初步
php是一种运行在服务器端的脚本语言,可以嵌入到html中
php代码标记
在php历史发展中,可以使用多种标记来区分php脚本
- ASP标记:
<% PHP代码 %> - 短标记:
<? php代码 ?>
以上两种基本弃用,如果要使用那么需要在配置文件中开启 - 脚本标记:
<script language= "php">php代码<script> - 常用标准标记:
<?php php代码 ?>
php注释
php注释分为两种
- 行注释:一次注释一行
// 后面跟的内容都是注释
# 与//一样 - 块注释:一次注释多行
/*
php代码
*/
php语句分隔符
语句分隔符:在PHP中,代码是以行为单位,系统需要通过判断行的结束,该结束通常都是一个符号:分号 ;
php的结束标签自带分隔符效果,最后一行php代码可以不加分号(不建议)
- php一般单独写在php文件中,所以一般不加结束符,即
?>,表示从头标签到最后都是php代码,而且节省空行
变量
php是一种动态网站开发的脚本语言,动态语言特点是交互性,会有数据的传递,而PHP作为”中间人“。需要进行数据的传递,传递的前提就是PHP能自己存储数据(临时存储)
变量的使用
- 定义:在系统中增加对应的变量名字(内存)
在PHP中不需要任何关键字定义变量,用$符号定义即可
$a; - 赋值:可以将数据赋值给变量名(可以在定义的同时完成)
$a=1; - 可以通过变量名访问存储的数据
echo $a - 可以将变量从内存中删除
unset($a)
变量命名规则:
- 变量名必须以
$开头,并且要一直带着$使用 - 名字由字母数字下划线构成,不能以数字开头
- 变量名支持中文,但不建议使用
预定义变量
预定义变量:提前定义的变量,系统定义的变量,存储许多需要用到的数据(预定义变量都是数组),常见预定义变量:
$_GET:获取所有表单以get方式提交的数据
$_POST:POST提交的数据都会保存在此
$_REQUEST:GET和POST提交的都会保存
$GLOBALS:php中所有的全局变量
$_SERVER:服务器信息
$_SESSION:session会话数据
$_COOKIE:cookie会话数据
$_ENV:环境信息
$_FILES:用户上传的文件信息
可变变量
可变变量:如果一个变量保存的值刚好是另外一个变量的名字,那么可以直接通过访问一个变量得到另外一个变量的值:在变量前多加一个$符号
$a = 'b';
$b = 'bb';
$$a 将打印'bb'
变量传值
将一个变量赋值给另外一个变量:变量传值
变量传值一共有两种方式:值传递和引用传递
- 值传递:将变量保存的值复制一份,然后将复制的新的值给另外一个变量保存
$a=1;
$b=$a;
- 引用传递:将变量保存的值所在的内存地址,传递给另外一个变量:两个变量指向同一块内存空间
$a=1;
$b=&$a;
因为$b接收到的是一个地址,又要将这个地址赋值给$b,所以$b就将接收到的地址作为了它自己的地址,和$a指向了同一块数据段
常量
常量与变量一样,都是用来保存数据的
常量:const/constant是一种在程序运行当中,不可改变的量
常量一旦定义,通常数据不可改变(用户级别)
常量定义形式
在PHP中常量有两种定义方式
- 使用定义常量的函数:define(‘常量名’,常量值)
define(‘PI’,3.14) - 5.3之后才有的:const 常量名 = 值
const PI = 3.14
常量的命名规则
- 常量不需要使用$符号,一旦使用系统会认为是变量
- 常量的名字组成由字母、数字和下划线组成,不能以数字开头;但常量命名的规则比变量要松散,可以使用一些特殊字符,该方式只能使用
define来定义 - 常量的名字通常是以大写字母为主(与变量以示区别)
注意细节:
- Define和const定义的常量是有区别的:在于访问权限的区别
- 定义常量通常不区分大小写,但是可以区分,可以参照define函数的第三个参数
常量的使用规则
常量在定义的时候必须赋值
常量在使用的时候前面不需要加$符号
在访问名字较特殊的常量时,需要用到另一个访问常量的函数:constant(‘常量名’)
常量和变量的选择
- 凡是数据会发生变化的,那么肯定用变量
- 数据不一定会变的,可以使用常量或变量(变量居多)
- 数据不允许被修改的,一定用常量
系统常量
系统常量:系统帮助用户定义的常量,用户可以直接使用
常用的几个系统常量
PHP_VERSION:PHP版本号PHP_INT_SIZE:整型大小PHP_INT_MAX:整型能表示的最大值
在PHP中还有一些特殊的变量,他们由双下划线开始+常量名+双下划线结束,这种常量称之为系统魔术常量:魔术常量的值通常会跟着环境变化,但是用户改变不了
__DIR__:当前被执行的脚本所在电脑的绝对路径(到脚本所在文件夹)
__FILE__:当前被执行的脚本所在的电脑的绝对路径(到脚本本身)
__LINE__:当前所属的行数
__NAMESPACE__:当前所属的命名空间
__CLASS__:当前所属的类
__METHOD__:当前所属的方法
数据类型
数据类型:data type,在PHP中指的是存储的数据的类型,而不是变量本身的类型。PHP是一种弱类型语言,变量本身没有数据类型
PHP的八种数据类型
在PHP中将数据分为三大类八小类:
- 简单(基本)数据类型:4个小类
整型:int/integer,系统分配4个字节存储,表示整数类型(有前提)
浮点型:float/double,系统分配8个字节存储,表示小数或者整型存不下的整数
字符串型:string,系统根据实际长度分配,表示字符串(带引号的就是字符串)
布尔类型:bool/boolen,表示布尔类型,只有两个值:true和false - 复合数据类型:2个小类
对象类型:object,存放对象
数组类型:array,存储多个数据(一次性) - 特殊数据类型:2个小类
资源类型:resource,存放资源数据(PHP外部变量,如数据库、文件)
空类型:NULL,只有一个值就是NULL(不能参与运算)
数据类型转换
类型转换:在很多的条件下,需要指定的数据类型,需要外部数据(当前PHP取得的数据)转换成目标数据类型
在PHP中有两种类型转换方式:
- 自动转换:系统根据需求自己判定,自己转换(用的比较多,效率偏低)
如
$a='abc1.1.1';
$b='1.1.1abc;'
echo $a+$b; //算数加运算,系统先转换为数值型再晕眩
输出结果1.1
- 强制(手动)转换:人为根据需要的目标类型转换
强制转换规则:在变量之前增加一个括号(),然后在里面写上对应类型:int/integer/float等等…其中NULL类型要 用到unset()
$a='abc1.1.1';
$b='1.1.1abc;'
echo (float)$a,(float)$b; //强制转换
输出结果0和1.1
在转换过程中用的比较多的就是转布尔类型(判断)和数值类型(算数运算)
- 转布尔类型:转为true和false,一般转为true较多
- 其他类型转数值的说明:
- 布尔true为1,false为0
- 字符串转数值有自己的规则:
2.1 以字母开头的字符串,永远为0
2.2 以数字开头的字符串,取到碰到字符串为止(不能同时包含两个小数点)
类型判断
通过一组类型判断函数,来判断变量,最终返回这个变量所保存数据的数据类型(相同结果为true,失败为false):是一组以is_开头的后面跟类型名字的函数:is_XXX(变量名)
BOOL类型不能用
echo来查看,因为这个true容易和bool类型的true混淆,可以使用var_dump结构查看:var_dump(变量1,变量2…)
还有一组函数可以用来获取以及设定数据(变量)的类型:
Gettype(变量名):获取类型,得到的是该类型对应的字符串Settype(变量名,类型):设定数据类型,与强制转换不同
2.1 强制转换是对数据值复制一份的内容进行处理,不会影响实际存储的内容
2.2 Settype会直接改变数据本身类型
整数类型
保存整数数值,4个字节存储数据,最大就是32位,也就是42亿多
但是在PHP中默认是有符号类型,即正21亿到负21亿
在PHP中提供了四种整型的定义方式:十进制定义,二进制定义,八进制定义和十六进制定义
$a=110;//10进制 输出110$a=0b110;//2进制 输出6$a=0110;//8进制 输出72$a=ox110;//16进制 输出272
默认的PHP输出数值都会自动转换成10进制输出
PHP也提供了很多函数供用户用来进制转换:
Decbin():十进制转二进制 会在结果前补零补齐32位来存储,但只在计算机内部实现Decoct(): 十进制转八进制Dechex(): 十进制转十六进制
浮点类型
浮点型:就是小数类型或者超过整数所能存储范围的整数(不保证精度),精度范围大概在15个有效数字左右
浮点型定义有两种方式:
$f=1.23;
$f=1.23e10;
简单说明浮点数为什么同样的字节数存储数据,但是却能表示更大的数据呢?
00000000 00000000 00000000 00000000 → 11111111 11111111 11111111 11111111 (整型最大值:所有位都是有效数据)浮点数:斜体7位算的结果是10的指数,后面三个字节存储表示具体数值
00000000 00000000 00000000 00000000 → 11111111 11111111 11111111 11111111尽量不用浮点数做精确判断:浮点数保存的数据不够精确,而且在计算机中凡是小数基本上存的都不准确
布尔类型
布尔类型:两个值true和false,通常用于判断比较
在进行某些数据判断的时候,需要特别注意类型转换
Empty():判断数据的值是否为空,如果为空则返回true,不为空则返回falseIsset():判断数据存储的变量本身是否存在,存在变量返回true,不存在返回false
运算符
在这里补充一些比较运算符
比较运算符
===:全等于,左边和右边不仅值相同,数据类型也要相同时才成立
!==:不全等于,左边和右边的值和数据类型有一个不相同则成立
连接运算符
连接运算:是PHP中将多个字符串拼接的一种符号
.:将两边字符串连接到一起
.=:将两边字符串连接到一起并赋值给左边的字符串
错误抑制符
在PHP中有一些错误可以提前预支,但是这些错误可能无法避免,但是又不希望报错给用户看,可以使用错误抑制符处理
- 用法:在语句前加@符号即可
位运算符
位运算:取出计算机中最小的单位(位bit)进行运算
注意位运算符与逻辑运算符的区别
&:按位与,两个位都为1,结果为1,否则为0|:按位或,两个有一个为1,结果为1~:按位非,一个位如果为1则变成0,为0则变成1^:按位异或,两个相同则为0,不同则为1<<:按位左移,整个位(32位),向左移动一位,右边补0>>:按位右移,整个位向右移动一位,左边补符号位对应内容(整数补0,负数补1)
注意:
- 系统进行任何位运算的时候都是使用的补码
- 运算结束之后都必须转换成原码才是最终要显示的数据
流程控制
流程控制:控制代码执行的顺序
分为顺序结构、分支结构、循环结构三种
顺序结构
顺序结构:最基本的结构,所有代码默认都是从上往下依次执行
分支结构
在php中,分支结构主要有两种:if分支和switch分支
if分支
基本语法:
最简if:只有一段代码,但是可以选择是否执行:
if(条件表达式){
}
---------------------------------------
基础if:有两面性,满足条件或者不满足条件都有对应的执行代码
if(条件表达式){
}else {
}
----------------------------------------
复杂if:判断多个表达式来执行多个对应代码
if(条件表达式){
}else if(){
}else {
}
switch分支
基本语法:
switch(条件表达式){
case 值1:
break;
case 值2:
break;
Default:
break;
}
循环结构
循环结构:代码段在一定的控制下,可以多次执行
分为for循环、while循环、do while循环、foreach循环(专门针对数组)
for循环
语法:
for($i = 1;$i = 10;$i++){
}
while循环和do while循环
基本语法:
while:while(条件表达式){};
do while:do{}while(条件表达式);
循环控制
循环控制:在循环内部对循环本身进行控制
中断控制continue:中断当前循环,直接执行下一次循环
终止控制break:直接终止整个循环
循环控制层级:
这两个循环控制的层级默认是1,表示控制该语句所在的循环;如果该语句所在的循环外还嵌套了一层循环,可以将层级设置为2,如break 2;表示直接终止外层循环,但不影响外层循环外的循环
流程控制替代语法
流程控制替代语法:分支和循环结构的替代语法
PHP本身是嵌入到HTML中的脚本语言,需要在HTML中书写一些关于判断或者循环的结构语法,必须符合PHP标签规范,需要HTML与PHP混搭,如果使用原始的PHP代码那么会非常不美观
需求:打印一个九九乘法表,使用表格来展示
<table border="1">
<?php for ($i = 1; $i < 10; $i++) { ?>
<tr>
<?php for ($j = 1; $j <= $i; $j++) { ?>
<td><?php echo $i . '*' . $j . '=' . $i * $j; ?></td>
<?php } ?>
</tr>
<?php } ?>
</table>
我们可以看到这样写起来括号非常的多,所以PHP提供了一种替代语法,让其可以不用书写大括号:
for(;;){ → for(;;):
} → endfor;
除了for循环外,PHP还提供了if、switch、while和foreach等替代语法(不包含do while),其格式都是将左大括号变为冒号,右大括号变为end+流程控制名+分号
如switch(){} → switch(): endswitch;
文件包含
文件包含:在一个PHP脚本中,去将另外一个文件(PHP)包含进来,去合作完成一件事情
文件包含的作用
- 使用被包含文件中的内容,实现代码的共享或重用:向上包含(索要)
- 自己有东西可以给别的文件使用,实现代码的共享或重用:向下包含
- 分工协作,每个脚本做的事情不一样,多个脚本共同完成一件事情
文件包含的四种形式
include:包含文件
include_once:系统会判断文件包含过程中是否已经包含过该文件,一个文件最多被包含一次
require:等同于include
require_once:等同于include_once
基本语法:
- include ‘文件名’;
- include(‘文件名’);
- include和require区别:
include包含的文件如果出错,不会影响其他代码的执行
require包含的文件如果出错,其他的代码也会停止执行
文件加载原理
- 在文件加载(include或require)的时候,系统会自动将被包含文件中的代码嵌套到当前文件中
- 加载位置:在哪里加载,对应文件的代码就嵌入到哪里
- 在PHP中被包含的文件是单独进行编译的
文件加载原理:
读取代码文件(PHP程序) → 将PHP代码编译为字节码(生成opcode) → zendengine来解析opcode,按照字节码去进行逻辑运算 → 转换成对应HTML代码
文件加载路径
文件的加载路径包含两大类:
- 绝对路径
- 从磁盘的根目录开始(本地绝对路径):C:/Apache/htdics/index/php
- 从网站根目录开始(网络绝对路径):
localhost/index.php
- 相对路径:从当前文件所在目录开始的路径
.或者./:表示当前文件夹../:表示上级目录
绝对路径和相对路径的加载区别:
- 绝对路径效率偏低,但是相对安全
- 相对路径效率高些,但是容易出错
文件嵌套包含
一个文件包含另一个文件,同时被包含的文件又包含了其他文件
嵌套包含下的相对路径容易出错,因为被包含文件中使用相对路径../又包含其他文件时,是以被包含文件所在目录为基准的,而不是以当前文件
###函数
函数定义语法
function (参数1,参数2) {
//函数体
//返回值
}
函数默认值
我们可以给形参赋值,如果没有实参传递给形参,则函数会以该默认值执行;
- 只有右边的形参(多个)可以用默认值,也就是说如果出现了第一个默认值,则后面的形参都要有默认值,如果第一个形参有默认值,而后面没有默认值则会报错
引用传值
function (&参数1,&参数2) {
//引用传值需在参数前加&符号,这样函数运算时会改变实参本身
//引用传值必须传入变量
}
函数返回值
return会将结果返回给函数调用处并结束当前函数,在PHP中所有的函数都有返回值。如果没有使用return,则函数默认返回NULL
return可以在文件中直接使用:代表将return后面的内容转交给包含当前文件的位置(通常在系统配置文件中使用较多);在文件中也代表终止后面的代码:return之后的内容不会执行
作用域
PHP中的作用域分为三种:
- 全局变量:函数外部定义的变量,在PHP中只允许在全局空间使用,函数内部不可访问,直到整个文件执行结束再销毁
- 局部变量:在函数内部定义的变量,只允许当前函数内部访问,函数执行完后销毁
- 超全局变量:系统定义的变量(预定义变量:$_SERVER、$_POST等),没有访问限制,函数内外都能访问
define定义的常量函数内外部也都可以访问
那么函数内如何访问全局变量呢?除了通过传参的形式,还可以借助于超全局变量$_GLOBALS,因为全局变量声明时会以数组的形式存储到超全局变量$_GLOBALS[]中
$a = 10;
function print () {
echo $_GLOBALS['a']; //注意a就是数组的下标,用引号包含并且不用加$符号
}
print(); //函数输出10
除了$GLOBALS之外,在PHP中还有一种方式可以实现全局变量和局部变量的互相访问:global关键字,global是在函数内部定义变量的一种方式
- 如果global定义的变量名在外部存在,那么该global定义的变量直接指向外部全局变量所指向的内存空间
- 如果global定义的变量名在外部不存在,那么系统会自动在外部定义一个与该变量同名的全局变量
- 本质就是在函数内部和外部对一个同名变量使用同一块内存地址保存数据,从而实现共同拥有
基本语法:
global $a; //在声明时不能赋值
$a = 10; //赋值
静态变量
静态变量:static,是在函数内部定义的变量,使用static关键字修饰,用来实现跨函数(不是指多个函数,是指同一个函数被多次调用)共享数据的变量:函数运行结束后所有的局部变量都会清空,如果重新运行一下函数,所有的局部变量又会重新初始化,而static不会被清空和初始化
- static原理:系统在进行编译时就会对static变量进行初始化,函数在调用时会自动跳过static这一行
基本语法:static $a = 10;
静态变量的使用场景:
- 统计当前函数被调用次数
- 统筹函数多次调用得到的不同结果(递归思想)
可变函数
可变函数:当前有一个变量所保存的值,刚好是一个函数的名字,那么就可以使用变量+()来充当函数名使用
基本语法:
function getsum() {
//定义一个getsum函数
}
$a = 'getsum';
$a(); → 相当于getsum();
匿名函数
匿名函数:没有名字的函数
基本语法:
变量名 = function () { //将函数赋值给一个变量来保存
}; //因为是定义变量,所以要加分号
变量保存匿名函数,本质得到的是一个对象(closure)
闭包
闭包:closure,简单理解就是函数内部有一些局部变量在函数执行后没有被释放,是因为在函数内部还有对应的函数在引用(函数的内部函数:匿名函数)
function display () {
$a = 10;
$fn = function () use($a){ //use就是将外部变量(局部)保留给内部使用,也就形成了闭包
echo $a;
}
}
证明函数局部变量在函数使用完后没有被释放:
- 使用内部匿名函数
- 匿名函数使用局部变量:
use - 返回匿名函数给外部使用
伪类型
伪类型:假类型,实际上在PHP中不存在的类型。但是通过伪类型可以帮助程序员更好的查看操作手册从而方便学习
伪类型主要由两种:在三大类和八小类之外
mixed:混合类型,可以是多种php中的数据类型
number:数值型,可以是任意数值类型,如整型和浮点型
当我们看到mixed或number时,知道它属于php数据类型中的一种即可
常用系统函数
有关输出的函数
print():类似于echo输出提供的内容,本质是一种结构(不是函数),返回1,可以不需要使用括号
print_r():类似于var_dump,但是比var_dump简单,不会输出数据的类型,只会输出值(数组打印使用比较多)
有关时间的函数
date():按照指定格式对应的时间戳(从1970年开始计算的秒数),如果没有指定特定的时间戳,那么就是默认解释当前的时间戳
time():获取当前时间对应的时间戳
microtime():获取微秒级别的时间
strtotime():按照规定格式的字符串转换成时间戳
有关数学的函数
max():指定参数中最大的值
min():指定参数中最小的值
rand():指定区间的随机整数
mt_rand():与rand一样,只是底层结构不一样,效率比rand高
round():四舍五入
cell():向上取整
floor():向下取整
pow():求置顶数字的指定指数次结果
abs():求绝对值
sqrt():求平方根
有关函数的函数
function_exists():判断指定的函数名字是否在内存中存在
func_get_arg():在自定义函数中去获取指定数值对应的参数
func_get_args():在自定义函数中获取所有的参数(数组)
func_num_args():获取当前自定义函数的参数数量
错误处理
错误处理:指系统或用户在对某些代码进行执行的时候,发现有错误,就会通过错误处理的形式告知程序员
错误分类
- 语法错误:用户书写的代码不符合PHP语法规范,语法错误会导致代码在编译过程中不通过,所以代码不会执行(parse error)
- 运行错误:代码编译通过,但是代码在执行的过程中会出现一些条件不满足桃汁的错误(runtime error)
- 逻辑错误:程序员在写代码的时候不够规范,出现了一些逻辑性的错误,导致代码正常执行,但是得不到想要的结果
错误代号
所有看到的错误代码在PHP中都被定义成了系统常量(可以直接使用)
- 系统错误:
E_ERROR:fatal error,致命错误,会导致代码不能正确继续执行(出错的位置断掉)
E_PARSE:编译错误,代码不会执行
E_WARNING:警告错误,不会影响代码执行,但是可能得到意想不到的结果
E_NOTICE:通知错误,不会影响代码执行 - 用户错误:E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE
用户在使用自定义错误触发的时候,会使用到的错误代号(系统不会用到) - 其他:E_ALL,代表着所有的错误(通常在进行错误控制的时候使用比较多),建议在开发过程中使用
所有E开头的错误常量(代号)其实都是由一个字节存储,然后每一种错误占据一个对应的位,如果想进行一些错误的控制,可以使用位运算进行操作
排除通知级别notice:E_ALL&~E_NOTICE
只要警告和通知:E_WARNING | E_NOTICE
错误触发
- 程序运行时触发:系统自动根据错误发生后,对比对应的错误信息,输出给用户:主要针对代码的语法错误和运行时错误
- 人为触发:知道某些逻辑可能会出错,从而使用对应的判断代码来触发相应的错误提示
如trigger_error('除数不能为0!',[E_USER_ERROR]);,方括号里可以指定错误类型
错误显示设置
错误显示设置:哪些错误该显示,以及该如何显示
在PHP中,其实有两种方式来设置当前脚本的错误处理
- PHP的配置文件:全局配置:php.ini → 设置
error_reporting和display_error两项参数 - 可以在运行的PHP脚本中去设置,且比php.ini中设置的权重高
error_reporting():设置对应的错误显示级别
ini_set('配置文件中的配置项',配置值);
ini_set('error_reporting',E_ALL);
ini_set('display_errors',1);
错误日志设置
在实际生产环境中,不会直接让错误赤裸裸的展示给用户:
- 不友好
- 不安全:错误会暴露网站很多信息(路径、文件名)
所以在生产环境中,一般不显示错误,但是不可避免的会出现错误(测试的时候不会发现所有的问题),这个时候不希望用户看到,但是又希望捕捉到可以让后台程序员去修改,这该怎么办呢?
此时我们可以将错误保存到日志文件中,需要在PHP配置文件中或者代码中(ini_set)设置对应error_log配置项
步骤:
- 打开php.ini
- 开启日志功能:log_errors = On
- 指定路径:error_log=“C:\xampp\php\logs\php_error_log”
自定义错误处理
最简单的错误处理:trigger_errors()函数,但是该函数不会阻止系统报错
PHP系统提供了一种用户处理错误的机制:用户自定义错误处理函数,然后将该函数增加到系统错误处理的句柄中,然后系统会在碰到错误之后,使用用户定义的错误函数
- 如何将用户自定义的函数放到系统中?使用
set_error_hander()函数 - 自定义错误处理函数
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 'fatal error in file' . $errfile . 'on line' . $errline . '<br/>';
echo 'error info:' . $errstr;
break;
}
return true;
}
//修改错误机制
set_error_handler('my_error');
字符串
字符串定义
语法:$str1 = 'hello';
该方式适合定义比较短的或者没有结构要求的字符串,如果有结构要求,或者内容超过一行,可以使用以下两种结构定义:
- heredoc
$str2 = <<<EOD
hello
EOD;
- nowdoc
$str3 = <<<'EOD'
hello
EOD;
结构化定义字符串变量规则:
- 上边界符EOD后面不能跟任何内容
- 下边界符必须顶格在最左边
- 下边界符后面只能有分号
- 边界符之间的所有内容都属于字符串内容
字符串转义
在PHP中系统常用的转义符号:
\':在单引号内容中显示单引号
\":在双引号内容中显示双引号
\r:代表回车(理论上是回到当前行的首位置)
\n:代表换行
\t:类似tab,输出4个空格
\$:在PHP中使用$符号作为变量符号,因此需要特定识别
单引号字符串和双引号字符串的自别
- 单引号字符串可以识别
\',而双引号不能 - 双引号中能识别
$符号,所以双引号中可以解析变量,而单引号不可以
双引号识别变量规则:
①保证变量前后有空格等标志,不要让系统难以区分
②使用变量专业标识符区分,给变量加上一组大括号
字符串长度问题
strlen():根据标准交换码ASCLL码得到字符串的长度,单位为字节,一个中文占3字节
mb_strlen($str,'utf-8'):可以根据字符集获取相应的长度,此时一个中文占1字节
字符串相关函数
- 转换函数:
implode(连接方式,数组):将数组中的元素按照某个规则连接成一个字符串
explode(分割字符,目标字符串):将字符串按照某个格式进行分割,变成数组
str_split(字符串,字符长度):按照指定长度拆分字符串得到数组 - 截取函数1
trim():本身默认是用来去除两边的空格(中间的空格不可以),但是也可以指定要去除的内容,是按照指定的内容循环去除两边有的内容,直到碰到一个不是目标字符位置
ltrim():去除左边空格
rtrim():去除右边空格 - 截取函数2
substr():从指定位置开始截取字符串
strstr():从指定位置截取到最后 - 大小写转换函数
strtolower():全部小写
strtoupwer():全部大写
ucfirst():首字母大写 - 查找函数
strpos():判断字符在目标字符串首次出现的位置
strrpos():判断字符在目标字符串最后出现的位置 - 替换函数
str_replace():将目标字符串中部分字符串进行替换 - 格式化函数
printf/sprintf:格式化输出数据
$age = 20;
$name = 'TOM';
echo sprintf('你好,我今年%d岁,我叫%s',$age,$name);
- 其他函数
str_repeat():重复某个字符串N次
str_shuffle():随机打乱字符串
数组
定义语法
$arr = array(元素1,元素2,元素3...);
元素也可以用键值对的形式实现:$arr = array(1,‘name’ => ‘tom’,2);$arr = [元素1,元素2,元素3...];$arr[下标] = 值; //一次只能设置一个
特点
- 数组下标的自增长特性:从0开始自动增长,如果中间手动设置了较大的下标,那么后面的自增长元素从最大的下标+1开始
- 特殊值下标的自动转换:
true下标自动转换为1,false下边自动转换为0,null下标自动转换为空 - PHP中的数组存储在堆区,并分配一块连续的内存
数组遍历
foreach($arr as $k => $v){}
也可以使用each配合list遍历数组
数组的相关函数
- 排序函数:对数组按照ASCII码进行比较
sort():顺序排序(下标重排)
rsort():逆序
asort():顺序排序(下标保留)
arsort():逆序
ksort():顺序排序:按照键名
krsort():逆序
shuffle():打乱顺序 - 指针函数
reset():重置指针,将数组指针回到首位
end():重置指针指向末尾
next():指针下移并取得这个元素值
prev():指针上移并取得这个元素的值
current():获取当前指针对应元素值
key():获取当前指针对应下标值
next和prev使用时可能移出了数组的范围导致出错,所以只能通过end或reset进行指针重置
- 其他函数
count():统计数组中元素数量 array_push():向数组后添加一个元素
array_pop():从数组后取出一个元素 array_shift():从数组前取出一个元素
arrat_unshift():向数组前加入一个元素 array_reverse():数组元素反相
in_array():判断一个元素在数组中是否存在 array_keys():获取一个数组的所有下标,返回一个索引数组
array_values()`:获取一个数组的所有值,返回一个索引数组
1379

被折叠的 条评论
为什么被折叠?



