樊琴琴 發表於 2019-8-11 10:17:00

PHP闭包 function() use(){}

<p>php的闭包(Closure)也就是匿名函数。是PHP5.3引入的。</p>
<p>闭包的语法很简单,需要注意的关键字就只有use,<span style="color: rgba(255, 102, 0, 1)">use意思是连接闭包和外界变量</span>。</p>
<div class="cnblogs_code">
<pre>$a =<span style="color: rgba(0, 0, 0, 1)">function()use($b) { <br>}</span></pre>
</div>
<p>&nbsp;</p>
<p>闭包的几个作用:</p>
<p><span style="color: rgba(255, 102, 0, 1)">&nbsp; &nbsp;减少foreach的循环的代码</span></p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 其中有一个方法用来计算购物车中所有商品的总价格。该方法使用了一个closure作为回调函数。</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Cart {
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> PRICE_BUTTER = <span style="color: rgba(128, 0, 128, 1)">1.00</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> PRICE_MILK   = <span style="color: rgba(128, 0, 128, 1)">3.00</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> PRICE_EGGS   = <span style="color: rgba(128, 0, 128, 1)">6.95</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> $products =<span style="color: rgba(0, 0, 0, 1)"> [];

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> function add($product, $quantity) {
      $</span><span style="color: rgba(0, 0, 255, 1)">this</span>-&gt;products[$product] =<span style="color: rgba(0, 0, 0, 1)"> $quantity;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> function getQuantity($product) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> isset($<span style="color: rgba(0, 0, 255, 1)">this</span>-&gt;products[$product]) ? $<span style="color: rgba(0, 0, 255, 1)">this</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">products[$product] : FALSE;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> function getTotal($tax) {
      $total </span>= <span style="color: rgba(128, 0, 128, 1)">0.00</span><span style="color: rgba(0, 0, 0, 1)">;

      $callback </span>=<span style="color: rgba(0, 0, 0, 1)">
      function ($quantity, $product) use ($tax, </span>&amp;<span style="color: rgba(0, 0, 0, 1)">$total) {
            $pricePerItem </span>= constant(__CLASS__ . <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">::PRICE_</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> .
                strtoupper($product));
            $total </span>+= ($pricePerItem * $quantity) * ($tax + <span style="color: rgba(128, 0, 128, 1)">1.0</span><span style="color: rgba(0, 0, 0, 1)">);
      };

      array_walk($</span><span style="color: rgba(0, 0, 255, 1)">this</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">products, $callback);
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> round($total, <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
    }
}

$my_cart </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Cart;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 往购物车里添加条目</span>
$my_cart-&gt;add(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">butter</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
$my_cart</span>-&gt;add(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">milk</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">);
$my_cart</span>-&gt;add(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">eggs</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 打出出总价格,其中有 5% 的销售税.</span>
print $my_cart-&gt;getTotal(<span style="color: rgba(128, 0, 128, 1)">0.05</span>) . <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> The result is 54.29</span>
?&gt;</pre>
</div>
<p><span style="color: rgba(255, 102, 0, 1)">&nbsp; 这里如果我们改造getTotal函数必然要使用到foreach</span></p>
<h4><span style="color: rgba(255, 102, 0, 1)">&nbsp; <span style="color: rgba(0, 0, 0, 1)">减少函数的参数</span></span></h4>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php

function html($code, $id </span>= <span style="color: rgba(128, 0, 0, 1)">""</span>, $<span style="color: rgba(0, 0, 255, 1)">class</span> = <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">) {

    </span><span style="color: rgba(0, 0, 255, 1)">if</span> ($id !== <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">) {
      $id </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> id = \"$id\"</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    $</span><span style="color: rgba(0, 0, 255, 1)">class</span> = ($<span style="color: rgba(0, 0, 255, 1)">class</span> !== <span style="color: rgba(128, 0, 0, 1)">""</span>) ? <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"> class =\"$class\"</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    $open </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;$code$id$class</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    $close </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">&lt;/$code&gt;</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">return</span> function ($inner = <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">) use ($open, $close) {

      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">$open$inner$close</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;};

}
</span>?&gt;</pre>
</div>
<p>&nbsp; &nbsp;如果是使用平时的方法,我们会把inner放到html函数参数中,这样不管是代码阅读还是使用都不如使用闭包</p>
<h4>&nbsp; &nbsp;解除递归函数</h4>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php

$fib </span>= function ($n) use (&amp;<span style="color: rgba(0, 0, 0, 1)">$fib) {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> ($n == <span style="color: rgba(128, 0, 128, 1)">0</span> || $n == <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">return</span> $fib($n - <span style="color: rgba(128, 0, 128, 1)">1</span>) + $fib($n - <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
};

echo $fib(</span><span style="color: rgba(128, 0, 128, 1)">2</span>) . <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2</span>
$lie =<span style="color: rgba(0, 0, 0, 1)"> $fib;
$fib </span>= function () {die(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">'</span>);}; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">rewrite $fib variable</span>
echo $lie(<span style="color: rgba(128, 0, 128, 1)">5</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error because $fib is referenced by closure</span>

?&gt;</pre>
</div>
<p>&nbsp; &nbsp;注意上题中的use使用了&amp;,这里不使用&amp;会出现错误fib(fib(n-1)是找不到function的(前面没有定义fib的类型)</p>
<p>&nbsp; &nbsp;所以想使用闭包解除循环函数的时候就需要使用</p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php
$recursive </span>= function () use (&amp;<span style="color: rgba(0, 0, 0, 1)">$recursive) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> The function is now available as $recursive</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span>?&gt;</pre>
</div>
<h4>&nbsp; &nbsp;关于延迟绑定</h4>
<p>&nbsp; &nbsp;如果你需要延迟绑定use里面的变量,你就需要使用引用(&amp;),否则在定义的时候就会做一份拷贝放到use中 //理解use(&amp;$var)</p>
<div class="cnblogs_code">
<pre>&lt;?<span style="color: rgba(0, 0, 0, 1)">php

$result </span>= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;

$one </span>=<span style="color: rgba(0, 0, 0, 1)"> function () {var_dump($result);};

$two </span>=<span style="color: rgba(0, 0, 0, 1)"> function () use ($result) {var_dump($result);};

$three </span>= function () use (&amp;<span style="color: rgba(0, 0, 0, 1)">$result) {var_dump($result);};

$result</span>++<span style="color: rgba(0, 0, 0, 1)">;

$one(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> outputs NULL: $result is not in scope</span>
$two(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> outputs int(0): $result was copied</span>
$three(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> outputs int(1)</span></pre>
</div>
<p>&nbsp; &nbsp;<span style="color: rgba(255, 102, 0, 1)">使用引用和不使用引用就代表了是调用时赋值,还是申明时候赋值</span></p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/mzhaox/p/11334077.html
頁: [1]
查看完整版本: PHP闭包 function() use(){}