PHP
一 php语法初步
- 代码标记
现在一般常用php标准标记和脚本标记,前两种基本弃用。其中?>
自带有语句结束符;
的效果,因此最后一行代码可以没有;
。通常书写上不建议使用?>
作为结束符,而且经常会被省略。
//ASP标记
<% php代码 >
//短标记
<? php代码 ?>
//脚本标记
<script='php'>
php代码
<script/>
//标准标记
<?php
echo 'hello!';
>
变量和常量
-
变量
php中变量的声明使用美元符号的形式声明,由于php是弱类型的语言,因此不需要对变量的类型进行强制限定。$var1 = 16;
-
预定变量
指系统提前定义好的变量,可以存储许多需要用到的数据(预定义的变量都是数组)$_GET
:获取表单以get方式提交的数据$_POST
:获取表单以post提交的数据$_REQUEST
:获取get和post方式提交的数据$_GLOBALS
:存放php中所有的全局变量$_SERVER
:存放服务器信息$_SESSION
:存放session会话数据$_COOKIE
:存放cookie会话数据$_ENV
:存放环境信息。如laravel框架中.env
文件中的配置信息可以使用该变量进行获取$_FILES
:存放用户上传的文件信息
-
可变变量
如果一个变量存放的值是另一个变量的变量名,那么就可以通过该变量访问到另一个变量的值。
$var1 = 15;
$var2 = 'var1';
echo $$var2 ; //15
- 变量传值
在php中,存在两种值的传递方式。一种是值传递,只会将变量保存的值传递出去;另一种是引用传递,会将变量存值的内存地址传递出去,这样接收的变量会指向同一块内存地址。
$var1 = 1500;
$var2 = $var1 ; //值传递
$var3 = &$var1; //引用传递
-
常量
在php中,可以有两种方式来声明变量- 使用
define
函数定义:define('常量名' ,'常量值');
- 使用
const
关键字定义:const 常量名=常量值;
常量在定义时不需要使用
$
符号,一旦使用系统会自动认定其为变量。在定义常量时,const
和deefine
两种方法是存在区别的:const
可以在类中使用,用于类常量的定义。define
不可以用于类成员的定义,但可以用于全局常量的定义。const
需要在编译时定义,必须处于最顶端的区域,不能再函数、循环等地方使用,define
是函数,所有能够调用函数的地方都可以使用define
。const
是一种语言结构,define
是一种函数,可以通过第三个参数来进行区分大小写敏感(默认为false
,表示对大小写敏感)。const
只能用于定义普通名称的常量,而define
可以采用表达式,并且能够接收任意表达式作为标量,如define('=_=' , 1<=25);
。在访问特殊名称变量时,需要使用constant(常量名)
来进行访问。
- 使用
-
系统常量
指php系统定义的常量,可以直接使用,如PHP_VERSION
、PHP_INT_SIZE
、PHP_INT_MAX
等。在php中,还存在一些特殊常量,这些常量的值会根据环境变化进行变化,称为魔术常量:__DIR__
:代表当前被执行脚本的绝对路径__FILE__
:代表当前被执行脚本的绝对路径(带文件名)__LINE__
:当前所属的行数__NAMESPACE__
:当前所属的命名空间__CLASS__
:当前所属的类__METHOD__
:当前所属的方法
数据类型
- 数据类型
在php中数据类型指的是数据本身的类型,而不是变量的类型。变量本身并没有数据类型。- 基本数据类型
int/integer , float/double , string , bool/boolean - 复合数据类型
对象类型object,数组类型array - 特殊数据类型
资源类型resource,用于存放外部资源数据,如数据库文件等
空类型NULL,只会有一个值就是null
- 基本数据类型
-类型转换
- 自动转换:由php自己完成,自动进行转化
- 手动强制转换:在需要转换的目标前使用(类型)
来进行强制转换。NULL类型的转换需要使用到unset()
函数
-
类型转换规则
当其他数据类型需要转为数值时true
会被当做1处理,false
会被当做0处理- 以非数字开头的字符串永远为0,数字开头的串会被截取到非数字字符为止
其他类型转为布尔类型时
示例 | true/false | isset() |
---|---|---|
$x = "" | false | true |
$x = null | false | false |
$x is undefined | false | false |
var $x | false | false |
$x = array() | false | true |
$x = false | false | true |
$x = true | true | true |
$x = 1 | true | true |
$x = 0 | false | true |
$x = -1 | true | true |
$x = "1" | true | true |
$x = "0" | false | true |
$x = "true" | true | true |
$x = "false" | true | true |
- 类型判断
基本数据类型可以使用一组函数如is_int()
等来根据返回的布尔值判断,boolean类型可以使用var_dump()
函数来查看
还可以通过getType(变量名)
和setType(变量名)
来进行对变量数据类型的操作。需要注意的是,当使用强制类型转换的时候,并不会对变量保存的数据本身造成影响,是将数据复制一份后进行处理。而setType()
函数会直接改变数据本身的数据类型。如setType($b , 'int');
运算符
- 运算符
php中的运算符比较正常,与java中的运算符差不离(算术、逻辑、位运算等)。重点需要说明的是php中的连接运算和错误抑制符-
连接运算符
.
:表示将两个字符串拼接到一起,
:同样表示将两个字符串拼接到一起,但是与.
有不同之处——echo '1+99=',1+99
会直接输出1+99=100
,而echo '1+99='.1+99
会输出100
,这是因为在参与计算时,.
会先拼接字符串才进行计算.=
:类似于+=
,会将拼接结果赋值回给左边
-
错误抑制符
在没有启用异常处理时,php中的错误会直接输出,在一些错误可以预知时,可以使用错误抑制符@
来避免报出错误信息,如echo @($a/$b)
——避免报出$b
为0的错误
-
流程控制
- 流程控制
同样的,php中的流程控制分为顺序结构
、循环结构
和分支结构
,不做赘述。需要注意的一点是,php会经常嵌入html中,这时书写大括号时会比较不美观,可以用下面的方式代替
if()
//~
endif;
for(;;)
//~
endfor;
文件包含
- 文件包含
指在一个php文件中将另一个php文件包含进来,以实现代码的复用(向上包含)或者是文件内容的使用(向下复用)
文件包含的四种形式:include
或者require
include_once
或者require_once
:系统会自动判断文件是否被包含过,如果包含过就不会再次包含
函数
- 函数
函数是在代码执行阶段调用执行,并不是在编译阶段。因此函数的调用可以在定义之前。
在php中,允许实参的个数多于形参个数,但是实参个数不能少于形参个数。当形参需要有默认值时,应当从最右端开始定义(由于同一个php文件中不允许存在同名函数,因此可以使用默认值来实现函数的重载)。
实参会在调用时将值传递给形参,此时为值传递,如果需要将整个参数传递给形参,这时可以使用&
来完成引用传递
//arg1表示值传递 , $arg2表示为引用传递
function funName(int $arg1 , &$arg2 ...){
//doSomeThings
}
-
函数返回值
php中所有的函数都会返回值,使用return来定义返回值。如果没有使用return显示的指定返回值时,php会默认返回null。
当return在文件中直接使用时,表示文件将return后面的内容转交给包含当前文件的位置(通常在配置文件中使用较多),同时终止该文件中的代码。 -
作用域
-
全局变量作用域——表示全局空间
-
局部变量作用域——表示方法内部的空间
-
超全局变量作用域——没有访问限制(即系统预定义变量)。超全局变量会将全局变量自动纳入
$GLOBALS
中,而$GLOBALS
没有作用域限制,所以能够帮助局部去访问全局变量,但是必须使用数组方式。
在php中还有一种方式也可以实现全局访问局部,局部访问全局——global
关键字。global
关键字是一种在函数里定义变量的方式。- 如果
global
定义的变量在外部存在,那么系统在函数内部定义的变量直接指向外部变量的内存空间 - 如果
global
定义的变量在外部不存在,那么系统会自动在全局空间定义一个与局部变量同名的外部变量。
本质是在函数内外,对同名变量使用同一块内存保存数据,以实现共同拥有。
- 如果
-
<?php
//使用超全局变量来在局部使用全局变量
$global = 'global area';
function display(){
echo $GLOBALS['global'];
}
==============================================
//使用global关键字来实现全局使用局部
function display(){
global $localConf = 'inner';
}
display();
//在外部使用局部定义的变量
echo $localConf;
==============================================
//使用global关键字来实现局部使用全局,但是一般不会这么使用,一般都会使用参数来传递值。
global $outer;
$outer = 'outer';
function display(){
echo $GLOBALS['outer'];
}
- 静态变量
static变量,是在函数内部定义的,用于实现跨函数共享数据的变量。静态变量的使用一般是为了统计函数调用次数,或者是统筹多次调用函数以得到不同结果的(如递归调用时可以使用静态变量)。函数在调用过程中会自动跳过static
修饰的这一行代码,直接去执行下一行。
function display(){
static $count = 1;
echo $count++;
}
display();//1
display();//2
display();//3
- 可变函数
如果一个变量所保存的值是一个函数的函数名,那么就可以使用变量名()
的方式来充当函数名使用。可变函数的使用比较广泛,尤其是在使用很多系统函数时,需要用户在外部定义一个自定义函数,但是需要传入到系统函数内部使用。
//如注册机制进行类的自动加载
function my_autoload($className){
//~
}
spl_autoload_register('my_autoload');
- 匿名函数
即没有函数名的函数,变量保存匿名函数时u,实际上保存得到的是一个对象(closure)。
$func = function(){
//函数体
}
$func();//调用函数
- 闭包
指要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及他们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)结合,称为闭包。
即函数内部有一些局部变量,在函数执行之后没有被释放,是因为在函数内部还有对应的其他函数在引用(函数的内部函数——即匿名函数)
function display(){
$name = __FUNCTION__;
//匿名函数
$innerFunction = function() use($name) {
echo $name;
}
return $innerFunction;
}
$closure = display();
$closure();
-
伪类型
即假类型,在php中不存在的类型,通过伪类型可以帮助程序员更好的查看操作手册Mixed
:可以是多种php中的数据类型Number
:任意数值类型
-
常用的系统函数
print()
:类似于echo()
,本质上是一种结构而不是函数,该结构在执行完毕后会返回1
,可以不使用括号进行调用。print_r()
:类似于var_dump()
,但是更加简单。不会输出数据的类型,只会输出值。在进行数组打印的时候使用较多。date()
:按照指定格式输出对应的时间戳time()
:获取当前时间对应的时间戳microtime()
:获取微秒级别的时间strtotime()
:按照指定规格格式的字符串转换为时间戳,如echo strtotime('now');
,echo strtotime('last Monday');
max() , min() , rand() , round() , floor() , ceil() , sbs() , pow() , sqrt() , mt_rand()
等数学函数function_exist()
:判断指定函数名的函数是否存在,存在则返回1func_get_arg()
:在自定义函数中获取指定参数func_get_args()
:在自定义函数中获取所有的参数func_num_args()
:获取当前自定义函数的参数数目
//获取函数参数等函数的使用
function func_test(){
var_dump(func_get_arg(0));//获取当前函数第一个参数
var_dump(func_get_args());//获取当前函数的所有参数
var_dump(func_num_args());//获取当前函数的参数数目
}
echo function_exist('func_test');
func_test(1,2,3,4,5,6);
错误处理
-
错误处理
php中在没有开启异常处理时,所有的错误都会直接输出。错误分为语法错误(编译时会报错)、运行时错误(编译期不报错)和逻辑错误(正常运行,但是得不到正确结果)。所有的错误代号都在php中定义为了系统常量,可以直接使用- 系统错误:
E_PARSE
:编译期错误E_ERROR
:fatal error,是致命错误,代码无法正常运行E_WARNING
:警告,不会影响代码的正常运行,但是可能得不到正确结果E_NOTICE
:通知,并不会影响代码的运行
- 用户错误:
E_USER_ERROR
,E_USER_WARNING
,E_USER_NITICE
。用户在使用自定义错误触发时,会使用到这些错误代号,系统是不会自动调用的 - 其他
E_ALL
,代表所有的从错误(通常在进行错误控制时使用),建议开发时使用
所有以
E
开头的错误常量其实都是以一个字节存储的,每一种错误对应着一个位置,如果需要进行错误控制,可以使用位运算来进行操作。如排除通知(notice
)级别错误为:E_ALL & ~E_NOTICE
;只显示警告和通知为:E_WARNING | E_NOTICE
- 系统错误:
-
错误触发
在程序运行的过程中,系统会自动根据错误发生后,对比对应的错误信息进行输出,主要针对Pase Error
和Runtime Error
。当然在用户直到某些代码可能出错时,可以使用对应的判断代码来触发相应的错误提示(Trigger_error()
)
Trigger_error
还可以通过第二个参数来进行严格性控制,如限定触发某类错误。但是需要注意的是,该函数并不会阻止系统的报错。
$b = 0;
//使用trigger_error来进行错误触发
if( $b == 0 ){
trigger_error('除数不能为0');
}
//但是trigger_error并不会阻止系统错误的报错,此处系统依然会报错
echo $a/$b;
//还可以使用参数来限制错误触发的严格性
if( $b == 0 ){
trigger_error('除数不能为0');
trigger_error('除数不能为0' ,E_USER_ERROR);
}
-
错误显示设置
用于表明哪些错误应当显示,以及如何显示。在php中有两种方式来设置
当前脚本的错误处理显示:- 在
php.ini
文件中设置:
display_errors = ON
,表示是否显示错误
error_reporting = E_ALL
,表示显示哪些错误 - 在运行的脚本中使用
ini_set()
函数进行设置
ini_set('配置文件中的配置项', '配置值')
,如ini_set('error_reporting' , 'E_ALL');
- 在
-
错误日志显示设置
在实际生产环境中,一般不会让错误直接展示给用户,而是将报错保存到日志中,以便管理员捕捉错误信息。在php中有两种方式来设置对应的error_log
配置项。- 在
php.ini
文件中开启日志并且指定日志路径
log_errors = ON
,error_log=E:/server/php7.2/errlog/php_error.log
- 使用
ini_set()
方法来设置配置项
ini_set('log_errors',1)
,ini_set('error_log','~~~')
- 在
-
自定义错误处理
php中可以由用户自定义错误处理的方式,如trigger_error()
方法就是最简单的错误处理,但是该函数不会阻止系统报错。
php系统提供了一种用户处理错误的机制,即用户自定义错误处理函数,然后将该函数添加到操作系统错误处理的句柄中,这样系统就会在碰到错误之后使用用户定义的错误函数。
对于自定义错误处理函数,系统做了如下要求
handler(int $errno , String $errstr , String $errfile , int $errline , array $errcontext)
- 在自定义错误处理函数中,
$errno
,$errstr
这两个参数为必须要存在的参数,系统在调用自定义错误处理函数时会给前两个参数传递值。 - 除了最开始的两个参数之外,其他的参数为可选参数
- 在自定义错误处理函数中,
function my_error($int $errno , String $errstr , String $errfile , int $errline){
//error_reporting()函数在没有参数时表示获取当前系统中进行错误处理的级别
if(!(error_reporting()) & $errno){
return false;
}
switch($errno){
case E_WARNING:
echo "file:",$errfile;
echo "line:",$errfile;
echo "info:",$errfile;
break;
case E_NOTICE:
echo "file:",$errfile;
echo "line:",$errfile;
echo "info:",$errfile;
break;
case E_ERROR:
echo "file:",$errfile;
echo "line:",$errfile;
echo "info:",$errfile;
break;
}
return true;
}
//将用户自定义的错误处理添加到操作 系统错误处理的句柄中,就可以实现自定义错误处理了
set_error_handler('my_error');
字符串
- 字符串定义
- 单引号字符串:
$string1 = 'abc'
- 双引号字符串:
$string2 = "abc"
- 结构化字符串:
$string3 = <<< 边界符 字符串内容 边界符;
结构化字符串分为nowdoc和heredoc,都可以用于保存字符串的结构,类似于XML中的CDATA结构。但是在使用结构化字符串时,需要注意一些使用规则:- 上边界符后不允许跟任何内容
- 下边界符必须顶格
- 下边界符后必须且只能跟分号
- 边界符中所有内容都是字符串本身
- 单引号字符串:
$str = <<< END
这里是
字符串
的内容
可以保存整体结构
END;
- 字符串相关函数
- 字符串长度函数:
strlen()
- 转换函数:
implode()
:将数组中的元素按照某种规则连接成字符串,如echo implode('?' , $array1)
explode()
:将字符串按规则分割为数组,类似于java中的spilt()
,如explode('?' , $string1)
str_spilt()
:根据指定长度拆分字符串为数组,如str_spilt($string2 , 10);
- 截取函数:
trim()
:默认去除字符串两端的空格,也可以指定去除字符串两边的指定字符,如trim($string , 'a');
ltrim()
和rtrim()
:去掉左边或者去除右边的空格或者指定字符substr()
:表示从指定位置开始截取字符串,可以指定截取长度。如果不指定长度则默认截取到末尾。如echo substr($string , 1 , 3);
strstr()
:表示从指定字符开始,截取到最后,如echo strstr($string , 'c');
- 转换函数:
strtolower()
,strtoupper()
,ucfirst()
:分别表示字符串小写,字符串大写和字符串首字母大写
- 查找函数:
strpos()
:用于判断字符在字符串中首次出现的位置strrpos()
:用于判断字符在字符串中最后一次出现的位置,如echo strrpos()
- 替换函数:
str_replace()
:将目标字符串中部分串进行替换,如str_replace('a' , 'b' , $str)
表示将$str
中的串a
替换为b
- 格式化函数:
printf()
:用于格式化输出数据,使用方法为printf(带占位符的串,顺序占位符内容)
,如printf("我今年%d岁,名字是%s",$age,$name);
。需要注意的是,printf
作为函数是有返回值的,会返回输出的字节数。sprintf()
:同样用来格式化输出数据,使用方法与printf
无异,但是需要注意的是sprintf()
没有返回值- 需要了解的是,在php中的占位符有多种,如
%b
,%c
,%d
,%e
等。还有%s
表示代替字符串类内容(string)
- 其他函数
str_repeat()
:用于重复某个字符串n次,如echo str_repeat($string , 100);
str_shuffle()
:随即打乱某一个字符串,如echo str_shuffle($string);
- 字符串长度函数:
数组详解
- php是弱类型语言,因此与java中数组还存在一些不同之处:
- 数组下标可以为整数也可以为字符串。当下标均为整数时,为索引数组。当下标均为字符串时,为关联数组。不同类型下标同时存在是为混合数组。
- 数组元素顺序以放入顺序为准,与下标无关
- 数字型下标可以自增,从0开始。如果中途手动出现更大的下标,后续自增为最大数加一
- 特殊下标会自动进行替换,如
array[false] => array[0]
,array[true] => array[1]
,array[null] => array[""]
- php中数组元素没有长度和数据类型限制
- php中的数组存放在堆空间中
- 数组遍历
-
foreach
遍历:基本语法为foreach($数组变量 as [$key =>] $value){}
。通常来说,如果遍历的是索引数组,可以直接访问value,因为key一般没有什么意义;如果遍历的是关联数组,那么可以key和value一同访问。
foreach遍历原理:本质上数组中存在着一个指针,默认指向首个元素,foreach会重置指针,让指针指向首个元素。进入foreach之后,将下标取出放入$key
中,将元素取出后放入$value
中 -
for循环遍历:使用for循环遍历时,要求得知数组长度,并且下标为有规律的数字,如
for($i = 0 , $len = count($arr) ; $i<$len ;$i++ ){}
-
while配合each和list遍历,但是while遍历需要在外部定义边界条件。
- each函数能够获取到数组当前指针指向的下标与元素,以一个四元素的数组返回:
0=>取得的元素下标值
1=>取得的元素值
key=>取得的元素下标值
value=>取得的元素值
当each取不到结果(即指针到数组末尾时),返回false
- list是一种结构,没有返回值。list可以提供一些变量从数组中取得元素值,然后依次放入提供的变量中。但是list只能通过索引下标取得元素值,从下标为0开始。因此当使用list将each取到的key-value保存在变量中,就可以实现数组的遍历
- each函数能够获取到数组当前指针指向的下标与元素,以一个四元素的数组返回:
-
$arr = array(1,2,'tom'=>'jerry',4,5,'king'=>'queen');
while(list($key,$value) = each($arr)){
echo 'key:' . $key , 'value: ' . $value , '<br>';
}
- 数组相关函数
- 排序函数:按照ASCII码对数组元素进行排序,可以进行英文比较。
sort()
和rsort()
:都是进行下标重排asort()
和arsort()
:会在保留下标的基础上进行重排,意思是顺序与下标无关ksort()
和krsort()
:会按照下标进行排序,即排序以下标为基准shuffle()
:会随机打乱排序,并且不保留下标usort()
:可以传入函数作为参数来进行自定义排序
- 指针函数
需要注意的是,next和prev有可能导致指针离开数组,导致无法使用。而且有可能通过该两个函数不能回到数组的真实位置,这时需要使用end
和reset
来找到数组的位置。reset()
:重置指针,将指针移回到首位end()
:重置指针,将指针移到末位next()
:指针下移一位prev()
:指针上移一位current()
:获取当前指针对应的元素值key()
:获取当前指针对应的下标值
- 其他函数
count()
:统计数组中元素的个数
array_push()
:向数组中添加一个元素(从后)
array_pop()
:从数组中取出一个元素(从后)
array_unshift()
:向数组中添加一个元素(从前)
array_shift()
:从数组中取出一个元素(从前)
array_reverse()
:将数组整体倒置翻转,并不会操作原数组,会返回一个新数组
in_array()
:判断一个元素在数组中是否存在
array_keys()
:获取数组的所有下标,返回索引数组
array_values()
:获取数组的所有元素,返回索引数组
- 排序函数:按照ASCII码对数组元素进行排序,可以进行英文比较。