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> </p>
<p>闭包的几个作用:</p>
<p><span style="color: rgba(255, 102, 0, 1)"> 减少foreach的循环的代码</span></p>
<div class="cnblogs_code">
<pre><?<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>->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>->products[$product]) ? $<span style="color: rgba(0, 0, 255, 1)">this</span>-><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>&<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>-><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->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>->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>->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->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>
?></pre>
</div>
<p><span style="color: rgba(255, 102, 0, 1)"> 这里如果我们改造getTotal函数必然要使用到foreach</span></p>
<h4><span style="color: rgba(255, 102, 0, 1)"> <span style="color: rgba(0, 0, 0, 1)">减少函数的参数</span></span></h4>
<div class="cnblogs_code">
<pre><?<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)">></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)"><$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)"></$code></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>?></pre>
</div>
<p> 如果是使用平时的方法,我们会把inner放到html函数参数中,这样不管是代码阅读还是使用都不如使用闭包</p>
<h4> 解除递归函数</h4>
<div class="cnblogs_code">
<pre><?<span style="color: rgba(0, 0, 0, 1)">php
$fib </span>= function ($n) use (&<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>
?></pre>
</div>
<p> 注意上题中的use使用了&,这里不使用&会出现错误fib(fib(n-1)是找不到function的(前面没有定义fib的类型)</p>
<p> 所以想使用闭包解除循环函数的时候就需要使用</p>
<div class="cnblogs_code">
<pre><?<span style="color: rgba(0, 0, 0, 1)">php
$recursive </span>= function () use (&<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>?></pre>
</div>
<h4> 关于延迟绑定</h4>
<p> 如果你需要延迟绑定use里面的变量,你就需要使用引用(&),否则在定义的时候就会做一份拷贝放到use中 //理解use(&$var)</p>
<div class="cnblogs_code">
<pre><?<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 (&<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> <span style="color: rgba(255, 102, 0, 1)">使用引用和不使用引用就代表了是调用时赋值,还是申明时候赋值</span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/mzhaox/p/11334077.html
頁:
[1]