php学习笔记03:函数、错误处理

函数

函数的基本概念

函数: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 '<br>';
}
加法(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 '函数调用:引用传递和值传递对比<br>';
function funA(&$a)//按引用传递。传递进来的变量$a本身会被函数内部操作改变。
//按引用传递时,传递进来的必须是变量,因为变量才有自己的内存地址。
{
$a=100;
}
function funB($b)//按值传递。传递进来的变量$b副本会被函数内部操作改变,但变量$b本身不会改变
{
$b=100;
}

$x=0;
funA($x);
echo $x;//$x已经被funA函数改变,输出100
echo '<br>';

$x=0;
funB($x);
echo $x;//$x本身并没有被funB函数改变,输出0
echo '<br>';

//出错演示:演示时请去掉下一行语句前的注释符号//
//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 变量名;//注意声明时不能赋值。

<?php
echo '在函数内部使用global关键字示例<br>';
/*--------------------*/
$真全局变量='我是在全局空间定义的真全局变量<br>';
function 测试函数甲(){
	global $真全局变量;//由于全局空间存在$真全局变量,此刻二者合一。
	echo '测试函数甲中输出:'.$真全局变量;
	//通过这种方式函数内部可以真正访问到已存在的全局变量
}
测试函数甲();//调用函数甲
/*--------------------*/
function 测试函数乙(){
	global $测试函数乙定义的全局变量;
	$测试函数乙定义的全局变量='我是在测试函数乙内部定义的全局变量<br>';
	//通过这种方式在函数内部声明、赋值全局变量
}
测试函数乙();//调用函数乙
echo $测试函数乙定义的全局变量;//在全局中可以访问到函数乙内部定义的全局变量

上例演示如何在函数内部访问已存在全局变量;在函数内部中定义全局变量。

*注意:为了代码结构化模块化和阅读流畅性,请不要在全局中访问局部,也不要在局部中访问全局。

静态变量

静态变量:声明时使用static关键字修饰局部变量。

普通的函数局部变量为动态变量,当函数调用结束,局部变量清空,下一次函数调用局部变量会重新初始化。而静态变量在函数调用结束也不会清空,会一直保留原值。

echo '静态变量演示<br>';

function testFunction()
{
	static $count =0;//声明静态变量并赋初值。注意初值仅赋值(执行)一次。
	$count++;
	echo 'testFunction()被调用次数:'.$count.'<br>';
	//虽然此时函数执行结束,$count作为静态变量,值并未清空,而是一直保留。
    //如果声明$count变量时没有声明为静态变量,则值不保留,试试看去掉static会有什么不同
}
testFunction();
testFunction();
testFunction();
//调用几次则显示调用次数。如果在函数声明时不使用static定义为静态变量,则永远显示调用次数为1.?为什么?

可变函数

可变函数:当前一个变量所保存的值,刚好是一个函数的名字,那么可以使用变量名+()的形式来充当函数使用。

如上图代码。通过变量$func来调用display()函数,注意调用的格式为$func();括号必不可少的。

可变函数在系统的使用过程中还是比较多的。尤其是使用很多的系统函数的时候,需要用户在外部定义一个自定义函数,但是需要传入到系统函数内部使用。

以上演示可变函数的用途。

匿名函数

基本概念:没有名字的函数。

基本语法:$变量名=function(){/*函数体*/};//注意函数结尾一定要有分号!

调用:使用$变量名+();来调用。

上图代码演示如何使用匿名函数。如图,变量中存储的实际上是一个对象Closure。

闭包:

闭包:closure,一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。

简单理解:函数内部有一些局部变量(要执行的代码块)在函数执行之后没有被释放,是因为在函数内部还有对应的函数在引用(函数的内部函数:匿名函数)。

伪类型:

PHP伪类型有三种,分别是:1,mixed混合类型。2,number数字类型。3,callback回调类型。

常用系统函数

1、有关输出的函数:

print():类似于echo函数,本质是一种结构(不是函数),返回1,可以不使用括号。

print_r():类似于var_dump函数。但是比var_dump简单。不会输出数据的类型,只会输出值(数组打印比较多)。

下图为示例。

2、有关时间的函数:

date():按照指定格式对应的时间戳(1970年格林威治时间开始计算的秒数),如果没有指定特定时间戳,那么默认为当前时间戳。

time():返回自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。

mircotime():返回当前 Unix 时间戳和微秒数

下图为时间函数示例:

strtotime():按照规定格式的字符串转换成时间戳。

3、有关数学的函数:参考手册

  • abs — 绝对值
  • acos — 反余弦
  • acosh — 反双曲余弦
  • asin — 反正弦
  • asinh — 反双曲正弦
  • atan2 — 两个参数的反正切
  • atan — 反正切
  • atanh — 反双曲正切
  • base_convert — 在任意进制之间转换数字
  • bindec — 二进制转换为十进制
  • ceil — 进一法取整 向上取整 *注意负数
  • cos — 余弦
  • cosh — 双曲余弦
  • decbin — 十进制转换为二进制
  • dechex — 十进制转换为十六进制
  • decoct — 十进制转换为八进制
  • deg2rad — 将角度转换为弧度
  • exp — 计算 e 的指数
  • expm1 — 返回 exp(number) - 1,甚至当 number 的值接近零也能计算出准确结果
  • floor — 舍去法取整 向下取整 *注意负数
  • fmod — 返回除法的浮点数余数
  • getrandmax — 显示随机数最大的可能值
  • hexdec — 十六进制转换为十进制
  • hypot — 计算一直角三角形的斜边长度
  • intdiv — 对除法结果取整
  • is_finite — 判断是否为有限值
  • is_infinite — 判断是否为无限值
  • is_nan — 判断是否为合法数值
  • lcg_value — 组合线性同余发生器
  • log10 — 以 10 为底的对数
  • log1p — 返回 log(1 + number),甚至当 number 的值接近零也能计算出准确结果
  • log — 自然对数
  • max — 找出最大值
  • min — 找出最小值
  • mt_getrandmax — 显示随机数的最大可能值
  • mt_rand — 生成更好的随机数。注:和rand函数功能一样,但效率更高。
  • mt_srand — 播下一个更好的随机数发生器种子
  • octdec — 八进制转换为十进制
  • pi — 得到圆周率值
  • pow — 指数表达式 即求幂
  • rad2deg — 将弧度数转换为相应的角度数
  • rand — 产生一个随机整数(指定区间的随机整数)。例如想要 5 到 15(包括 5 和 15)之间的随机数,用rand(5, 15)
  • round — 对浮点数进行四舍五入
  • sin — 正弦
  • sinh — 双曲正弦
  • sqrt — 求平方根
  • srand — 播下随机数发生器种子
  • tan — 正切
  • tanh — 双曲正切

 

4、有关函数的函数:

function_exist():判断指定的函数是否在内存中存在(帮助用户不去使用一个不存在的函数,让代码安全性更高)

func_get_arg():在自定义函数中去获取指定数值对应的参数

func_get_args():在自定义函数中去获取所有的参数(数组)

func_num_args():获取当前自定义函数的参数数量

以上为演示。注意php允许实参多于形参。但是这个特性没有卵用,为了代码规范也没有必要使用这个特性。

错误处理

错误分类:

1语法错误:拼写错误。编译不通过。(parse error)

2运行时错误:代码编译通过,但是代码在执行的过程中会出现一些条件不满足导致的错误(runtime error)

3逻辑错误:程序员编写代码出现逻辑性错误,导致代码运行正常,但却得不到正确或想要的结果。

如上图代码,逻辑错误基本很难查出来!

错误代号:

所有看到的错误代码在php中都被定义成系统常量(可以直接使用)

1系统错误

E_PARSE:编译错误。代码不会执行

E_ERROR:fatal error 致命错误,会导致代码不能正确继续执行(出错的位置断掉)

E_WARNING:warning 警告错误。不会影响代码执行。但是可能得到意想不到的结果。

E_NOTICE:notice 通知错误。不会影响代码执行

2用户错误:

E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE

用户在使用自定义错误触发的时候,会使用到的错误代号(系统不会用到)

3其他:

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注册用户自定义函数:定义用户自己的错误处理机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值