PHP 自 5.2 到 5.6 中新增的功能详解(4)

也叫闭包(Closures), 经常被用来临时性地创建一个无名函数,用于回调函数等用途。

$func = function($arg)
{
    print $arg;
};

$func("Hello World");

以上代码定义了一个匿名函数,并赋值给了 $func.
可以看到定义匿名函数依旧使用 function 关键字,只不过省略了函数名,直接是参数列表。

然后我们又调用了 $func 所储存的匿名函数。

匿名函数还可以用 use 关键字来捕捉外部变量:

function arrayPlus($array, $num)
{
    array_walk($array, function(&$v) use($num){
        $v += $num;
    });
}

上面的代码定义了一个 arrayPlus() 函数(这不是匿名函数), 它会将一个数组($array)中的每一项,加上一个指定的数字($num).

在 arrayPlus() 的实现中,我们使用了 array_walk() 函数,它会为一个数组的每一项执行一个回调函数,即我们定义的匿名函数。
在匿名函数的参数列表后,我们用 use 关键字将匿名函数外的 $num 捕捉到了函数内,以便知道到底应该加上多少。

魔术方法:__invoke(), __callStatic()

PHP 的面向对象体系中,提供了若干“魔术方法”,用于实现类似其他语言中的“重载”,如在访问不存在的属性、方法时触发某个魔术方法。

随着匿名函数的加入,PHP 引入了一个新的魔术方法 __invoke().
该魔术方法会在将一个对象作为函数调用时被调用:

class A
{
    public function __invoke($str)
    {
        print "A::__invoke(): {$str}";
    }
}

$a = new A;
$a("Hello World");

输出毫无疑问是:

A::__invoke(): Hello World

__callStatic() 则会在调用一个不存在的静态方法时被调用。

命名空间

PHP的命名空间有着前无古人后无来者的无比蛋疼的语法:

<?php
// 命名空间的分隔符是反斜杠,该声明语句必须在文件第一行。
// 命名空间中可以包含任意代码,但只有 **类, 函数, 常量** 受命名空间影响。
namespace XXOO\Test;

// 该类的完整限定名是 \XXOO\Test\A , 其中第一个反斜杠表示全局命名空间。
class A{}

// 你还可以在已经文件中定义第二个命名空间,接下来的代码将都位于 \Other\Test2 .
namespace Other\Test2;

// 实例化来自其他命名空间的对象:
$a = new \XXOO\Test\A;
class B{}

// 你还可以用花括号定义第三个命名空间
namespace Other {
    // 实例化来自子命名空间的对象:
    $b = new Test2\B;

// 导入来自其他命名空间的名称,并重命名,
    // 注意只能导入类,不能用于函数和常量。
    use \XXOO\Test\A as ClassA
}

更多有关命名空间的语法介绍请参见官网 [注].

命名空间时常和 autoload 一同使用,用于自动加载类实现文件:

spl_autoload_register(
    function ($class) {
        spl_autoload(str_replace("\\", "/", $class));
    }
);

当你实例化一个类 \XXOO\Test\A 的时候,这个类的完整限定名会被传递给 autoload 函数,autoload 函数将类名中的命名空间分隔符(反斜杠)替换为斜杠,并包含对应文件。
这样可以实现类定义文件分级储存,按需自动加载。

注:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/d0e6b2f43571283dfd35a31fe23f0f67.html