天天看点

PHP>5.3版本部分新功能

【php5.3的新增、改进】匿名函数

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

PHP>5.3版本部分新功能

$func = function ($arg) {  

    print $arg;  

};  

$func("hello world");  

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

PHP>5.3版本部分新功能

function arrayplus($array, $num)  

{  

    array_walk($array, function (&$v) use ($num) {  

        $v += $num;  

    });  

}  

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

后期静态绑定php的继承模型中有一个存在已久的问题,那就是在父类中引用扩展类的最终状态比较困难。

PHP>5.3版本部分新功能

<?php  

class parentbase  

    static $property = 'parent value';  

    public static function render()  

    {  

        return self::$property;  

    }  

class descendant extends parentbase  

    static $property = 'descendant value';  

//output: parent value  

echo descendant::render();  

在这个例子中,render()方法中使用了self关键字,这是指parentbase类而不是指descendant类。在 parentbase::render()方法中没法访问$property的最终值。为了解决这个问题,需要在子类中重写render()方法。通过引入延迟静态绑定功能,可以使用static作用域关键字访问类的属性或者方法的最终值

PHP>5.3版本部分新功能

        return static::$property;  

    public static function status()  

        static::getstatus();  

    protected static function getstatus()  

        echo "person is alive";  

//output: descendant value  

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

__call($funcname, $arguments)

__callstatic($funcname, $arguments)

参数说明:

$funcname string 调用的不存在的方法名称。

$arguments array 调用方法时所带的参数。

 __invoke魔术方法会在将一个对象作为函数调用时被调用:

PHP>5.3版本部分新功能

class a  

    public function __invoke($args)  

        print "a::__invoke(): {$args}";  

$a = new a;  

//output: a::__invoke(): hello world  

$a("hello world");  

 __callstatic则会在调用一个不存在的静态方法时被调用,有了__callstatic,可以省不少代码了。而且这个方法支持在子类中调用,配合上get_called_class,子类也一起魔术了

PHP>5.3版本部分新功能

class activerecordbase  

    /**  as of php 5.3.0  */  

    public static function __callstatic($func, $arguments)  

        if ($func == 'getbyid') {  

            $id = $arguments[0];  

            return get_called_class() . '(' . $id . ')';  

        }  

        throw new exception('invalid method : ' . $name);  

class person extends activerecordbase  

// output: person(123)  

echo person::getbyid(123);  

__call 当要调用的方法不存在或权限不足时,会自动调用__call 方法。

PHP>5.3版本部分新功能

class db  

    private $sql = array(  

        "field" => "",  

        "where" => "",  

        "order" => "",  

        "limit" => "",  

        "group" => "",  

        "having" => "",  

    );  

    // 连贯操作调用field() where() order() limit() group() having()方法,组合sql语句  

    function __call($methodname, $args)  

        // 将第一个参数(代表不存在方法的方法名称),全部转成小写方式,获取方法名称  

        $methodname = strtolower($methodname);  

        // 如果调用的方法名和成员属性数组$sql下标对应上,则将第二个参数给数组中下标对应的元素  

        if (array_key_exists($methodname, $this->sql)) {  

            $this->sql[$methodname] = $args[0];  

        } else {  

            echo '调用类' . get_class($this) . '中的方法' . $methodname . '()不存在';  

        // 返回自己对象,则可以继续调用本对象中的方法,形成连贯操作  

        return $this;  

    // 输出连贯操作后组合的一个sql语句,是连贯操作最后的一个方法  

    function select()  

        echo "select {$this->sql['field']} from  user {$this->sql['where']} {$this->sql['order']} {$this->sql['limit']} {$this->sql['group']}  

                {$this->sql['having']}";  

$db = new db();  

// 连贯操作  

$db->field('sex, count(sex)')  

    ->where('where sex in ("男","女")')  

    ->group('group by sex')  

    ->having('having avg(age) > 25')  

    ->select();  

?>  

命名空间一个最明确的目的就是解决重名问题,php中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误。这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀。

PHP>5.3版本部分新功能

//创建空间blog  

namespace blog;  

class comment  

//非限定名称,表示当前blog空间  

//这个调用将被解析成 blog\comment();  

$blog_comment = new comment();  

//限定名称,表示相对于blog空间  

//这个调用将被解析成 blog\article\comment();  

$article_comment = new article\comment(); //类前面没有反斜杆\  

//完全限定名称,表示绝对于blog空间  

$article_comment = new \blog\comment(); //类前面有反斜杆\  

$article_comment = new \blog\article\comment(); //类前面有反斜杆\  

//创建blog的子空间article  

namespace blog\article;  

别名和导入可以看作是调用命名空间元素的一种快捷方式。php并不支持导入函数或常量。 它们都是通过使用use操作符来实现:

PHP>5.3版本部分新功能

//创建一个bbs空间(我有打算开个论坛)  

namespace bbs;  

//导入一个命名空间  

use blog\article;  

//导入命名空间后可使用限定名称调用元素  

$article_comment = new article\comment();  

//为命名空间使用别名  

use blog\article as arte;  

//使用别名代替空间名  

$article_comment = new arte\comment();  

//导入一个类  

use blog\article\comment;  

//导入类后可使用非限定名称调用元素  

$article_comment = new comment();  

//为类使用别名  

use blog\article\comment as comt;  

$article_comment = new comt();  

 php5.4

数组简写形式

PHP>5.3版本部分新功能

//原来的数组写法  

$arr = array("key" => "value", "key2" => "value2");  

// 简写形式  

$arr = ["key" => "value", "key2" => "value2"];  

traits

所谓traits就是“构件”,是用来替代继承的一种机制。trait和类相似,但不能被实例化php中无法进行多重继承,但一个类可以包含多个traits.

PHP>5.3版本部分新功能

trait sayworld  

    public $var = 'test';  

    public function sayhello()  

        echo 'world!';  

class myhelloworld  

    // 将sayworld中的成员包含进来  

    use sayworld;  

$xxoo = new myhelloworld();  

// sayhello()函数是来自sayworld构件的 $xxoo->var  

$xxoo->sayhello();  

traits还有很多神奇的功能,比如包含多个traits, 解决冲突,修改访问权限,为函数设置别名等等。

新增在实例化时访问类成员的特征:

PHP>5.3版本部分新功能

(new myclass)->xxoo();  

 新增支持对函数返回数组的成员访问解析

PHP>5.3版本部分新功能

print [1, 2, 3][0];  

 php5.5

yield的一个功能就是能有效的降低迭代的内存开销,yield关键字用于当函数需要返回一个迭代器的时候, 逐个返回值.也就是说, 每当产生一个数组元素, 就通过yield关键字返回成一个, 并且函数执行暂停, 当返回的迭代器的next方法被调用的时候, 会恢复刚才函数的执行, 从上一次被yield暂停的位置开始继续执行, 到下一次遇到yield的时候, 再次返回.

PHP>5.3版本部分新功能

function generators()  

    for ($i = 1; $i <= 10; $i += 1) {  

        yield $i;  

foreach (generators() as $v) {  

    echo $v;  

 可以用 list() 在 foreach 中解析嵌套的数组:

PHP>5.3版本部分新功能

$array = [  

    [1, 2, 3],  

    [4, 5, 6],  

];  

foreach ($array as list($a, $b, $c))  

    echo "{$a} {$b} {$c}\n";  

 aaa