0%

函数的用法及封装、变量范围

函数的定义

函数function是一段完成指定任务的已命名代码块。函数可以遵照给它的一组值或参数完成特定的任务,并且可能返回一个值。在PHP中有两种函数:自定义函数与系统函数

函数的优点:

  • 控制程序设计的复杂性
  • 提高软件的可靠性
  • 提高软件的开发效率
  • 提高软件的可维护性
  • 提高程序的重用性

自定义函数

自定义函数语法格式:

1
2
3
4
function  函数名称([参数1 [,参数2 [,…]]]){
程序内容叙述(也叫函数体);
[return 返回值;] //如需函数有返回值时使用
}

函数的使用:

1
函数名称([参数1 [,参数2 [,…]]]);

自定义函数的名称:

它是函数在程序代码中的识别名称,函数名可以是以字母或下划线开头后跟零个或多个字母、下划线和数字的任何字符串。函数名不区分大小写。命名函数时不可使用已声明的函数,或PHP内建的函数名称。

参数:

所谓的参数就是用来把数值由函数外部传入函数体中,并用来加以运算处理。参数之间用“ ,”号隔开。当函数不需要任何数值传入时,可以省略参数。

返回值:

当调用函数时需要它返回一些数值,那么就要函数体中用return语句实现。格式如下:

1
2
return  返回值;    //返回值也可以是一个表达式
exit(); //无返回值 void

示例

1
2
3
4
5
6
7
8
9
10
11
12
<?php
echo "用函数求累加:<br>";
function test($a)
{
$sum=0;
for($i=0;$i<=$a;$i++)
$sum+=$i;
return $sum;
}
echo "50的累加是:".test(50)."<br>";
echo "100的累加是:".test(100)."<br>";
?>

判断函数是否存在

function_exists() - - 判断函数是否存在。

1
2
var_dump(function_exists('mkdir'));
//判断系统函数mkdir是否存在,输出bool(true)

PHP变量的范围

变量的范围意指变量在程序中的可作用范围。当一个变量执行赋值动作后,会随着声明局部的差异,而有不同的作用范围。大致上来说变量会依据声明的局部分为下列两种:局部变量和全局变量

局部变量(内部变量)

在函数之中声明的变量就是局部变量,并且该变量只有在函数范围之中才能加以使用。如果其它程序局部需要调用使用该变量值时,必须通过return指令,来将其传回至主程序区块以作后续处理。

1
2
3
4
5
6
7
8
9
$a=0;
function print_A(){
$a = 3; //定义局部变量
echo "在函数中显示局部变量 a 值: $a <p>"; //输出a的值是3
return $a;
}
$b = print_A();
echo "在函数外显示局部变量 b 值: $b <br>"; //输出a的值是3
echo $a; //输出a的值是3

全局变量

  • 在函数范围之外所声明的变量就是全局变量。由于函数可以视为单独的程序片段,所以局部变量会复盖全局变量的能见度,因此在函数中并无法直接调用使用全局变量
  • 函数中若要使用全局变量时,必须要利用global关键字定义目标变量,以告诉函数主体此变量为全局。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $a = 5;
    function print_A(){
    global $a;
    $a = 10;
    echo "在函数中显示全局变量 a 值: $a <p>"; //输出a的值是10
    return $a;
    }
    $b = print_A();
    echo "在函数外显示全局变量 b 值: $b <br>"; //输出a的值是10
    echo $a; //输出a的值是10
  • 也可以使用预定义的全局变量数组$GLOBALS.这是一个特殊变量在程序运行时自动创建。格式:echo $GLOBALS["变量名"];
    1
    2
    $a = 5;
    echo $GLOBALS["a"]; //输出5

注意事项

  • 在函数中声明全局变量时,其名字要与全局变量一致
    通过unset($var)可以手动删除变量,变量会在内存中被释放,也就不在全局作用域中了。
  • 使用requireinclude包含不会影响作用域
  • 通过参数列表传递给函数的变量,对于函数来说是局部变量,除非在传递时带有&引用符号

静态变量

PHP支持声明函数变量为静态的static。一个静态变量在所有对该函数的调用之间共享,并且仅在脚本的执行期间函数第一次被调用时被初始化。要声明函数变量为静态的用关键字static。通常,静态变量的第一次使用时赋予一个初始值。

1
2
3
4
5
6
7
8
9
10
function test() {
static $a = 0; //声明静态变量a的初始值为0
echo $a; //输出a的值
$a++; //每次调用函数后a的值+1
}
test(); //调用第一次输出a的值为0
test(); //调用第二次输出a的值为1
test(); //调用第三次输出a的值为2
test(); //调用第四次输出a的值为3
test(); //调用第五次输出a的值为4

声明及应用各种形式的PHP函数

常规参数的函数

  • 函数的实参和形参应该个数相等、类型一致
  • 调用时传递的参数个数和顺序必须一致

chr()

传递进去ascii码,返回对应的ascii

1
var_dump(chr(65));      //输出string(1) "A"

ceil()

进一法取整,返回float类型整数

1
var_dump(ceil(5.44411111)); //输出float(6)

array_combine()

合并一个数组,第一个传参key值,第二个传参value值,返回一个数组

1
2
3
$info = array('1','2','3');
$info2 = array('a','b','c');
var_dump(array_combine($info,$info2));

image

implode()

合并数组并且用符号隔开返回string类型

1
var_dump(implode(",",['key','key1','key2']));   //输出string(13) "key,key1,key2"

引用参数的函数

  • 相对于按值传递模式,并不会将父程序中的指定数值或目标变量传递给函数,而是把该数值或变量的内存储存区块相对地址导入函数之中。因此当该数值在函数中有任何变动时,会连带对父程序造成影响
  • 如果在函数的形参中使用&修饰的参数,在调用该函数时必须传入一个变量给这个参数,而是不能传递一个值。

使用常规参数传值,类似于局部变量

1
2
3
4
5
6
function test($arg) {         
$arg = 200; //在函数中改变参数$a的值为200
}
$var = 100; //在父程序中声明一个全局变量$var,初值为100
test($var); //调用test函数,并将变量$var的值100传给函数的参数$arg
echo $var; //输出100。$var的值没有变化

使用“&”引用参数传值,类似于全局变量

1
2
3
4
5
6
function test( &$arg ) {        
$arg = 200; //改变参数$a的值为200,$arg是引用参数,外部变量$var也被修改
}
$var = 100; //在父程序中声明一个全局变量$var,初值为100
test($var); //调用test函数,并将变量$var的引用传给函数的参数$arg
echo $var; //输出200。$var的值在函数中修改变量$arg时被修改

默认参数的函数

  • php中,支持函数的默认方式调用。如果在调用函数时没有指定参数的值,在函数中会使用参数的默认值
  • 默认参数必须列在所有没有默认值参数的后面。

有默认参数的函数

1
2
3
4
5
6
7
8
function test($name = '张三', $sex = "男", $age = "18")
{
echo "我的名字叫:".$name." 性别:".$sex. " 年龄:".$age."<br>";
}
test(); //输出我的名字叫:张三 性别:男 年龄:18
test("李四"); //输出我的名字叫:李四 性别:男 年龄:18
test("王麻子","女");//输出我的名字叫:王麻子 性别:女 年龄:18
test("王麻子2","女","16"); //我的名字叫:王麻子2 性别:女 年龄:16

没有默认参数的函数

1
2
3
4
5
6
function test($name, $sex, $age)
{
echo "我的名字叫:".$name." 性别:".$sex. " 年龄:".$age."<br>";
}
test(); //报错必须指定三个参数值
test("王麻子2","女","16"); //输出我的名字叫:王麻子2 性别:女 年龄:16

image

可变个数参数的函数

通常用户定义函数时,设置的参数数量是有限的。如果希望函数可以接受任意数量的参数,需使用以下函数:

1
2
3
func_get_args()  //返回一个数组,包含所有参数
func_num_args() //返回参数总数
func_get_arg() //接收一个数组下标,返回指定数组下标的值

示例1:

声明一个函数more_args(),用于打印参数列表的值
虽然没有声明参数列表,但可以传入任意个数,任意类型的参数值

1
2
3
4
5
6
7
8
function more_args() {           
$args = func_get_args(); //将所有传递给脚本函数的参数当做一个数组返回
for($i=0; $i<count($args); $i++) { //使用for循环遍历数组$args
echo "第".$i."个参数是".$args[$i]."<br>"; //分别输出传入函数的每个参数
}
var_dump(func_get_arg(3)); //输出一次$args数组中下标为3的参数
}
more_args("one", "two", "three", 1, 2, 3, 4); //调用函数并输入多个参数

页面返回结果:

image

示例2:

直接使用func_num_args()函数得到数组的总数

1
2
3
4
5
6
function more_args() {           
for($i=0; $i<func_num_args(); $i++) { //使用for循环遍历数组$args
echo "第".$i."个参数是".func_get_arg($i)."<br>";//分别输出传入函数的每个参数
}
}
more_args("one", "two", "three", 1, 2, 3); //调用函数并输入多个参数

返回结果和示例1一致

回调函数

所谓回调函数,就是指调用函数时并不是传递一个标准的变量作为参数,而是将另一函数作为参数传递到调用的函数中

变量回调函数

示例1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** 声明第一个函数one, 计算两个数的和
@param int $a 计算和的第一个运算元
@param int $b 计算和的第二个运算元
@return int 返回计算后的结果
*/
function one( $a, $b ) {
return $a + $b;
}
/** 声明第二个函数two, 计算两个数的平方和
*/
function two($a, $b) {
return $a*$b + $b*$b;
}
$result = "one"; //将函数名"one"赋给变量$result, 执行$result()时则调用函数one()
// $result = "two"; //将函数名"two"赋给变量$result, 执行$result()时则调用函数two()
echo "运算结果是:".$result(2, 3); //变量$result的函数名值是哪个,就调用哪个函数
示例2

声明回调函数filter, 在0-100的整数中通过自定义条件过滤不要的数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function filter( $fun ) {
for($i=0; $i <= 100; $i++) {
//将参数变量$fun加上一个圆插号$fun(), 则为调用和变量$fun值同名的函数
if( $fun($i) )
continue;
echo $i.'<br>';
}
}
//声明一个函数one, 如果参数是3的倍数就返回true, 否则返回false
function one($num) {
return $num%3 != 0;
}
// 声明一个函数two, 如果参数是一个回文数(翻转后还等于自己的数)返回true, 否则返回false
function two($num) {
return $num%7 != 0;
}
filter("one"); //打印出100以内3的倍数,参数"one"是函数one()的名称字符串,是一个回调
echo '--------------------<br>';
filter('two'); //打印出100以内7的倍数,参数"two"是函数two()的名称字符串,是一个回调

页面返回结果:

image

类静态函数和对象的方法回调

借助call_user_func_array()函数自定义回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 声明一个类Demo,类中声明一个静态的成员方法fun() */
class Demo {
static function fun($msg1, $msg2) {
echo '$msg1 = '.$msg1;
echo '<br>';
echo '$msg2 = '.$msg2;
}
}
/* 声明一个类Test, 类中声明一个普通的成员方法fun() */
class Test {
function fun($msg1, $msg2) {
echo '$msg1 = '.$msg1;
echo '<br>';
echo '$msg2 = '.$msg2;
}
}

call_user_func_array( array("Demo", 'fun'), array('LAMP', '兄弟连') );
echo '<br>';
echo '<br>';
call_user_func_array( array(new Test(), 'fun'), array('BroPHP', '学习型PHP框架') );

页面返回结果:

image

匿名函数

匿名函数Anonymous functions,也叫闭包函数closures,允许 临时创建一个没有指定名称的函数。

1
2
3
4
5
$greet = function($name){
echo ("Hello %s\r\n", $name);
}
$greet('World'); //输出 Hello World
$greet('PHP'); //输出 Hello PHP

递归函数

  • 所谓的函数递归调用,就是函数可以在其声明的执行叙述之中调用执行自己
  • 通常在此类型的函数之中会附加一个条件判断叙述,以判断是否需要执行递归调用,并且在特定条件下终止函数的递归调用动作,把目前流程的主控权交回上一层函数执行。因此当某个执行递归调用的函数,没有附加条件判断叙述时可能会造成无限循环的错误情形.
  • 函数递归调用最大的好处在于可以精简程序中繁杂重复调用程序,并且能以这种特性来执行一些较为复杂的运算动作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /**
    声明一个名称为test的函数,用于测试递归
    $param int $n 需要一个整数作为参数
    */
    function test( $n ) { //声明一个名为test的函数,有一个参数
    echo $n."&nbsp;&nbsp;"; //在函数开始处输出参数的值和两个空格

    if($n>0) //判断参数是否大于0
    test($n-1); //如果参数大于0则调用自己,并将参数减1后再传入
    else //判断参数不大于0
    echo " <--> "; //输出分界字符串

    echo $n."&nbsp;&nbsp;"; //在函数结束处输出参数的值和两个空格
    }

    test(10);
    页面返回结果:

image

调用自定义函数库

通过重复使用已有的代码,提高开发效率,降低成本

include()和require()函数

include()require ()几乎等价,区别在于在脚本执行时包含,当处理失败时,include()产生一个警告而require()则导致一个致命错误。

使用include()引入不存在的文件

如果文件引用失败,那么就报警告错误还是会执行后面的代码

1
2
include "tests.php";
echo "1";

image

使用require()引入不存在的文件

如果文件引用失败,那么就直接终止程序,不会执行后面的代码

1
2
require "tests.php";
echo "1";

image

include_once()和require_once()函数

两个函数在脚本执行期间包括并运行指定文件。与include()语句及require()类似,唯一区别是如果该文件中的代码已经被包括了,则不会再次包括,只会包括一次。这两个函数应该用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

同目录下有一个test.php文件,内容如下:

1
2
3
<?php
echo "test <br>";
?>
示例1:

使用include()函数调用test.php文件多次。输出4次test

1
2
3
4
include "test.php";
include "test.php";
include "test.php";
include "test.php";
示例2:

使用include_once()函数和require_once()调用test.php文件多次。只输出一次test

1
2
3
4
5
6
7
8
include_once "test.php";
include_once "test.php";
include_once "test.php";
include_once "test.php";
require_once "test.php";
require_once "test.php";
require_once "test.php";
require_once "test.php";