昔、Phalconで実装したことがありましたが、
Cakeだと、どうやれば良いのかと。
デフォルトで対応してくれれば良いのにと、昔から思ってるんですけどね。
あと、以下の様にプラグインを書いてる方もいらっしゃる様ですが、
プラグインなので、導入できない場合や、あと細かい調整がなぁと。
参考にした方が良さそうな所は、ありましたけどね。
[Cakephp3] もう毎回 h() なんて書きたくない!! - Qiita
なので、以下を書いてみました。
個々のシステムによって、細かい調整が必要かと思いますけどね。
あと、PHPは7.1以上が必要ですが、
Cake3のマイナーバージョンまでは、良く分かりません。
<?php // 今回の処理と関係無い所は省略しています class AppController extends Controller { // エスケープしない項目リスト // 必要に応じて、子クラスで値を入れておく private $notEscapeNameList = []; protected function addNotEscapeNameList($name, $value) { $this->notEscapeNameList[$name] = $value; } public function beforeRender(Event $event) { // レンダリングする直前なので、以下のエスケープ処理終了後に書いた方が良いか? parent::beforeRender($event); // viewVarsに、子クラスで$this->setされた内容が入っている foreach ($this->viewVars as $name => $value) { // エスケープしない項目リストに含まれている場合は、何もしない if (false === array_key_exists($name, $this->notEscapeNameList)) { $this->viewVars[$name] = $this->htmlEscape($value); } } } protected function htmlEscape($value) { if (true === is_null($value) || true === is_bool($value) || true === is_callable($value) || true === is_double($value) || true === is_float($value) || true === is_int($value)) { // エスケープ不要な型(のはず) return $value; } else if (true === is_iterable($value)) { // 配列以外に、ResultSetの場合もここに入るので、 // テンプレート側では、ResultSetでのデータ操作は行えない(けど問題ある?) $ret = []; foreach ($value as $key => $val) { $ret[$key] = $this->htmlEscape($val); } return $ret; } else if ($value instanceof Entity) { $array = $value->toArray(); foreach ($array as $key => $val) { $value->$key = $this->htmlEscape($val); } // Entityは一応、配列にしないで型は維持しておく return $value; } else if (true === is_resource($value)) { // Cakeの場合、MySQLのbinary・varbinary・blob型は、Entity内ではリソース型になる模様 // これは、どうにもならないか? return $value; } else if ($value instanceof \Cake\I18n\FrozenTime) { // そもそもエスケープしなくても良い気もするが // コメントアウトした以下と、どっちが良いか? //return $this->htmlEscape($value->format('Y-m-d H:i:s')); return new \Cake\I18n\FrozenTime($this->htmlEscape($value->format('Y-m-d H:i:s'))); } else if ($value instanceof \Cake\I18n\FrozenDate) { // そもそもエスケープしなくても良い気もするが // コメントアウトした以下と、どっちが良いか? //return $this->htmlEscape($value->format('Y-m-d')); return new \Cake\I18n\FrozenDate($this->htmlEscape($value->format('Y-m-d'))); } // オブジェクトは、汎用的過ぎて上手い方法が無い?のでコメントアウト /* else if (true === is_object($value)) { $obj = new \stdClass(); $properties = get_object_vars($value); //var_dump($properties); foreach ($properties as $n => $v) { $obj->$n = $this->htmlEscape($v); } return $obj; } */ else { return h($value); } } }