Successfully reported this slideshow.

PHP基本的関数QUIZ

10

Share

1 of 60
1 of 60

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

PHP基本的関数QUIZ

  1. 1. 2015-05-26 GMOリサーチ 寺田 渉 Facebook: 寺田渉 Twitter: @wa_terada
  2. 2. ボードゲーム翻訳 CakePHP Cookbook翻訳 TED 字幕 翻訳 開発 (PHP/JavaScript/Java/Perl) 0:00+30
  3. 3. PHPの仕様で 初心者がハマりやすいポイントや 知ってると便利な関数を紹介します。 0:30+15
  4. 4. 文法編
  5. 5. ==
  6. 6. これは NG!!!! が出力される。 なぜ? <?php $input = "1abc"; if ($input == 1) { echo "NG!!!!"; } 0:45+15
  7. 7. キャストされるから。 さけるには === を使う。 左右のどちらかが文字列でない場合、 == は危険。 <?php $input = "1abc"; if ($input == 1) { echo "NG!!!!"; } 1:00+15
  8. 8. empty()
  9. 9. 変数が null , false , 0 , 0.0 , '' , [] , 未定義 なら true になる。 他にもあるが何? empty(変数) 1:15+15
  10. 10. 文字列の '0' が空だと 判定されることを忘れないこと。 $var = '0'; empty($var); //←これは true 1:30+15
  11. 11. 文法っぽい関数
  12. 12. range(0, 10000, 5) 0,5,10,...という具合に 10000まで5つ刻みの数列がほしい! 1:45+15
  13. 13. $id = $array[0]; $name = $array[1]; これを下記のように書けます! list($id, $name) = $array; 2:00+15
  14. 14. 配列の +
  15. 15. この結果は違う? 配列の + と array_merge は何が違う? <?php $a = ['a' => 1, 'b' => 3, 5]; $b = ['a' => 2, 'c' => 4, 6]; var_export($a + $b); var_export(array_merge($a, $b)); 2:15+30
  16. 16. 【$a + $b】 array ( 'a' => 1, //先勝ち 'b' => 3, 'c' => 4, 0 => 5, //先勝ちで6無し ) → key/index どちら でも常に先勝ち 【array_merge($a, $b)】 array ( 'a' => 2, //後勝ち 'b' => 3, 'c' => 4, 0 => 5, 1 => 6, //勝手に連番 ) → key なら後勝ち index なら連番 $a = ['a' => 1, 'b' => 3, 5]; $b = ['a' => 2, 'c' => 4, 6]; 2:45+30
  17. 17. では、これはどうなるでしょう? <?php $a = [1,2]; $b = [3,4,5]; var_export($a + $b); var_export(array_merge($a, $b)); 3:15+15
  18. 18. 【$a + $b】 array ( 0 => 1, 1 => 2, 2 => 5, ) 【array_merge($a, $b)】 array( 0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, ) $a = [1,2]; $b = [3,4,5]; ※おそらく混乱するので 配列の + はオススメしません。3:30+15
  19. 19. ついでに array_merge_recursive
  20. 20. 下記ではどうなる? $a = ['a' => ['b' => 1]]; $b = ['a' => ['c' => 2]]; var_export(array_merge_recursive($a, $b)); //[ // 'a' => [ // 'b' => 1, // 'c' => 2, // ] //] $a = ['a' => 1]; $b = ['a' => 1]; var_export(array_merge_recursive($a, $b)); 3:45+30
  21. 21. $a = ['a' => 1]; $b = ['a' => 1]; var_export(array_merge_recursive($a, $b)); 答え: ['a' => [1, 1]] array_merge_recursive は再帰的にマージするものだが、 マージする対象に配列以外があった場合は、 配列に変換 してマージする。 配列への変換を望まないなら CakePHP なら Hash::merge が使える。 4:15+30
  22. 22. 関数編
  23. 23. 文字列 分割 いろいろ
  24. 24. <?php $str = "aaa<br/>bbb<br/>ccc"; $res = 【なんでしょう】; array ( 0 => 'aaa', 1 => 'bbb', 2 => 'ccc', ) 期待する結果: 4:45+10
  25. 25. <?php $str = "aaa<br/>bbb<br/>ccc"; $res = explode("<br/>", $str); var_export($res); array ( 0 => 'aaa', 1 => 'bbb', 2 => 'ccc', ) 結果: 4:55+05
  26. 26. <?php $str = "aaa<br/>bbb<br>ccc"; $res = 【なんでしょう】; 期待する結果: array ( 0 => 'aaa', 1 => 'bbb', 2 => 'ccc', ) 5:00+10
  27. 27. array ( 0 => 'aaa', 1 => 'bbb', 2 => 'ccc', ) <?php $str = "aaa<br/>bbb<br>ccc"; $res = preg_split('/<br¥/?>/', $str); var_export($res); 結果: 5:10+05
  28. 28. <?php $str = "aaa<br/>bbb<br>ccc"; $res = 【なんでしょう】; 期待する結果: array ( 0 => 'aaa', 1 => '<br/>', 2 => 'bbb', 3 => '<br>', 4 => 'ccc', ) 5:15+10
  29. 29. <?php $str = "aaa<br/>bbb<br>ccc"; $res = preg_split('/(<br¥/?>)/', $str, null, PREG_SPLIT_DELIM_CAPTURE); var_export($res); array ( 0 => 'aaa', 1 => '<br/>', 2 => 'bbb', 3 => '<br>', 4 => 'ccc', ) 結果: 5:25+05
  30. 30. <?php $str = "aaa<br/>bbb<br>ccc"; $res = str_split($str, 5); var_export($res); array ( 0 => 'aaa<b', 1 => 'r/>bb', 2 => 'b<br>', 3 => 'ccc', ) 結果: 5:30+15
  31. 31. array_map と array_walk
  32. 32. 指定した配列の要素に コールバック関数を適用する ( http://jp1.php.net/manual/ja/function.array-map.php より) 配列の全ての要素に ユーザー定義の関数を適用する ( http://jp1.php.net/manual/ja/function.array-walk.php より) 答えはドキュメントの中! ヒント:引数と戻り値 array array_map ( callable $callback , array $array1 [, array $... ] ) bool array_walk ( array &$array , callable $callback [, mixed $use 5:45+30
  33. 33. array_map array_walk array array_map ( callable $callback , array $array1 [, array $.. bool array_walk ( array &$array , callable $callback [, mixed $u そう! array_map は変更後の新しい配列を作るためのもの array_walk は自身を書き換えるためのもの 6:15+30
  34. 34. foreach で 置き換え
  35. 35. $array1 = [1,2]; foreach ($array1 as &$val) { $val = '書換'; } $array2 = [3,4]; foreach ($array2 as $val) { //何か } var_export($array1); // ['書換', 4] なぜ!? var_export($array2); // [3, 4] 6:45+30
  36. 36. $array1 = [1,2]; foreach ($array1 as &$val) { $val = ‘書換’; } $array2 = [3,4]; foreach ($array2 as $val) { //何か }
  37. 37. $array1 = [1,2]; foreach ($array1 as &$val) { $val = ‘書換’; } unset($val); //かならずこれが必要 $array2 = [3,4]; foreach ($array2 as $val) { //何か } 7:15+15
  38. 38. $array1 = [1,2]; array_walk($array1, function(&$val) { $val = '書換'; }); //これなら危険は無い。これがオススメ。 $array2 = [3,4]; foreach ($array2 as $val) { //何か } 7:30+15
  39. 39. エンコードする タイミング
  40. 40. これは何がNGか解りますか? $fh = fopen($path, 'r'); while (($data = fgetcsv($fh, 1000, ",")) !== false) { array_walk($data, function(&$val) { $val = mb_convert_encoding($val,'UTF-8','SJIS'); }); // $data を使う処理 } fclose($fh); 7:45+30
  41. 41. ならOK? まだダメですよね? $fh = fopen($path, 'r'); while (($line = fgets($fh)) !== false) { $line = mb_convert_encoding($line,'UTF-8','SJIS'); $data = str_getcsv($line, ","); // $data を使う処理 } fclose($fh); エンコード前に fgetcsv を呼んではいけません。 区切り文字等の認識がエンコード前では正しくできないからです。 ならば 8:15+20
  42. 42. そう。 改行コードが正しく認識できません。 じゃ、どうする? $fh = fopen($path, 'r'); while (($line = fgets($fh)) !== false) { $line = mb_convert_encoding($line,'UTF-8','SJIS'); $data = str_getcsv($line, ","); // $data を使う処理 } fclose($fh); 8:35+10
  43. 43. そこでストリームフィルタです! $fh = fopen($path, 'r'); stream_filter_append($fh, 'convert.iconv.utf-16le/utf-8', STREAM_FILTER_READ); while (($data = fgetcsv($fh, 1000, ",")) !== false) { // $data を使う処理 } fclose($fh); stream_filter_append($fh, 'convert.iconv.cp932/utf-8', Shift_JIS を読む場合はこう: 8:45+30
  44. 44. SPL編Standard PHP Library (SPL) (標準で入っているライブラリ) http://jp1.php.net/manual/ja/book.spl.php
  45. 45. バグ検出用の例外
  46. 46. LogicException throwされたらバグだという場合の例外。 つまり、これをキャッチするプログラムは不要だし、 運用中には絶対throwされないようにすべき。 バグを発見しやすくするために仕込む例外はコレ。 if ($data == null) { throw new LogicException( "dataがnullの場合はこの関数使えません"); } 9:15+30
  47. 47. LogicException の代わりに 下記の関数作っておくのもオススメ。 https://github.com/waterada/phplib-bug_if 9:45+90
  48. 48. イテレータ
  49. 49. 通常、foreach で回すには、 全要素をメモリに保持する必要があるし、 要素に対する制御はループの中に書く。 しかし イテレータを使うと 要素ごとのメモリ読み込みができたり、 要素の制御をループ外に定義できる。 =メモリに優しく、汎用化しやすい (身近なものでいうと bash コマンドのイメージ) イテレータ 11:15+15
  50. 50. SplFileObject ファイルの1行ずつをイテレータとして扱える。 <?php $ite = new SplFileObject($path); $ite->setFlags(SplFileObject::READ_CSV); foreach ($ite as $line) { echo $line[0]; } $ite = null; //close 11:30+15
  51. 51. AppendIterator イテレータ複数を1つのイテレータとして扱える。 サイズが大きくて array_merge では心配なとき良い。 $ite = new AppendIterator(); $ite->append(new ArrayIterator([1,2,3])); $ite->append(new ArrayIterator([5,6,7])); foreach ($ite as $a) { echo $a; } //result: 123567 11:45+60
  52. 52. LimitIterator イテレータのループ範囲を限定する。上位100件とか。 $ite = new LimitIterator( new ArrayIterator([1,2,3,4,5,6,7] , 2, 4); foreach ($ite as $a) { echo $a; } //3456 12:45+15
  53. 53. CallbackFilterIterator イテレータにフィルタを適用する。 $ite = new CallbackFilterIterator( new ArrayIterator([1,2,3,4,5,6,7]), function($current, $key, $iterator) { return $current % 2 == 0; } ); foreach ($ite as $a) { echo $a; } //246 13:00+15
  54. 54. Iterator (インターフェイス) を implements して、 current(), next(), key(), valid(), rewind() を実装すれば 誰でもイテレータの自作が可能。 ちょっと作ってみましょう。 13:15+15
  55. 55. Iterator (例) class OreOreArrayIterator implements Iterator { private $array; private $i; public function __construct($array) { $this->array = $array; $this->i = 0; } public function rewind() { $this->i = 0; } public function next() { $this->i++; } public function valid() { return ($this->i < count($this->array)); } public function key() { return $this->i; } public function current() { return $this->array[$this->i]; } } foreach (new OreOreArrayIterator([1,2,3]) as $a) { echo $a; } //123 13:30+60
  56. 56. PHP5.5 から ジェネレータ構文 が 導入されました。 yield って書くやつですね。 これを使うと 簡単に Iterator が作れます。 14:30+60
  57. 57. yield (例) function generateOreOreArrayIterator($array) { foreach ($array as $a) { yield $a; } } foreach (generateOreOreArrayIterator([1,2,3]) as $a) { echo $a; } //123 簡単ですね! ただし、 yield で作った Iterator は 巻き戻せません(使い捨て) ので気をつけて。 14:30+60
  58. 58. 公式ホームページは宝の山です!! http://jp1.php.net/manual/ja/
  59. 59. PHPの公式ホームページは かなり充実しています。 特に 文法 、 配列 、 文字列 、 SPL まわり は一度ざっと読んでおくと良いでしょう。 判らなかったら公式ホームページ を見てみましょう! 15:30+15
  60. 60. ぜひ Facebook 等で 寺田渉 まで ご連絡ください!! ご清聴ありがとうございました!

×