楠Go随笔

第十课:PHP函数介绍

2018-01-27 16:38:46 admin 阅读 网站首页 > PHP > PHP学习

什么是PHP函数?

在面向过程的编程中,每一次需要完成一个功能就需要写入一些代码来实现,当代码量有点多的时候或者有好几块地方需要用到相同的代码时(比如登录检测模块)要去维护、修改和调错时就显得有点力不从心,还会让整个程序显得冗长、可读性差。几乎所有的编程语言都支持函数,函数指的是可以实现某一功能的代码块,通过抽离代码和传入参数的方式可以实现复用,减轻代码量,提高开发效率,在团队开发中尤其重要,编写完函数供团队其他成员调用的时候,其他人不必关心其中的实现细节。在PHP中不仅有系统函数还可以有自定义函数。函数可以接受一组函数,返回结果。

系统函数

系统自带的完成特定功能的代码块,主要可以分为以下几类函数。

字符串函数

数组函数

文件函数

            经常使用的有两个引入文件的函数,但是在细节上又有点小区别

                include() 引入文件,遇到错误给出提示并继续向下运行,可以放在文件的任意位置

                require() 引入文件,遇到错误终止运行,须放在文件的头部,常用于导入核心库文件

           有些情况下不允许重复导入文件,但是由于工程庞大,文件很可能在其他地方导入到PHP环境,如导入函数库文件的时候重复导入会导致系统报错,这个时候需要用到上述两种函数的变体,要求该文件只导入一次,避免重复导入造成系统异常。

                include_once()

                require_once()

           导入文件的返回值

                导入成功 文件没有返回值的时候返回 1 有返回值则返回值

                导入失败 include 返回false require 则直接终止运行

自定义函数

用户自己来定义的函数,定义函数的时候需要用关键字 function 来声明,函数名命名规则与变量名命名规则一样,但是PHP在函数名大小写上管制比较松散,允许用大写定义的函数名然后以小写的方式去调用,在使用中要注意,不建议这样做。并且自定义函数不允许同系统函数重名。函数可以在使用前定义和使用后定义,加载PHP文件,环境会先把函数定义读入环境。如下所示

<?php
#定义自己的一个函数 function myfunc($name) {     #声明函数需要用关键字 function     #函数名遵循标识符命名规则 但大小写管制松散     #函数名不允许同系统函数重名 否则系统报错 有些版本部分系统函数不存在 这个时候为了兼容 需要做判断     # function_exists 函数用于判断指定函数名函数是否存在 适用于系统函数和自定义函数     if(!function_exists('print')){         echo "自定义函数:".$name;     } else {         print('自定义函数调用系统函数打印输出:'.$name);     } }
?>


普通函数由 函数声明关键字、函数名、形参列表和函数体组成。形参列表中如果有多个参数,参数间用逗号,隔开,需要记住的时在PHP中没有重载函数的存在。重载的概念是函数名相同,形参个数或者类型不同就属于重载函数。由于PHP是弱类型语言,只有在执行的时候才能确定变量的类型,而且PHP支持默认参数和不定长参数,这就使得PHP不存在重载函数。

自定义函数体内就是一个封闭的环境,除了常量、函数和超全局数组变量外,函数体是不能直接去使用外部内容的,这时候要么用参数传递的方式传进来,要么在函数体内声明变量是一个全局变量。

参数传递  有两种方式 值传递 和 引用传递

    值传递

        传递进来的变量是外部变量的一个副本,一个拷贝。修改该变量值不会影响外部变量

    引用传递

        传递进来的变量是外部变量的引用,修改该变量的值同时会影响到外部变量,声明引用变量需要在形参变量前面加上 & 作用符

需要注意的是,在接下来讲解的类的编程中的对象不管是引用还是值传递都是传递对象的编号,也就是对同一对象做操作,除非调用对象的克隆命令复制出一份副本。

<?php
class Person  {     public $name;     public $age;     public $sex;     function __construct()     {              }     public function show() {         echo "name:{$this->name}  age:{$this->age}  sex:{$this->sex}\n";     } } $person = new Person(); $person->name = '苍苍'; $person->age = 35; $person->sex = '男'; $name = '苍井优'; $age = 25; $sex = '女'; echo $person->show(); setInfo($name,$age,$sex,$person); function setInfo($name,$age,&$sex,$person) {     $person->name = $name;     $person->age = $age;     $person->sex = $sex;     $sex = '未知'; } echo $person->show(); echo $sex; setInfo($name,$age,$sex,$person); function setInfo2($name,$age,$sex,&$person) {     $person->name = $name;     $person->age = $age;     $person->sex = $sex;     $sex = '男'; } $name = '苍井空'; $age = 20; $sex = '女'; setInfo2($name,$age,$sex,$person); echo $person->show(); echo $sex; exit;
?>

声明全局变量

在函数内部使用外部变量需要用global关键字将该变量声明为全局变量,对该变量的修改将会在外部表现出来。

<?php
#导入配置文件 将返回值赋予 config变量 $config = include './config.php'; function connectDB() {     #声明该变量为全局变量     global $config;     #链接数据库 返回数据库句柄     return DB::connect($config); }
?>

 递归函数

在PHP函数中,递归函数是一种特殊的函数类型,所谓的递归函数应该与函数嵌套区分开来,函数嵌套就是在一个函数体内调用其他函数,通常一个实现复杂功能的函数不会是单一函数,函数体内会使用其他系统函数或自定义函数来拓展实现,整个函数体内的逻辑应该是自上而下,逐层细化,大函数里包括其他实现某一功能的函数,来组合实现。而递归函数就是函数体内部会反复调用自身,直到不满足条件退出。如果不设立终止条件,将会形成死循环,耗尽PHP资源。利用递归函数是为了简化流程和应对未知的分支循环情况。递归很强大,几乎所有的循环语句都可以用递归来实现,而递归还能实现循环语句实现不了的功能。比如我想从树形结构中某一节点找到该节点的叶子节点,由于不知道需要循环的次数,采用递归的方式显得更加方便。

下面就用循环和递归的方式演示递归阶乘的例子。

<?php
#循环实现阶乘 $result = 1; for($i=1;$i<=6;$i++) {     $result *= i; } echo $result;
?>
<?php
#递归实现阶乘 function JieCheng($num) {     if ($num==1) {         return 1;     } else {         return JieCheng($num-1)*$num;     } } echo JieCheng(8);
?>

可变函数

PHP支持用变量存储函数名称的功能,提升了PHP的灵活性。在变量后追加小括号时,PHP将自动解析变量是否为一个函数名,如果是的话直接执行函数。

<?php
function plus($num1,$num2) {     return $num1+$num2; } function reduce($num1,$num2) {     return $num1-$num2; } function getWay($type){     if($type==0) {         return 'reduce';     } else {         return 'plus';     } } $type=0; $result = getWay($type); #最后这一句 调用字符串变量加函数运算符 尝试执行函数 echo $result(10,3);
?>


匿名函数

PHP5.3以上版本支持匿名函数,指的是临时创建一个没有指定名称的函数。一般用途有三种。匿名函数目前是通过 Closure 类来实现的。

第一种 用于回调函数,当模块处理好需要对获取结果做进一步过滤或整合。

<?php
$str = 'afd-LKjfimfolfdsf-,foSA25'; function matchContent($str,$func) {     $data = array();     if (preg_match('/-([a-zA-Z]+)-/',$str,$data)){         return $func($data[1]);     } else {         return false;     }     return $func($match); } $result = matchContent($str,function($data){     return strlen($data); }); if ($result) {     echo $result; } else {     echo "匹配失败"; }
?>

第二种 把匿名函数当做变量来使用,PHP自动将表达式转换为内置类Closure的对象实例,与普通变量赋值一样,结尾要用分号;隔开

<?php
$func1 = function($data) {     echo "my function msg :{$data}"; }; $func1('hello function');
?>

第三种 从父作用域继承变量 匿名函数也是函数的一种 没法直接使用外部变量,当匿名函数提供继承功能,可以将外部变量传入其中,通过use关键字可以继承父变量 多个变量用逗号,隔开

<?php
$name = 'PHP5.3'; $msg = 'PHPer is good at code!'; function showMessage($type,$func){     if ($type==1) {         $date = date('Y-m-d H:i:s',time());     } else {         $date = date('Y-m-d',time());     }     $func($date); } showMessage(1,function($date) use($name,$msg){     echo $date.'-------'.$name.'------------'.$msg; });
?>

注意的是,PHP函数中出现return语句时将结束函数运行,将控制权交回上层调用,后面的代码块将不再执行。

闭包 

闭包其实就是函数中定义函数。姑且称为父子函数,子函数可以为普通函数或者匿名函数,与一般函数加载的情况不同,闭包函数中的子函数是在父函数执行的时候才动态载入。

为什么需要闭包了?

大多数情况下我们需要隐藏函数的内部细节,函数内部也无法直接使用外部变量。但有些情况下,又需要与函数内部保持沟通,这个时候闭包的作用就体现出来了,它充当一座桥梁。实现内部与外部的通信。

闭包的使用

    函数内部定义函数并使用

<?php
function myfunc($str) {     $func1 = function($data) use($str) {         return $data.$str;     };     echo $func1('print:'); } myfunc('define and use it!');
?>

    函数内部定义函数并返回匿名函数变量

<?php
function myfunc($str) {     $func1 = function($data) use($str) {         return $data.$str;     };     #返回匿名函数变量     return $func1; } #返回匿名函数变量 $func1 = mufunc('define and use it!'); #添加函数运行符执行该段命令 可以发现myfunc 中的局部变量能被匿名函数调用 所以内存中myfunc局部变量没有释放 因为 匿名函数依赖于父函数 匿名函数不释放 父函数资源也不会释放 这就实现了内部与外部的通信 echo $func1('print:');
?>

需要注意的是,虽然闭包内部定义普通函数,但是普通函数相当于定义一段代码块存入内存中直到程序运行结束才释放,而匿名函数则是想当于定义一个变量,当该引用计数器为0时会自动释放。如果试定义普通函数,重复调用父函数会报redeclare重复定义函数错误,从资源加载和占用空间的角度考虑 显示用匿名函数做闭包更适合。虽说闭包可以实现内部与外部的通信,但是子函数使用的父变量是父函数的副本,需要采用引用方式才能实现可读可写,如下。

<?php
function myfunc() {     $num = 1;     #不妨把 & 符号去掉 运行看执行结果 再加深理解闭包的概念     $func1 = function() use(&$num) {         var_dump($num);         $num++;     };     return $func1; } $func1 = myfunc(); $func1(); $func1(); $func1();
?>

这一节课我们讲解PHP函数,从系统函数过渡到自定义函数,以及自定义函数分类及使用。PHP没有重载函数概念,当函数参数长度不确定时可以在函数体内调用 func_num_args() 函数获取形参个数,用 func_get_args() 获取形参组成的数组 key 为变量名 value 为变量值。最后又匿名函数引申到闭包,我们只需要了解闭包的概念和作用以及形式,通常情况下不会过多的用到,一些PHP框架的底层会采取这种做法,有它的优点也有相应的缺点,在工程开发中应该折中考虑,如果频繁使用闭包函数没法及时释放会导致内存使用过大。了解闭包,在深入学习PHP时,在阅读优秀源码时可以加深理解又可以感受到代码的优雅。

闭包参考资料:http://www.cnblogs.com/yjf512/archive/2012/10/29/2744702.html

搜索

关于楠Go

2015年毕业于吉林大学珠海学院,现今工作已两年有余,2014年在珠海一家游戏公司从事手机游戏开发,后离职转型为网络端PHP工程师,时至今日。熟练掌握PHP面向对象编程网络编程TP框架使用Discuz论坛插件开发。掌握前端框架Bootstrap的使用,掌握JS框架Jquery的使用。已开发多款网站,有着一定基础的开发经验,希望能在互联网领域再上一层楼!

了解更多: 开源中国 ThinkPHP


Powered by MetInfo 5.3.19 ©2008-2018 www.MetInfo.cn