天天看點

PHP的閉包閉包的幾個作用:

閉包的文法很簡單,需要注意的關鍵字就隻有use,use意思是連接配接閉包和外界變量。

1

2

3

<code>$a</code> <code>=</code><code>function</code><code>()</code><code>use</code><code>(</code><code>$b</code><code>) {</code>

<code>}</code>

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

<code>&lt;?php</code>

<code>// 一個基本的購物車,包括一些已經添加的商品和每種商品的數量。</code>

<code>// 其中有一個方法用來計算購物車中所有商品的總價格。該方法使用了一個closure作為回調函數。</code>

<code>class</code> <code>cart</code>

<code>{</code>

<code>    </code><code>const</code> <code>price_butter  = 1.00;</code>

<code>    </code><code>const</code> <code>price_milk    = 3.00;</code>

<code>    </code><code>const</code> <code>price_eggs    = 6.95;</code>

<code>    </code><code>protected</code>   <code>$products</code> <code>=</code><code>array</code><code>();</code>

<code>    </code> 

<code>    </code><code>public</code> <code>function</code> <code>add(</code><code>$product</code><code>,</code><code>$quantity</code><code>)</code>

<code>    </code><code>{</code>

<code>        </code><code>$this</code><code>-&gt;products[</code><code>$product</code><code>] =</code><code>$quantity</code><code>;</code>

<code>    </code><code>}</code>

<code>    </code><code>public</code> <code>function</code> <code>getquantity(</code><code>$product</code><code>)</code>

<code>        </code><code>return</code> <code>isset(</code><code>$this</code><code>-&gt;products[</code><code>$product</code><code>]) ?</code><code>$this</code><code>-&gt;products[</code><code>$product</code><code>] :</code>

<code>               </code><code>false;</code>

<code>    </code><code>public</code> <code>function</code> <code>gettotal(</code><code>$tax</code><code>)</code>

<code>        </code><code>$total</code> <code>= 0.00;</code>

<code>        </code> 

<code>        </code><code>$callback</code> <code>=</code>

<code>            </code><code>function</code> <code>(</code><code>$quantity</code><code>,</code><code>$product</code><code>)</code><code>use</code> <code>(</code><code>$tax</code><code>, &amp;</code><code>$total</code><code>)</code>

<code>            </code><code>{</code>

<code>                </code><code>$priceperitem</code> <code>= constant(</code><code>__class__</code> <code>.</code><code>"::price_"</code> <code>.</code>

<code>                    </code><code>strtoupper</code><code>(</code><code>$product</code><code>));</code>

<code>                </code><code>$total</code> <code>+= (</code><code>$priceperitem</code> <code>*</code><code>$quantity</code><code>) * (</code><code>$tax</code> <code>+ 1.0);</code>

<code>            </code><code>};</code>

<code>        </code><code>array_walk</code><code>(</code><code>$this</code><code>-&gt;products,</code><code>$callback</code><code>);</code>

<code>        </code><code>return</code> <code>round</code><code>(</code><code>$total</code><code>, 2);;</code>

<code>$my_cart</code> <code>=</code><code>new</code> <code>cart;</code>

<code>// 往購物車裡添加條目</code>

<code>$my_cart</code><code>-&gt;add(</code><code>'butter'</code><code>, 1);</code>

<code>$my_cart</code><code>-&gt;add(</code><code>'milk'</code><code>, 3);</code>

<code>$my_cart</code><code>-&gt;add(</code><code>'eggs'</code><code>, 6);</code>

<code>// 打出出總價格,其中有 5% 的銷售稅.</code>

<code>print</code> <code>$my_cart</code><code>-&gt;gettotal(0.05) .</code><code>"\n"</code><code>;</code>

<code>// the result is 54.29</code>

<code>?&gt;</code>

這裡如果我們改造gettotal函數必然要使用到foreach 

<code>function</code> <code>html (</code><code>$code</code> <code>,</code><code>$id</code><code>=</code><code>""</code><code>,</code><code>$class</code><code>=</code><code>""</code><code>){</code>

<code>if</code> <code>(</code><code>$id</code> <code>!==</code><code>""</code><code>)</code><code>$id</code> <code>=</code><code>" id = \"$id\""</code> <code>;</code>

<code>$class</code> <code>= (</code><code>$class</code> <code>!==</code><code>""</code><code>)?</code><code>" class =\"$class\""</code><code>:</code><code>"&gt;"</code><code>;</code>

<code>$open</code> <code>=</code><code>"&lt;$code$id$class"</code><code>;</code>

<code>$close</code> <code>=</code><code>"&lt;/$code&gt;"</code><code>;</code>

<code>return</code> <code>function</code> <code>(</code><code>$inner</code> <code>=</code><code>""</code><code>)</code><code>use</code> <code>(</code><code>$open</code><code>,</code><code>$close</code><code>){</code>

<code>return</code> <code>"$open$inner$close"</code><code>;};</code>

<code>如果是使用平時的方法,我們會把inner放到html函數參數中,這樣不管是代碼閱讀還是使用都不如使用閉包</code>

<code>    </code><code>$fib</code> <code>=</code><code>function</code><code>(</code><code>$n</code><code>)</code><code>use</code><code>(&amp;</code><code>$fib</code><code>) {</code>

<code>        </code><code>if</code><code>(</code><code>$n</code> <code>== 0 ||</code><code>$n</code> <code>== 1)</code><code>return</code> <code>1;</code>

<code>        </code><code>return</code> <code>$fib</code><code>(</code><code>$n</code> <code>- 1) +</code><code>$fib</code><code>(</code><code>$n</code> <code>- 2);</code>

<code>    </code><code>};</code>

<code>   </code><code>echo</code> <code>$fib</code><code>(2) .</code><code>"\n"</code><code>;</code><code>// 2</code>

<code>   </code><code>$lie</code> <code>=</code><code>$fib</code><code>;</code>

<code>   </code><code>$fib</code> <code>=</code><code>function</code><code>(){</code><code>die</code><code>(</code><code>'error'</code><code>);};</code><code>//rewrite $fib variable</code>

<code>   </code><code>echo</code> <code>$lie</code><code>(5);</code><code>// error   because $fib is referenced by closure</code>

注意上題中的use使用了&amp;,這裡不使用&amp;會出現錯誤fib(fib(n-1)是找不到function的(前面沒有定義fib的類型)

是以想使用閉包解除循環函數的時候就需要使用

<code>$recursive</code> <code>=</code><code>function</code> <code>()</code><code>use</code> <code>(&amp;</code><code>$recursive</code><code>){</code>

<code>// the function is now available as $recursive</code>

這樣的形式

如果你需要延遲綁定use裡面的變量,你就需要使用引用,否則在定義的時候就會做一份拷貝放到use中

<code>$result</code> <code>= 0;</code>

<code>$one</code> <code>=</code><code>function</code><code>()</code>

<code>{ var_dump(</code><code>$result</code><code>); };</code>

<code>$two</code> <code>=</code><code>function</code><code>()</code><code>use</code> <code>(</code><code>$result</code><code>)</code>

<code>$three</code> <code>=</code><code>function</code><code>()</code><code>use</code> <code>(&amp;</code><code>$result</code><code>)</code>

<code>$result</code><code>++;</code>

<code>$one</code><code>();   </code><code>// outputs null: $result is not in scope</code>

<code>$two</code><code>();   </code><code>// outputs int(0): $result was copied</code>

<code>$three</code><code>();   </code><code>// outputs int(1)</code>

使用引用和不使用引用就代表了是調用時指派,還是申明時候指派