摘要:匿名函數輸出可以直接將匿名函數進行傳遞。報錯,找不到變量之所以稱為副本,是因為通過閉包傳值到匿名函數內的變量值也是不能改變。該方法使用了一個作為回調函數。
匿名函數
// Example1 $func = function( $param ) { echo $param; }; $func( "some string" );//輸出:some string // Example2 function callFunc( $func ) { $func( "some string" ); } $printStrFunc = function( $str ) { echo $str; }; callFunc( $printStrFunc ); //可以直接將匿名函數進行傳遞。如果你了解js,這種寫法可能會很熟悉 callFunc( function( $str ) { echo $str; } );閉包
PHP在默認情況下,匿名函數內不能調用所在代碼塊的上下文變量,而需要通過使用use關鍵字。
//1. 通過閉包獲取當前函數環境外的變量值副本。 function getMoney() { $rmb = 1; $dollar = 6; $func = function() use ( $rmb ) { echo $rmb; //1 echo $dollar; //報錯,找不到dorllar變量 }; $func(); } getMoney(); //2. 之所以稱為副本,是因為通過閉包傳值到匿名函數內的變量,值也是不能改變。 function getMoney() { $rmb = 1; $func = function() use ( $rmb ) { $rmb += 2; echo $rmb; // 3 }; $func(); echo $rmb; // 還是1沒有改變; } getMoney(); //3. 如果要改變外部變量的值,還是得通過傳址的方法 function getMoney() { $rmb = 1; $func = function() use ( &$rmb ) { $rmb += 2; echo $rmb; // 3 }; $func(); echo $rmb; // 3; } getMoney(); //4. function getMoneyFunc() { $rmb = 1; $func = function() use(&$rmb){ echo $rmb; //把$rmb的值加1 $rmb++; }; return $func; // 如果將匿名函數返回給外界,匿名函數會保存use所引用的變量,而外界則不能得到這些變量,這樣形成‘閉包’ } $getMoney = getMoneyFunc(); $getMoney(); // 1 $getMoney(); // 2 $getMoney(); // 3閉包的好處
1. 減少循環
// 一個基本的購物車,包括一些已經添加的商品和每種商品的數量。 // 其中有一個方法用來計算購物車中所有商品的總價格。該方法使用了一個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(__CLASS__ . "::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) . " "; // The result is 54.29
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"; }; } $tag = html("div","","class"); // 可讀性和可維護性大大提高; echo $tag("div1,div1,div1"); echo PHP_EOL; echo $tag("div2,div2,div2");
3. 解除遞歸函數
// ↓↓ 注意,這里的fib一定要用引用哦,因為第一次的時候就會Notice: Undefined variable,然后后面的fib()就會錯誤; $fib = function($n) use (&$fib){ if ($n == 0 || $n == 1) return 1; return $fib($n - 1) + $fib($n - 2); }; echo $fib(2) . " "; // 2 $lie = $fib; $fib = function(){ die("error"); };//rewrite $fib variable echo $lie(5); // error 達到遞歸解除;
4. 關于延遲綁定
$result = 0; $one = function(){ var_dump($result); }; $two = function() use ($result){ var_dump($result); }; // 在回調生成的時候進行賦值; $four = function() use ($result){ //0 回調生成的時候賦值,也就是$result = 0; var_dump($result); }; // 如果使用引用,就能使use里面的變量完成延遲綁定,也就是在調用的時候再賦值; $three = function() use (&$result){ //1 在調用的時候再賦值進去,也就是1,注意對象類型也屬于引用; var_dump($result); }; $result += 1; $one(); // outputs NULL: $result is not in scope $two(); // outputs int(0): $result was copied $three(); // outputs int(1) $four(); // outputs int(0)幾個配合回調或閉包的函數
bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] )
/** * @param array $array * @param callable $funcname () * @param mixed|NULL $userdata * @return bool * bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] ) */ $fruits = array( "d" => "lemon" , "a" => "orange" , "b" => "banana" , "c" => "apple" ); $test_print = function(&$item2 , $key, $prefix){ $item2 .= " 10"; echo "{$prefix} : $key => $item2 "; }; /* this result : d => lemon this result : a => orange this result : b => banana this result : c => apple */ array_walk($fruits , $test_print, "this result"); print_r($fruits); /* Array ( [d] => lemon 10 [a] => orange 10 [b] => banana 10 [c] => apple 10 ) */
bool array_walk_recursive ( array &$input , callable $funcname [, mixed $userdata = NULL ]
$sweet = array( "a" => "apple" , "b" => "banana" ); $fruits = array( "sweet" => $sweet , "sour" => "lemon" ); $test_print = function($item , $key) { echo "$key holds $item "; }; array_walk_recursive($fruits , $test_print); /* * 自動跳過sweet,因為sweet是數組;任何其值為 array 的鍵都不會被傳遞到回調函數中去 a holds apple b holds banana sour holds lemon */
array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
$odd = function($var){ return ($var & 1); }; $even = function($var){ return (!($var & 1)); }; $array1 = array( "a" => 1 , "b" => 2 , "c" => 3 , "d" => 4 , "e" => 5 ); $array2 = array( 6 , 7 , 8 , 9 , 10 , 11 , 12 ); echo "Odd : "; print_r(array_filter($array1 , "odd")); /* Odd : Array ( [a] => 1 [c] => 3 [e] => 5 ) */ echo "Even: "; print_r(array_filter($array2 , "even")); /* Even: Array ( [0] => 6 [2] => 8 [4] => 10 [6] => 12 ) */ # 如果不傳第二參數的的話 $entry = array( 0 => "foo", 1 => false, 2 => -1, 3 => null, 4 => "" ); print_r(array_filter($entry)); /* * 當前值為false的話就filter; Array ( [0] => foo [2] => -1 ) */
array array_map ( callable $callback , array $arr1 [, array $array ] )
/** * @param callable $callback * @param array $arr1 * @param array $array */ $func = function($value) { return $value * 2; }; print_r(array_map($func, range(1, 5))); /* Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 ) */ $show_Spanish = function($n , $m){ return ("The number $n is called $m in Spanish"); }; $a = array( 1 , 2 , 3 , 4 , 5 ); $b = array( "uno" , "dos" , "tres" , "cuatro" , "cinco" ); $c = array_map($show_Spanish , $a , $b); /** print_r($c); Array ( [0] => The number 1 is called uno in Spanish [1] => The number 2 is called dos in Spanish [2] => The number 3 is called tres in Spanish [3] => The number 4 is called cuatro in Spanish [4] => The number 5 is called cinco in Spanish ) */ $map_Spanish = function($n , $m){ return (array($n => $m)); }; $d = array_map($map_Spanish , $a , $b); print_r($d); /** Array ( [0] => Array ( [1] => uno ) [1] => Array ( [2] => dos ) [2] => Array ( [3] => tres ) [3] => Array ( [4] => cuatro ) [4] => Array ( [5] => cinco ) ) */
mixed array_reduce ( array $input , callable $function [, mixed $initial = NULL ] )
/** * 用回調函數迭代地將數組簡化為單一的結果值,解釋不清楚的一看代碼就明白了; * @param array $input * @param callable $function * @param mixed|NULL $initial 如果指定了可選參數 initial,該參數將被當成是數組中的第一個值來處理,或者如果數組為空的話就作為最終返回值。 */ $rsum = function($result , $value){ // $result 初始值為NULL, 如果有第三參數的話,第三參數為初始值; $result += $value; return $result; }; $rmul = function($result , $value){ $result *= $value; return $result; }; $a = array(1, 2, 3, 4, 5); $x = array(); $b = array_reduce($a, $rsum); // (NULL)0+1+2+3+4+5 = 15; $c = array_reduce($a, $rmul, 10); // 10*1*2*3*4*5 = 1200; $d = array_reduce($x, $rsum, "No data to reduce"); // No data to reduce
mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] )
/** * @param mixed $pattern 正則模式; * @param callable $callback * @param mixed $subject * @param int $limit 對于每個模式用于每個 subject 字符串的最大可替換次數。 默認是-1(無限制)。 * @param int $count 如果指定,這個變量將被填充為替換執行的次數。 * mixed preg_replace_callback ( mixed $pattern , callable $callback , mixed $subject [, int $limit = -1 [, int &$count ]] ) */ // 將文本中的年份增加一年. $text = "April fools day is 04/01/2002 "; $text .= "Last christmas was 12/24/2001 "; // 回調函數 $next_year = function($matches){ // 通常: $matches[0]是完成的匹配 // $matches[1]是第一個捕獲子組的匹配 // 以此類推 return $matches[1] . ($matches[2] + 1); }; echo preg_replace_callback("|(d{2}/d{2}/)(d{4})|" , $next_year , $text);
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
mixed call_user_func_array ( callable $callback , array $param_arr )
/** * @param callable $callback 第一個參數為需要調用的函數; 如果是數組array($classname, $methodname) * @param mixed $parameter 第二個參數開始就是隊列進該函數的參數; * @param mixed $parameter2 * @param mixed $parameter3 * .. * @return 返回值:返回調用函數的結果,或FALSE */ $eat = function($fruit , $num){ //參數可以為多個 echo "You want to eat $fruit $num pcs, no problem "; }; call_user_func($eat , "apple" , 10); //print: You want to eat apple 10 pcs, no problem; call_user_func($eat , "orange" , 5); //print: You want to eat orange 5 pcs,no problem; // 調用類方法 class myclass { public static function say_hello($name,$message) { echo "Hello! $name $message"; } } //array(類名,靜態方法名),參數 call_user_func(array("myclass", "say_hello"), "dain_sun", "good person"); call_user_func_array(array("myclass", "say_hello"), array("dain_sun", "good person")); // Hello! dain_sun good person
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31417.html
摘要:復制當前閉包對象,綁定指定的對象和類作用域。類作用域,可以是對象,也可以是實例名稱什么是匿名類先理解以下三個例子例閉包函數都是繼承類返回匿名函數返回匿名函數,也就是閉包函數,所有閉包函數都是繼承類輸出例將一個匿名函數綁定到一個類中。 類結構 Closure { /* 方法 */ // 用于禁止實例化的構造函數 __construct ( void ) ...
摘要:它使得在生產環境中啟用斷言為零成本,并且提供當斷言失敗時拋出特定異常的能力。錯誤和異常改變了大多數錯誤的報告方式。不同于傳統的錯誤報告機制,現在大多數錯誤被作為異常拋出。 PHP7性能 7最大的亮點,應該就是性能提高了兩倍,某些測試環境下甚至提高到三到五倍,具體可以了解以下鏈接: PHP7 VS HHVM (WordPress) HHVM vs PHP 7 – The Competit...
摘要:通過生成器來生成關聯數組下面每一行是用分號分割的字段組合,第一個字段將被用作鍵名。正常來說,產生的是一個,它的成員變量與函數不存在別名引用關系。關鍵字在的版本,生成器允許從其他生成器,可迭代對象或數組通過關鍵字來生成對應的值輸出 一般你在迭代一組數據的時候,需要創建一個數據,假設數組很大,則會消耗很大性能,甚至造成內存不足。 //Fatal error: Allowed memory ...
摘要:而依賴倒置原則的思想是,上層不應該依賴下層,應依賴接口。上面通過構造函數注入對象的方式,就是最簡單的依賴注入當然注入不僅可以通過構造函數注入,也可以通過屬性注入,上面你可以通過一個來動態為這個屬性賦值。 依賴倒置和控制反轉是一種編程思想,而依賴注入就是通過服務容器實現這種面向接口或者是面向抽象編程的思想 概念理解 依賴倒置原則 依賴倒置是一種軟件設計思想,在傳統軟件中,上層代碼依賴于下...
摘要:可以在任何時候啟用和禁用斷言驗證,因此可以在測試時啟用斷言,而在部署時禁用斷言。會檢查指定的并在結果為時采取適當的行動視而定。中的斷言向后兼用并增強之前的的方法。它使得在生產環境中啟用斷言為零成本,并且提供當斷言失敗時拋出特定異常的能力。 簡述 編寫代碼時,我們總是會做出一些假設,斷言就是用于在代碼中捕捉這些假設,可以將斷言看作是異常處理的一種高級形式。程序員斷言在程序中的某個特定點該...
閱讀 2241·2023-04-26 01:50
閱讀 706·2021-09-22 15:20
閱讀 2579·2019-08-30 15:53
閱讀 1585·2019-08-30 12:49
閱讀 1704·2019-08-26 14:05
閱讀 2700·2019-08-26 11:42
閱讀 2298·2019-08-26 10:40
閱讀 2587·2019-08-26 10:38