由于存在函数内部不能访问全局作用的,所以就需要一种可以引入上一级作用域的语法结构,可以通过use使用函数声明时所在作用域的变量的值。php的闭包可能不常用,但是在某些场合之下还是可以考虑用php的闭包来实现某些功能的。

php的闭包(Closure)也就是匿名函数。是PHP5.3引入的。

提到闭包就不得不想起匿名函数,也叫闭包函数(closures)。匿名函数因为没有名字,如果要使用它,需要将其返回给一个变量。匿名函数也像普通函数一样可以声明参数,调用方法也相同。

    $func = function( $param ) {
     echo $param;
    };
    $func( 'some string' );

    //输出:
    //some string

function () use () {}语法结构

在PHP中,由于存在函数内部不能访问全局作用的,所以就需要一种可以引入上一级作用域的语法结构,和上级作用域产生了联系,语句结构如下:

function () use () {}

将需要引入到这个函数作用于内的变量写入到use的括号里面就可以了,举个例子

<?php
$a = 1;
$closure = function () use ($a) {
    echo $a;
};
$closure();
?>

输出的结果为

1

闭包function() use() {}的使用场景:

1 减少foreach的循环的代码

<?php  
// 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。  
// 其中有一个方法用来计算购物车中所有商品的总价格。该方法使用了一个closure作为回调函数。  

class Cart  
{  
    const PRICE_BUTTER  = 1.00;  
    const PRICE_MILK    = 3.00;  
    const PRICE_EGGS    = 6.95;  
    protected   $products =array();  
    public function add($product,$quantity)  
    {  
        $this->products[$product] = $quantity;  
    }  

    public function getQuantity($product)  
    {  
        return isset($this->products[$product]) ? $this->products[$product] :  
               FALSE;  
    }  

    public function getTotal($tax)  
    {  
        $total = 0.00;  
        $callback =  function ($quantity,$product)use ($tax, &$total)  
            {  
                $pricePerItem = constant("::PRICE_" .  strtoupper($product));  
                $total += ($pricePerItem *$quantity) * ($tax + 1.0);  
            };  
        array_walk($this->products,$callback);  
        return round($total, 2);;  
    }  
}  
$my_cart =new Cart;  
// 往购物车里添加条目  
$my_cart->add('butter', 1);  
$my_cart->add('milk', 3);  
$my_cart->add('eggs', 6);  
// 打出出总价格,其中有 5% 的销售税.  
print $my_cart->getTotal(0.05) . "\n";  
// The result is 54.29  
?>

这里如果我们改造getTotal函数必然要使用到foreach

2 减少函数的参数

function html ($code ,$id="",$class=""){  
    if ($id !=="")$id =" id = \"$id\"" ;  
    $class = ($class !=="")?" class =\"$class\"":">";  
    $open ="<$code$id$class";  
    $close ="</$code>";  
    return function ($inner ="")use ($open,$close){  
    return "$open$inner$close";};  
}

如果是使用平时的方法,我们会把inner放到html函数参数中,这样不管是代码阅读还是使用都不如使用闭包

3 解除递归函数

<?php  
    $fib =function($n)use(&$fib) {  
        if($n == 0 || $n == 1) return 1;  
        return $fib($n - 1) + $fib($n - 2);  
    };  
   echo $fib(2) . "\n";// 2  
   $lie =$fib;  
   $fib =function(){die('error');};//rewrite $fib variable   
   echo $lie(5);// error   because $fib is referenced by closure

注意上题中的use使用了&,这里不使用&会出现错误n-1)是找不到function的(前面没有定义fib的类型)

所以想使用闭包解除循环函数的时候就需要使用

<?php  
$recursive =function ()use (&$recursive){  
// The function is now available as $recursive  

}

这样的形式

4 关于延迟绑定

如果你需要延迟绑定use里面的变量,你就需要使用引用,否则在定义的时候就会做一份拷贝放到use中

<?php  

$result = 0;  
$one =function(){ 
    var_dump($result); 
    
};  

$two =function()use($result)  { 
    var_dump($result); 
    
};  

$three =function()use (&$result)  { 
    var_dump($result); 
};  

$result++;  
$one();   // outputs NULL: $result is not in scope  
$two();   // outputs int(0): $result was copied  
$three();   // outputs int(1)

使用引用和不使用引用就代表了是调用时赋值,还是申明时候赋值

到此这篇关于PHP中的闭包function() use() {}使用场景和技巧的文章就介绍到这了,更多相关PHP function() use()内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!

点赞(0)

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部