第45回PHP勉強会に参加してきました。


久しぶりにPHP勉強会に参加してきました。第45回PHP勉強会@関東 - events.php.gr.jp

場所ははてなというおいしい鉄板焼きのお店でした。
また、gusagiさんのテンポよい司会進行でとても楽しい時間を過ごせました。ありがとうございました。


私自身は参加表明自体が遅く時間がなかったので、以前ブログで書いたArrayObjectでエスケープ処理させるサンプルをLTで発表しました。
そのときにforeachだとエスケープされないーと言ったところ、「それはイテレータを実装してないからでは」とツッコミをいただきました。なるほどーというわけで、イテレータを実装したところちゃんと無事エスケープ処理させることができました。

というわけで、イテレータも実装したコードは以下になりました。

<?php
Class EscapeArray extends ArrayObject {
  public function __construct($input=array(), $flag=self::STD_PROP_LIST, $iterator_class='EscapeArrayIterator')
  {
    parent::__construct($input, $flag, $iterator_class);
  }
  public function offsetGet($id)
  {
    $v = parent::offsetGet($id);
    if (is_array($v)) {
      array_walk_recursive($v, array($this, 'escape'));
    } else {
      self::escape($v);
    }
    return $v;
  }
  public static function escape(&$v)
  {
    $v = htmlspecialchars_decode($v, ENT_QUOTES);
    $v = htmlspecialchars($v, ENT_QUOTES, 'utf-8');
  }
}
class EscapeArrayIterator extends ArrayIterator
{
  public function current()
  {
    $v = parent::current();
    if (is_array($v)) {
      array_walk_recursive($v, array('EscapeArray', 'escape'));
    } else {
      EscapeArray::escape($v);
    }
    return $v;
  }
}

これで以下のように直接echoしても、foreachで回しているものをechoしてもエスケープされるようになりました。

<?php
$str =  '<script>alert("test")</script>';

$tpl_values = new EscapeArray();
$tpl_values['attack'] = $str;

echo $tpl_values['attack'];  // &lt;script&gt;alert(&quot;test&quot;)&lt;/script&gt;

foreach ($tpl_values as $k => $v) {
  echo $v; // &lt;script&gt;alert(&quot;test&quot;)&lt;/script&gt;
}