php中的函数

来源:互联网 发布:软件测试行业现状 编辑:程序博客网 时间:2024/06/17 03:17

定义一个函数

function test($a, $b){  $temp = $a + $b;  return $temp;}

在php中,任何有效的 PHP 代码都有可能出现在函数内部,甚至包括其它函数和类定义。 同时,由于PHP 中的所有函数和类都具有全局作用域,可以定义在一个函数之内而在之外调用,反之亦然。 也就是说,在函数内定义的函数或类,在函数之外可以直接使用,使用时与定义它的函数并无关联。

另外,有别于变量,函数是不能重复定义的。


有条件地定义一个函数

有条件定义一个函数包括两种情形,即函数定义在一个条件语句中,或定义在另一个函数(假设为函数a)中,这时语句是否执行以及函数a是否调用,就成了函数是否定义的条件。在这两种情况下,函数必须是确定已经定义之后,才可以调用。

除了这两种情况,函数是可以先调用再定义的。

$a = 4;if($a % 2 == 0){    function test1(){        echo "test1\n";    }}switch($a){    case 4;        function test2(){            echo "test2\n";        }        break;}function fun(){    function test3(){        echo "test3\n";    }}fun();test1();test2();test3();
本示例能够正常运行,对于test1(),因为if语句确实运行过了,对于test2(),switch中的分支确实运行过了,对于test3(),fun()函数也是确实运行过了,只有这样,这些函数才得以正常运行。

引用参数

通过在函数参数前添加"&"符号,可以定义引用参数,这时形参将成为实参的一个别名:

$a = 4;function test1(&$x){    $x++;}test1($a);echo $a;    // 5

默认参数

可以给函数参数添加默认参数,这种情况下,如果调用时不提供实参,将会以默认参数作为实参。默认参数可以是各种标量、数组、NULL等,不过必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。

$str = "Hi";function test($a, $b=null, $c=array("Ann","Nicke","Jeck"), &$x="Hello"){    foreach($c as $name)    {        if($a-- <= 0) break;        echo "$x $name\n";    }}test(2);
注意:

1.提供了默认参数的参数必须全部集中在参数列表的最后

2.引用参数也可以有默认参数(尽管上例没能很好地体现这一点)


类型声明

默认情况下函数的参数是没有指定类型的,这样的参数可以传递任何类型的参数。不过也可以为参数指定一个类型,如果参数的类型不正确,将会抛出TypeError异常。另外,虽然指定了参数的类型,仍可以通过给参数设定一个null默认值,使得参数可以接收null。

function test(int $x) {  return $x * $x;}echo test(2);   // 4


可用的类型名包括:

类名/接口名/array/callable/bool/float/int/string/self

注意:

1.不能使用integer/boolean/double等

2.self只用于类或接口方法,表示参数的类型与所有在类或接口类型相同

3.对于指定为类的参数,实参可以是子类对象

4.如果不开启严格模式,那么在默认情况下,PHP将会强迫错误类型的值转为函数期望的标量类型。 例如,一个函数的一个参数期望是string,但传入的是integer,最终函数得到的将会是一个string类型的值。 

function test(float $x) {  return $x * $x;}echo test("2x");   // 4

declare(strict_types=1);function test(float $x) {  return $x * $x;}echo test("2x");   // 异常


可变数量的参数列表

函数可以接受不定数量的参数,这些参数可以在函数内部以数组的形式获得。

function test(int ...$num) {  $count = 0;  foreach($num as $x)    $count += $x;  return $count;}echo test(1,2,3);   // 6

可变数量的参数最多只能有一个,而且只能出现在参数列表的最后一个。同时,可变数量的参数也可以是引用参数,可以有或者没有类型声明。

function test($x, $y=2, &...$num) {  foreach($num as &$n) {    $n += $x;    $n *= $y;  }}$a = 4;$b = 5;test(2,3,$a,$b);echo "$a\n";    // 18echo "$b\n";    // 21

可变数量的参数还有第二种实现方式,即使用以下三个函数:

int func_num_args ( void ) - 实参个数
mixed func_get_arg ( int $arg_num ) - 获取指定编号的实参值
array func_get_args ( void ) - 获取全部实参,返回一个数组

这3个函数可用于任意函数内部,与是否使用...参数无关

function test1($x, $y, ...$num) {  var_dump(func_num_args());  var_dump(func_get_args());}function test2(){  $count = 0;  for($i=0; $i<func_num_args(); $i++)    $count += func_get_arg($i);  return $count;}test1(1,2,3,4);echo test2(1,2,3,4);
--------------------
int(4)
array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}
10


...运算符不仅可以用于函数形参,也可以用于函数实参,效果是将数组类型的实参拆解为多个值

function test($x, $y) {  return $x + $y;}$a = [1,2,3];echo test(...$a);    // 3echo test(...[3,4]); // 7echo test(2,3,4);    // 5 实参数量可以比形参多,但不能少,否则出错

返回值

可以使用return语句从函数中返回一个值。可以返回包括数组和对象的任意类型。如果省略了 return,则返回值为 NULL。 函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。


返回一个引用

要让函数返回一个引用,必须在函数声明和函数调用处,都使用&运算符,而return语句处则不需要。

function &test(&$x, &$y) {  if($x > $y) return $x;  else        return $y;}$a = 3;$b = 4;$c = &test($a, $b);$c++;echo "$a\n";    // 3echo "$b\n";    // 5


注意,虽然函数定义成可以返回引用,但调用时却可以不使用此特性,另外,引用也可以返回函数的局部变量
function &test($x) {  static $max = 0;  $max = $x > $max ? $x : $max;  return $max;}$a = 3;$b = 4;$c = &test($a);test($b);echo $c;   // 4
在本例中,局部变量定义成静态变量,从语法上这不是必须的,但是如果定义成非静态变量,则每次函数返回的引用都将是新的局部变量(也就是每次函数调用都会临时创建的局部变量)。

指定函数的返回类型

与函数的参数可以声明类型一样,函数的返回值也可以声明类型,例如:

function numAdd($x, $y) : int {  return $x + $y;}$x = numAdd(3,4);$y = numAdd("23", true);echo $x;   // 7echo $y;   // 24
与参数的类型一样,如果需要严格的类型匹配,可以为文件添加 declare(strict_types=1); 声明。


可变函数

与可变变量类似,PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。不过,可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。如果确实需要,可自行对这些语言结构进行函数封装。

一般情况下,在调用函数或方法时,函数名前面是不会有$符号的,例如:

var_dump();

如果出现了$符号,则表明$之后的标识符不是一个函数名,只有在与$结合起来解析后,才会得到真正的函数名(或方法名)。

function myPrint($x) {  echo "$x\n";}function varPrint($x) {  return print $x;}$a = "myPrint";$a("Hello world!");
这里便出现了$xxx()的形式,类似的,方法也可以使用可变函数:xxx->$xxx(); xxx::$xxx();


可变的变量不仅仅只能是一个字符串,还可以是数组,一般包含以下几种形式:

1.字符串:函数名或方法名

2.字符串:"类名::静态方法名"

3.数组:array("类名","静态方法名")

4.数组:array(对象,"对象方法名")


另外,注意在使用类的静态成员时,解析的优先问题:

class TestClass {  public static $a = "func"; }function func() {    return "func";}echo TestClass::$a;   // funcecho TestClass::$a(); // 出错
第二个输出语句被解析为:

(TestClass::($a))()
而不是:
(TestClass::$a)()
由于$a未定义,所以出错。

class TestClass {  public static $a = "func";   public static function ft() {      return "ft";  }}function func() {    return "func";}$a = "ft";echo TestClass::$a;   // funcecho TestClass::$a(); // ft
本例中,两个输出语句都能正常输出。

匿名函数/闭包

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。 目前通过 Closure 类来实现。 

定义匿名函数时,不需要指定函数名,类似如下形式:

function ($a ...) {}

可以直接将这样的表达式传递给函数调用,也可以赋值给一个变量

$p = function($x) {    echo "$x\n";};$p("Hello world!");

闭包的特色功能在于继承父作用域的变量,只需要使用use语言结构。注意,PHP 7.1 起,不能传入此类变量: 超级全局变量、 $this 或者和参数重名。

$message = 'hello';// 继承 $message$example = function () use ($message) {    var_dump($message);};$example();    // string(5) "hello"// 变量的值在函数定义时继承,而不是在函数调用时$message = 'world';$example();    // string(5) "hello"
在本例中,如果不使用use继承变量,那么函数内$message实际上只是一个未定义的局部变量。从父作用域中继承变量与使用全局变量是不同的。全局变量存在于一个全局的范围,无论当前在执行的是哪个函数。而 闭包的父作用域是定义该闭包的函数(不一定是调用它的函数)。

下面是一个相对实用一些的闭包实例:

function operate($operator){  return function($a,$b) use($operator) {    switch($operator)    {    case "-":        return $a-$b;    case "+":        return $a+$b;    }  };}$subtraction = operate("-");echo $subtraction(4,3);    // 1$addition = operate("+");echo $addition(1,2);       // 3


如果使用引用继承,则变量会在闭包内外形成联结:

$message = 'hello';// 引用继承$example = function () use (&$message) {    var_dump($message);};$example();    // string(5) "hello"// 外界变量的改变可以映射到闭包内部$message = 'world';$example();    // string(5) "world"


下面的例子演示了引用继承多个变量:

function func($x, $y) {    return function() use(&$x, &$y) {        echo $x + $y;        $x++;        $y++;    };}$a = func(4,5);$a();   // 9$a();   // 11$a();   // 13


在类内部定义的匿名函数会自动绑定$this,如果要避免此特性,可将匿名函数定义成静态的

class MyClass{    public function __construct($num) {        $this->num = $num;    }    public function func() {        return function() {            var_dump($this->num);        };    }}$a = new MyClass(3);$x = $a->func();$x();   // int(3)$a->num = 4;$x();   // int(4)

class MyClass{    public function __construct($num) {      $this->num = $num;    }    public function func() {        return static function() {        };    }}


原创粉丝点击