函数:function,是一种语法结构,将实现某一功能的代码块(多行代码)封装到一个结构中,从而实现代码的重复利用(复用)。
函数有几个关键点:function关键字,函数名,参数(形参,实参)、函数体和返回值。参考手册
基本语法:以下为定义函数。注意:函数【定义的时候并不会执行】,它只是向系统声明并定义函数。想要使用函数必须调用它。
function 函数名(参数)
{
//函数体;
//返回值;
}
通过访问函数名()来调用函数,如果函数定义的时候有参数,则调用的时候也必须指定参数。
function 第一次函数()//此时定义函数,但并不执行。想要执行必须调用它。
{
echo "第一次使用函数唷!好兴奋!";
}
//以上为函数声明定义,并不执行。注意代码从此处开始执行
echo '你好啊!';
第一次函数();//使用Unicode命名简洁明了,但必须注意老版本可能不支持
*函数定义部分可以放在调用之前,也可以放在之后,不影响使用。但为了阅读流畅性,请将函数定义放在代码首部即调用之前。
原因:编译和执行代码是分开的(先编译、后运行),因此函数定义部分放在哪里并不影响执行(调用)。
由字母、数字、下划线构成,但不能以数字开头。(新版本支持Unicode即汉字和其他全球字母)
驼峰法,例如:myFunction();下划线法,单词间通过下划线连接,例如:this_is_my_function()。
?函数命名规范为什么不使用首字母大写或纯大写?
答:首字大写一般用于类名,例如:MyClass;纯大写一般用于常量,例如:PI。
函数定义时指定的参数为形式参数,用来占位置并表示该参数的数据类型。
例如你对老婆说晚饭给我烧肉菜,这种预先声明的行为,即【声明 老婆做晚饭(肉1,肉2,肉3……)】假如为函数的话,此处你想要的肉菜即为形式参数。因为此时你和你老婆尚未做晚饭,并不知道晚饭时做什么肉菜,但它一定是肉菜。
函数调用时候实际指定的参数为实际参数。
例如接上例,到了晚饭时间,你老婆给你做了红烧肉,回锅肉,四喜丸子等,即【老公调用 老婆做晚饭(红烧肉,回锅肉,四喜丸子)】。此处红烧肉、回锅肉、四喜丸子即为实际参数。你老婆给你做晚饭的行为即为函数调用。因为不止今天给你做晚饭,明天、大后天、活着生生世世都得做晚饭。最后你吃上晚饭了,即代码执行成功。
假如你老婆给你做了素菜,这就是传入参数错误(明明指定肉菜类型非要传入素菜);老婆打你还让你跪搓板,这是函数未正确调用(老婆打你根本不是你调用的!你调用的老婆做晚饭到底在哪里?);如果厨房烧菜时候炸了,即程序崩溃。
上图为函数调用、形参、实参举例。
*PHP允许实参多于形参,不会报错,但这没啥用。切记为了规范不可使用这个特性,大多数其他语言形参-实参必须一一对应。
*php理论上形参个数不限制。但不可使用过多以免造成影响阅读流畅。
*实参不能少于形参个数。
定义函数时会指定形参默认值。调用时,实参如果不指定,则使用定义时的默认值;如果指定实参值,则使用指定的值。
function 加法($参数1=0,$参数2=0)//定义函数时设置参数默认值
{
echo $参数1+$参数2;
echo '
';
}
加法(100,10);//调用时指定2个参数值,则不使用默认值。输出110
加法(100);//调用时指定第1个参数值,则使用定义时默认的第2个参数值。输出100
加法();//调用时不指定参数,则使用定义时默认的2个参数值。输出0
上例展示参数默认值用法。
*默认值定义时放在最后边(多个也是如此)。不可以左边有默认值,右边没有默认值。大多数语言亦是如此规定。
×:function 函数甲($参数1=100,$参数2){/*函数体*/}//错误
√:function 函数乙($参数1,$参数2=100){/*函数体*/}//正确
函数默认传递参数是值传递的,即实参参数变量A传递进函数内部的是变量A的副本而不是变量A本身。这样即使在函数内部改变变量A的值,改变的也仅仅是变量A的副本,并不会改变变量A本身。
如果函数参数使用引用传递,那么变量A传递进函数内部的是变量A本身(即变量A内存地址)而不是副本。这样如果在函数内部改变变量A的值,变量A的值会真正改变。
echo '函数调用:引用传递和值传递对比
';
function funA(&$a)//按引用传递。传递进来的变量$a本身会被函数内部操作改变。
//按引用传递时,传递进来的必须是变量,因为变量才有自己的内存地址。
{
$a=100;
}
function funB($b)//按值传递。传递进来的变量$b副本会被函数内部操作改变,但变量$b本身不会改变
{
$b=100;
}
$x=0;
funA($x);
echo $x;//$x已经被funA函数改变,输出100
echo '
';
$x=0;
funB($x);
echo $x;//$x本身并没有被funB函数改变,输出0
echo '
';
//出错演示:演示时请去掉下一行语句前的注释符号//
//funA(100);//致命错误!因为funA函数定义的时候是按引用传递,只有变量做函数参数才可以按引用传递!
上例显示函数参数按引用传递和按值传递的区别。编程时请根据实际环境使用恰当的传值方式。
函数内部即花括号{}内的所有代码称为函数体。
返回值:return,指的是将函数计算的结果,通过return关键字(同时结束、退出函数),返回给函数,即函数调用之后有了函数返回值。在php函数中所有函数都有返回值。(如果没有明确使用return,那么系统默认返回NULL)
上例中,display函数没有设置返回值,则默认返回值为NULL,如图。
返回值作用:将计算结果返回给调用处。
上图代码展示函数返回值的用处。函数add定义两数加法,函数返回值是两数之和。调用时计算10+20之和,并将函数返回值赋值给$res。最后输出$res值.
1、return在函数内部存在的价值:返回当前函数的结果,并结束退出函数执行。
2、return还可以在文件中直接使用:代表本文件将return后面跟的内容,返回给包含(include)它的文件。同时也结束、退出本文件的执行。
//main.php文件
$res = include_once 'sub.php';
echo $res;//输出sub.php has been called
//sub.php文件
return 'sub.php has been called';//本文件返回指定内容。并且结束本文件执行
//return后面的语句(如果有的话)将不会执行,因为return已结束本文件代码执行
echo 'test';//不会被执行
如上例演示文件return。按上例内容建立两个文件main.php和sub.php,然后执行main.php,则输出sub.php has been called。
作用域:变量(常量)能够被访问的区域。
全局变量:所属全局空间。在php中只允许在全局空间中使用,理论上函数内部不可以使用。
脚本周期:执行到最后1行代码
局部变量:函数内部定义的变量。所属当前函数空间。php中只允许在当前函数内部使用。
函数周期:到函数执行结束。
超全局变量:系统定义的变量,如预定义变量等。任何地方都可以访问。
*由于函数内部不能访问全局变量,可通过系统定义的预定义变量变相的访问。
如上例,在函数内部通过系统预定义变量$GLOBALS来访问全局变量。
在PHP中,其实还有一种方式,能够实现局部访问全局,全局访问局部:global关键字。
global关键字:是一种在函数中定义变量的方式。
1、如果在函数内部中使用global定义的变量名在全局中存在,则两者为一。
2、如果在函数内部中使用global定义的变量名在全局中不存在,则系统自动在全局空间定义同名全局变量,两者为一。
语法:global 变量名;//注意声明时不能赋值。
';
/*--------------------*/
$真全局变量='我是在全局空间定义的真全局变量
';
function 测试函数甲(){
global $真全局变量;//由于全局空间存在$真全局变量,此刻二者合一。
echo '测试函数甲中输出:'.$真全局变量;
//通过这种方式函数内部可以真正访问到已存在的全局变量
}
测试函数甲();//调用函数甲
/*--------------------*/
function 测试函数乙(){
global $测试函数乙定义的全局变量;
$测试函数乙定义的全局变量='我是在测试函数乙内部定义的全局变量
';
//通过这种方式在函数内部声明、赋值全局变量
}
测试函数乙();//调用函数乙
echo $测试函数乙定义的全局变量;//在全局中可以访问到函数乙内部定义的全局变量
上例演示如何在函数内部访问已存在全局变量;在函数内部中定义全局变量。
*注意:为了代码结构化模块化和阅读流畅性,请不要在全局中访问局部,也不要在局部中访问全局。
静态变量:声明时使用static关键字修饰局部变量。
普通的函数局部变量为动态变量,当函数调用结束,局部变量清空,下一次函数调用局部变量会重新初始化。而静态变量在函数调用结束也不会清空,会一直保留原值。
echo '静态变量演示
';
function testFunction()
{
static $count =0;//声明静态变量并赋初值。注意初值仅赋值(执行)一次。
$count++;
echo 'testFunction()被调用次数:'.$count.'
';
//虽然此时函数执行结束,$count作为静态变量,值并未清空,而是一直保留。
//如果声明$count变量时没有声明为静态变量,则值不保留,试试看去掉static会有什么不同
}
testFunction();
testFunction();
testFunction();
//调用几次则显示调用次数。如果在函数声明时不使用static定义为静态变量,则永远显示调用次数为1.?为什么?
可变函数:当前一个变量所保存的值,刚好是一个函数的名字,那么可以使用变量名+()的形式来充当函数使用。
如上图代码。通过变量$func来调用display()函数,注意调用的格式为$func();括号必不可少的。
可变函数在系统的使用过程中还是比较多的。尤其是使用很多的系统函数的时候,需要用户在外部定义一个自定义函数,但是需要传入到系统函数内部使用。
以上演示可变函数的用途。
基本概念:没有名字的函数。
基本语法:$变量名=function(){/*函数体*/};//注意函数结尾一定要有分号!
调用:使用$变量名+();来调用。
上图代码演示如何使用匿名函数。如图,变量中存储的实际上是一个对象Closure。
闭包:closure,一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。
简单理解:函数内部有一些局部变量(要执行的代码块)在函数执行之后没有被释放,是因为在函数内部还有对应的函数在引用(函数的内部函数:匿名函数)。
PHP伪类型有三种,分别是:1,mixed混合类型。2,number数字类型。3,callback回调类型。
print():类似于echo函数,本质是一种结构(不是函数),返回1,可以不使用括号。
print_r():类似于var_dump函数。但是比var_dump简单。不会输出数据的类型,只会输出值(数组打印比较多)。
下图为示例。
date():按照指定格式对应的时间戳(1970年格林威治时间开始计算的秒数),如果没有指定特定时间戳,那么默认为当前时间戳。
time():返回自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。
mircotime():返回当前 Unix 时间戳和微秒数
下图为时间函数示例:
strtotime():按照规定格式的字符串转换成时间戳。
function_exist():判断指定的函数是否在内存中存在(帮助用户不去使用一个不存在的函数,让代码安全性更高)
func_get_arg():在自定义函数中去获取指定数值对应的参数
func_get_args():在自定义函数中去获取所有的参数(数组)
func_num_args():获取当前自定义函数的参数数量
以上为演示。注意php允许实参多于形参。但是这个特性没有卵用,为了代码规范也没有必要使用这个特性。
1语法错误:拼写错误。编译不通过。(parse error)
2运行时错误:代码编译通过,但是代码在执行的过程中会出现一些条件不满足导致的错误(runtime error)
3逻辑错误:程序员编写代码出现逻辑性错误,导致代码运行正常,但却得不到正确或想要的结果。
如上图代码,逻辑错误基本很难查出来!
所有看到的错误代码在php中都被定义成系统常量(可以直接使用)
E_PARSE:编译错误。代码不会执行
E_ERROR:fatal error 致命错误,会导致代码不能正确继续执行(出错的位置断掉)
E_WARNING:warning 警告错误。不会影响代码执行。但是可能得到意想不到的结果。
E_NOTICE:notice 通知错误。不会影响代码执行
E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE
用户在使用自定义错误触发的时候,会使用到的错误代号(系统不会用到)
E_ALL,代表所有错误。(通常在进行错误控制的时候使用比较多),建议在开发过程中(开发环境)使用
所有以E开头的错误常量(代号)其实都是由一个字节存储,然后每一种错误占据一个对应的位。如果想进行一些错误的控制,可以使用位运算进行操作。
例如:排除通知级错误notice:E_ALL & ~E_NOTICE
只要警告和通知:E_WARNING | E_NOTICE
程序运行时系统自动触发:代码有错误,系统自动触发错误
人为触发:知道某些逻辑可能会出错,从而写相应的判断代码来处理错误。
上图代码产生1个致命错误。系统捕获该错误并显示错误信息,代码执行中止。
trigger_error(自定义错误提示):用于触发一个用户级别的错误条件,它能结合内置的错误处理器所关联,或者可以使用用户定义的函数作为新的错误处理程序
function chufa($a,$b)
{
if($b==0){//如果除数为0
trigger_error('错误!除数不能为0!');//人为触发错误,默认触发notice,会继续执行
return;
}
return $a/$b;
}
chufa(100,0);//除数为0,代码捕获错误
假如是 trigger_error('除数不能为0!',E_USER_ERROR);则指定触发的是error,代码不会继续执行。
因此,我们可以通过第二个参数进行严格性控制。
哪些错误应该显示,以及该如何显示。
在php中,其实有两种方式来设置当前脚本的错误设置。
1php配置文件:全局配置。php.ini
display_errors:是否显示错误。
error_reporting:显示什么级别的错误。默认是E_ALL显示所有错误。
2可以在运行的php脚本中设置:脚本中的配置项级别比php全局配置php.ini的要高。但脚本一定要执行。
error_reporting():设置对应的错误显示级别
ini_set('配置文件中的配置项',配置值):
ini_set('error_reporting',E_ALL);
ini_set('display_errors',1); 1代表true
需要先开启日志:log_errors = on (php.ini文件中开启设置)
err_log项:在php.ini中或者脚本中配置以记录错误日志。
例如err_log = 'e:/server/php5/log/php_errors.log'
最简单的错误处理:trigger_errors函数,但它不会阻止系统报错。
php系统提供了一种用户处理错误的机制:用户自定义错误处理函数,然后将该函数增加操作系统错误处理的句柄中,然后系统会在碰到错误之后,使用用户定义的错误函数。
1如何将用户自定义函数放到系统中去?使用set_error_handler()函数。
2自定义错误处理函数
代码实现:1自定义错误处理函数:注意参数
视频:https://www.bilibili.com/video/av12863134/?p=75
2注册用户自定义函数:定义用户自己的错误处理机制