PHPの無名関数について。
PHP5.3.0以降で実装され、概念としては知っていましたが、あまり使ったことがありませんでした。
今開発しているPHPの案件で無名関数のソースをみたので、復習もかねてメモです。
無名関数とは?
基本的な使用法
その名のとおり、名前のない関数のことです。JavaScriptなんかでは大量にでてきますが、下記のようなソースです。別名クロージャーともいわれるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//変数への無名関数の代入 $greet = function($name) { printf("Hello %s\r\n", $name); }; $greet('World'); //Hello World $n = 10; $func1 = function( $n ) { return $n * 2; } $var1 = $func1( 10 ); echo $var1; //20; |
http://php.net/manual/ja/functions.anonymous.php
array_map系
無名関数と同時に扱われやすい、array_map,array_walk,array_filter,array_column,array_reduceなど。
1 2 3 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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
<?php $arr = [100,200,300]; $arr2 = array_map(function ($val){ return $val * 2; }, $arr); var_dump($arr2); //array(3) { // [0] => // int(200) // [1] => // int(400) // [2] => // int(600) //} $double_price = function ($val){ return $val * 2; }; $arr3 = array_map($double_price, $arr); var_dump($arr3);//$arr2と同じ $arr4 = array_walk( $arr, function ($val){ return $val * 2; }); var_dump($arr4); //trueが返る $arr=[ ["name"=>" kazumi", "domain"=>"gmail.com", "age"=>"30","pref"=>"chiba"], ["name"=>"ichirou","domain"=>"yahoo.co.jp", "age"=>"18","pref"=>"tokyo"], ["name"=>" yuusuke","domain"=>"hotmail.com", "age"=>"25","pref"=>"chiba"], ["name"=>" satoshi","domain"=>"gmail.com", "age"=>"45","pref"=>"kanagawa"], ["name"=>"jirou ", "domain"=>"hotmail.com", "age"=>"9","pref"=>"tokyo"] ]; $arr5 = array_filter( $arr, function ( $val){ return $val['age'] >= 20 && $val['pref'] === 'chiba'; }); var_dump($arr5); //array(2) { // [0] => // array(4) { // 'name' => // string(7) " kazumi" // 'domain' => // string(9) "gmail.com" // 'age' => // string(2) "30" // 'pref' => // string(5) "chiba" // } // [2] => // array(4) { // 'name' => // string(8) " yuusuke" // 'domain' => // string(11) "hotmail.com" // 'age' => // string(2) "25" // 'pref' => // string(5) "chiba" // } //特定のカラム抜き出し $arr6 = array_column($arr, 'name'); var_dump($arr6); //array(5) { // [0] => // string(7) " kazumi" // [1] => // string(7) "ichirou" // [2] => // string(8) " yuusuke" // [3] => // string(8) " satoshi" // [4] => // string(6) //} $arr7 = array_map(function ($val){ return $val['name'];}, $arr); var_dump($arr7);//$arr6と同じ //30歳以上のメルアド(名前の空白を削除し、名前+@+domain)を作る //若干読みにくいがarray_filterで配列を作り、そのあとarray_mapに渡している $arr8 = array_map(function ($val){ $val["email"] = $val["name"] ."@" . $val["domain"]; return $val; },array_filter($arr, function ($val){ return $val['age'] >= 30; })); var_dump($arr8); //array(2) { // [0] => // array(5) { // 'name' => // string(7) " kazumi" // 'domain' => // string(9) "gmail.com" // 'age' => // string(2) "30" // 'pref' => // string(5) "chiba" // 'email' => // string(17) " kazumi@gmail.com" // } // [3] => // array(5) { // 'name' => // string(8) " satoshi" // 'domain' => // string(9) "gmail.com" // 'age' => // string(2) "45" // 'pref' => // string(8) "kanagawa" // 'email' => // string(18) " satoshi@gmail.com" // } //} $arr = [100,200,300]; $arr2 = array_reduce($arr,function ($res, $val){ $res += $val; return $res; }); var_dump($arr2); //600 $arr = [ [ "name" => " kazumi", "domain" => "gmail.com", "age" => "30", "pref" => "chiba", "score" => '75' ], [ "name" => "ichirou", "domain" => "yahoo.co.jp", "age" => "18", "pref" => "tokyo", "score" => '23' ], [ "name" => " yuusuke", "domain" => "hotmail.com", "age" => "25", "pref" => "chiba", "score" => '92' ], [ "name" => " satoshi", "domain" => "gmail.com", "age" => "45", "pref" => "kanagawa", "score" => '17' ], [ "name" => "jirou ", "domain" => "hotmail.com", "age" => "9", "pref" => "tokyo", "score" => '43' ] ]; //30才以上のスコアの取得 $arr3 = array_reduce($arr, function ($res, $val){ if (empty($res)) $res = ['count' => 0,'score'=>0]; if ($val['age'] >=30) { $res['count']++; $res['score'] += $val['score']; } return $res; }); var_dump($arr3); //array(2) { // 'count' => // int(2) // 'score' => // int(92) //} //年齢順にソート usort( $arr, function ($a,$b){ return $a['age'] - $b['age']; }); array_map(function ($val){echo $val['name'] . " " .$val['age']. "\n";}, $arr); //jirou 9 //ichirou 18 //yuusuke 25 //kazumi 30 //satoshi 45 |
array_reduce を使い倒す
PHP 配列操作あれこれ
useを使ったバインディング
本来PHPは関数外の変数を使用することはできませんが、useを使うことで引数としてではなく、関数外の値を使うことができます。また参照渡しにすることで遅延バインディングも可能です。
1 2 3 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 |
$n = 8; $m = 9; $func = function ($a) use ($n, $m) { return $a + ($n * $m); }; //この時点で$nと$mが決定しているので、 //この後下記のように$nと$mを変更しても値は変わらない $n = 1; $m = 2; // 無名関数の実行 $answer = $func(10); echo $answer; //82 echo "\n----------------------------------\n"; $n = 8; $m = 9; $func = function () use ( &$n, &$m) { return $n * $m; }; //上記は参照なので //この後下記のように$nと$mを変更すると値は変わる //また引数を使わないことも当然できる $n = 1; $m = 2; // 無名関数の実行 $answer = $func(); echo $answer; //2 |