Created
January 26, 2012 16:13
-
-
Save k-holy/1683549 to your computer and use it in GitHub Desktop.
SplFileObject + CallbackFilterIterator(PHP5.4)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Acme; | |
// SPLのファイル処理クラスSplFileObjectとPHP5.4のCallbackFilterIteratorを試してみる | |
class U { | |
public static function H($data, $default = null) { | |
if (isset($data)) { | |
return htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); | |
} | |
return $default; | |
} | |
} | |
class FilterableFileIterator extends \SplFileObject | |
{ | |
protected $filter = null; | |
public function __set($name, $value) | |
{ | |
if (strcmp('filter', $name) === 0) { | |
if (!is_callable($value)) { | |
throw new \InvalidArgumentException('The filter is not callable.'); | |
} | |
$this->filter = $value; | |
return; | |
} | |
throw new \RuntimeException(sprintf('The field "%s" not defined.', $name)); | |
} | |
public function current() | |
{ | |
$item = parent::current(); | |
if (isset($this->filter)) { | |
$item = call_user_func($this->filter, $item, $this->key()); | |
} | |
return $item; | |
} | |
} | |
$csv_iterator = new FilterableFileIterator('php://memory', 'r+'); | |
$csv_iterator->filter = function($item, $key) { | |
if (!is_array($item)) { | |
throw new \RuntimeException(sprintf('Invalid data found at line %d', $key)); | |
} | |
$user = new \Stdclass(); | |
$user->id = (isset($item[0])) ? mb_convert_encoding(trim($item[0]), 'UTF-8', 'SJIS') : null; | |
$user->name = (isset($item[1])) ? mb_convert_encoding(trim($item[1]), 'UTF-8', 'SJIS') : null; | |
$user->comment = (isset($item[2])) ? mb_convert_encoding($item[2], 'UTF-8', 'SJIS') : null; | |
return $user; | |
}; | |
$csv_text = <<< CSV_TEXT | |
1,田中, | |
a,不正なID, | |
2,"小林""",コメント | |
3,長い名前長い名前長い名前, | |
4,"鈴木,","改行 | |
改行 | |
改行" | |
5,長井,とても長いコメントとても長いコメントとても長いコメントとても長いコメントとても長いコメント | |
CSV_TEXT; | |
$csv_text = mb_convert_encoding(str_replace("\n", "\r\n", $csv_text), 'SJIS', 'UTF-8'); | |
$csv_iterator->fwrite($csv_text); | |
$csv_iterator->rewind(); | |
$csv_iterator->setFlags(\SplFileObject::READ_CSV); | |
$csv_iterator->setCsvControl(',', '"'); | |
$validator = function($user) { | |
if (strlen($user->id) === 0) { | |
return false; | |
} | |
if (!ctype_digit($user->id)) { | |
return false; | |
} | |
if (strlen($user->name) === 0) { | |
return false; | |
} | |
if (mb_strlen($user->name) > 10) { | |
return false; | |
} | |
if (mb_strlen($user->comment) > 20) { | |
return false; | |
} | |
return true; | |
}; | |
$valid_users = new \CallbackFilterIterator($csv_iterator, function($user) use ($validator) { | |
return $validator($user); | |
}); | |
?> | |
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8" /> | |
<style type="text/css"> | |
table { | |
width:80%; | |
border-collapse:collapse; | |
margin:5px 0px; | |
} | |
caption { | |
text-align:left; | |
font-weight:bold; | |
} | |
th, td { | |
padding:2px; | |
border:solid 1px #999999; | |
} | |
tr.row1 { | |
background-color:#ffffcc; | |
} | |
tr.row2 { | |
background-color:#cccccc; | |
} | |
td.id { | |
width:5%; | |
text-align:right; | |
} | |
td.name { | |
width:30%; | |
text-align:left; | |
} | |
td.comment { | |
width:65%; | |
text-align:left; | |
white-space:pre; | |
} | |
</style> | |
</head> | |
<body> | |
<table> | |
<caption>Valid Users</caption> | |
<thead> | |
<tr> | |
<th>ID</th> | |
<th>名前</th> | |
<th>コメント</th> | |
</tr> | |
</thead> | |
<tbody> | |
<?php $number = 0;?> | |
<?php foreach ($valid_users as $user) : ?> | |
<tr class="row<?=(($number & 1) == 0) ? '1' : '2'?>"> | |
<td class="id"><?=U::H($user->id)?></td> | |
<td class="name"><?=U::H($user->name)?></td> | |
<td class="comment"><?=U::H($user->comment)?></td> | |
</tr> | |
<?php $number++; ?> | |
<?php endforeach ?> | |
</tbody> | |
</table> | |
<table> | |
<caption>All Users</caption> | |
<thead> | |
<tr> | |
<th>ID</th> | |
<th>名前</th> | |
<th>コメント</th> | |
</tr> | |
</thead> | |
<tbody> | |
<?php $number = 0;?> | |
<?php foreach ($csv_iterator as $user) : ?> | |
<tr class="row<?=(($number & 1) == 0) ? '1' : '2'?>"> | |
<td class="id"><?=U::H($user->id)?></td> | |
<td class="name"><?=U::H($user->name)?></td> | |
<td class="comment"><?=U::H($user->comment)?></td> | |
</tr> | |
<?php $number++; ?> | |
<?php endforeach ?> | |
</tbody> | |
</table> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ファイルハンドルを扱えるイテレータないの?って思ったら、SplFileObjectがSplFileInfoのイテレータ実装版だったという…。
普段はあまりSPL使ってないので知らなかったです(´・ω・`)