2015-05-26 GMOリサーチ 寺田 渉
Facebook: 寺田渉 Twitter: @wa_terada
ボードゲーム翻訳
CakePHP Cookbook翻訳
TED 字幕 翻訳
開発 (PHP/JavaScript/Java/Perl)
0:00+30
PHPの仕様で
初心者がハマりやすいポイントや
知ってると便利な関数を紹介します。
0:30+15
文法編
==
これは NG!!!! が出力される。
なぜ?
<?php
$input = "1abc";
if ($input == 1) { echo "NG!!!!"; }
0:45+15
キャストされるから。
さけるには === を使う。
左右のどちらかが文字列でない場合、
== は危険。
<?php
$input = "1abc";
if ($input == 1) { echo "NG!!!!"; }
1:00+15
empty()
変数が
null , false , 0 , 0.0 , '' , [] , 未定義
なら true になる。
他にもあるが何?
empty(変数)
1:15+15
文字列の '0' が空だと
判定されることを忘れないこと。
$var = '0';
empty($var); //←これは true
1:30+15
文法っぽい関数
range(0, 10000, 5)
0,5,10,...という具合に
10000まで5つ刻みの数列がほしい!
1:45+15
$id = $array[0];
$name = $array[1];
これを下記のように書けます!
list($id, $name) = $array;
2:00+15
配列の +
この結果は違う?
配列の + と array_merge は何が違う?
<?php
$a = ['a' => 1, 'b' => 3, 5];
$b = ['a' => 2, 'c' => 4, 6];
var_export($a + $b);...
【$a + $b】
array (
'a' => 1, //先勝ち
'b' => 3,
'c' => 4,
0 => 5,
//先勝ちで6無し
)
→ key/index どちら
でも常に先勝ち
【array_merge($a, $b)】
ar...
では、これはどうなるでしょう?
<?php
$a = [1,2];
$b = [3,4,5];
var_export($a + $b);
var_export(array_merge($a, $b));
3:15+15
【$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...
ついでに
array_merge_recursive
下記ではどうなる?
$a = ['a' => ['b' => 1]];
$b = ['a' => ['c' => 2]];
var_export(array_merge_recursive($a, $b));
//[
// 'a' => [
/...
$a = ['a' => 1];
$b = ['a' => 1];
var_export(array_merge_recursive($a, $b));
答え: ['a' => [1, 1]]
array_merge_recursive は再帰...
関数編
文字列 分割
いろいろ
<?php
$str = "aaa<br/>bbb<br/>ccc";
$res = 【なんでしょう】;
array (
0 => 'aaa',
1 => 'bbb',
2 => 'ccc',
)
期待する結果:
4:45+10
<?php
$str = "aaa<br/>bbb<br/>ccc";
$res = explode("<br/>", $str);
var_export($res);
array (
0 => 'aaa',
1 => 'bbb',
2 => ...
<?php
$str = "aaa<br/>bbb<br>ccc";
$res = 【なんでしょう】;
期待する結果:
array (
0 => 'aaa',
1 => 'bbb',
2 => 'ccc',
)
5:00+10
array (
0 => 'aaa',
1 => 'bbb',
2 => 'ccc',
)
<?php
$str = "aaa<br/>bbb<br>ccc";
$res = preg_split('/<br¥/?>/', $str);
var...
<?php
$str = "aaa<br/>bbb<br>ccc";
$res = 【なんでしょう】;
期待する結果:
array (
0 => 'aaa',
1 => '<br/>',
2 => 'bbb',
3 => '<br>',
4 =...
<?php
$str = "aaa<br/>bbb<br>ccc";
$res = preg_split('/(<br¥/?>)/', $str,
null, PREG_SPLIT_DELIM_CAPTURE);
var_export($res...
<?php
$str = "aaa<br/>bbb<br>ccc";
$res = str_split($str, 5);
var_export($res);
array (
0 => 'aaa<b',
1 => 'r/>bb',
2 => '...
array_map
と
array_walk
指定した配列の要素に
コールバック関数を適用する
( http://jp1.php.net/manual/ja/function.array-map.php より)
配列の全ての要素に
ユーザー定義の関数を適用する
( http://jp1.p...
array_map
array_walk
array array_map ( callable $callback , array $array1 [, array $..
bool array_walk ( array &$array , c...
foreach
で
置き換え
$array1 = [1,2];
foreach ($array1 as &$val) {
$val = '書換';
}
$array2 = [3,4];
foreach ($array2 as $val) {
//何か
}
var_expor...
$array1 = [1,2];
foreach ($array1 as &$val) {
$val = ‘書換’;
}
$array2 = [3,4];
foreach ($array2 as $val) {
//何か
}
$array1 = [1,2];
foreach ($array1 as &$val) {
$val = ‘書換’;
}
unset($val); //かならずこれが必要
$array2 = [3,4];
foreach ($array2 as...
$array1 = [1,2];
array_walk($array1, function(&$val) {
$val = '書換';
});
//これなら危険は無い。これがオススメ。
$array2 = [3,4];
foreach ($ar...
エンコードする
タイミング
これは何がNGか解りますか?
$fh = fopen($path, 'r');
while (($data = fgetcsv($fh, 1000, ",")) !== false) {
array_walk($data, function(&...
ならOK? まだダメですよね?
$fh = fopen($path, 'r');
while (($line = fgets($fh)) !== false) {
$line = mb_convert_encoding($line,'UTF-8...
そう。
改行コードが正しく認識できません。
じゃ、どうする?
$fh = fopen($path, 'r');
while (($line = fgets($fh)) !== false) {
$line = mb_convert_encodi...
そこでストリームフィルタです!
$fh = fopen($path, 'r');
stream_filter_append($fh, 'convert.iconv.utf-16le/utf-8',
STREAM_FILTER_READ);
wh...
SPL編Standard PHP Library (SPL)
(標準で入っているライブラリ)
http://jp1.php.net/manual/ja/book.spl.php
バグ検出用の例外
LogicException
throwされたらバグだという場合の例外。
つまり、これをキャッチするプログラムは不要だし、
運用中には絶対throwされないようにすべき。
バグを発見しやすくするために仕込む例外はコレ。
if ($data ==...
LogicException の代わりに
下記の関数作っておくのもオススメ。
https://github.com/waterada/phplib-bug_if
9:45+90
イテレータ
通常、foreach で回すには、
全要素をメモリに保持する必要があるし、
要素に対する制御はループの中に書く。
しかし
イテレータを使うと
要素ごとのメモリ読み込みができたり、
要素の制御をループ外に定義できる。
=メモリに優しく、汎用化しや...
SplFileObject
ファイルの1行ずつをイテレータとして扱える。
<?php
$ite = new SplFileObject($path);
$ite->setFlags(SplFileObject::READ_CSV);
forea...
AppendIterator
イテレータ複数を1つのイテレータとして扱える。
サイズが大きくて array_merge では心配なとき良い。
$ite = new AppendIterator();
$ite->append(new Array...
LimitIterator
イテレータのループ範囲を限定する。上位100件とか。
$ite = new LimitIterator(
new ArrayIterator([1,2,3,4,5,6,7] , 2, 4);
foreach ($it...
CallbackFilterIterator
イテレータにフィルタを適用する。
$ite = new CallbackFilterIterator(
new ArrayIterator([1,2,3,4,5,6,7]),
function($c...
Iterator (インターフェイス)
を implements して、
current(), next(), key(), valid(), rewind() を実装すれば
誰でもイテレータの自作が可能。
ちょっと作ってみましょう。
13:1...
Iterator (例)
class OreOreArrayIterator implements Iterator {
private $array;
private $i;
public function __construct($arra...
PHP5.5 から ジェネレータ構文 が
導入されました。
yield って書くやつですね。
これを使うと
簡単に Iterator が作れます。
14:30+60
yield (例)
function generateOreOreArrayIterator($array) {
foreach ($array as $a) {
yield $a;
}
}
foreach (generateOreOreArr...
公式ホームページは宝の山です!!
http://jp1.php.net/manual/ja/
PHPの公式ホームページは
かなり充実しています。
特に 文法 、 配列 、 文字列 、 SPL まわり
は一度ざっと読んでおくと良いでしょう。
判らなかったら公式ホームページ
を見てみましょう!
15:30+15
ぜひ Facebook 等で
寺田渉 まで
ご連絡ください!!
ご清聴ありがとうございました!
Upcoming SlideShare
Loading in …5
×

PHP基本的関数QUIZ

2,371 views

Published on

PHP基本的関数QUIZ!!
意外と知らない便利な基本的関数の紹介

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,371
On SlideShare
0
From Embeds
0
Number of Embeds
949
Actions
Shares
0
Downloads
12
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

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 等で 寺田渉 まで ご連絡ください!! ご清聴ありがとうございました!

×