time 2017/10/17
『Sanitize::clean』でサニタイズを行うと、改行コードもエスケープされます。
このままでは、『textarea』要素に入力された改行がない状態になり、想像していた表示にならないことがあります。
下記の赤文字の部分がサニタイズ時にエスケープされた改行コードです。
▼サニタイズされた『textarea』要素のテキスト
登録時に『Sanitize::clean』を使用しサニタイズを行いました。\n\nこのテキストは確認用です。
このままでは『nl2br』関数も使用できないので、コンポーネント作成の練習も兼ねて、『\\\n』を『\n』に戻す簡単なコンポーネントを作りたいと思います。
(※表示では『\n』ですが、実際はエスケープシーケンスがあるので『\\\n』の状態になっています。)
コンポーネントは、『Object』クラスを継承し作成します。
▼『Object』クラスを継承
class HtmlDecodeComponent extends Object {
public $name = 'HtmlDecode';
}
これをCakePHPの規約どおりに、『html_decode.php』として『/app/controllers/components』ディレクトリに配置します。
これでコンポーネントの準備ができました。
次は、メソッドを追加していきます。
改行コードを元に戻すメソッドだけでは寂しいので、HTMLエンティティを特殊文字に置き換えるメソッドも書いてみました。
▼作成したコンポーネントにメソッドを追加
class HtmlDecodeCompnent extends Object {
public $name = 'HtmlDecode';
// 置き換え対象のHTMLエンティティ
protected $_patterns = array(
'before' => array(
"/¥&/", // 『&』
"/¥</", // 『<』
"/¥>/", // 『>』
"/¥"/", // 『"』
"/¥'/", // 『'』
),
'after' => array(
"&", // 『&』
"<", // 『<』
">", // 『>』
"'", // 『"』
'"', // 『'』
)
);
/**
* HTMLエンティティを特殊文字に置き換える
*
* @param string or array $data HTMLエンティティを特殊文字に置き換えたい配列、または文字列
* @param pool $script 置き換え後の特殊文字がScriptタグになった場合、削除するなら『true』を指定
* @param pool $space 置き換え後の文字列からスペースを削除するなら『true』を指定
*
* @return string or array $data 処理後、引数に指定された形式で返す。
*/
public function htmlCheck($data, $script = true, $image = true, $space = true) {
if(is_array($data)) {
$cnvData = array();
// 配列の処理
foreach($data as $key => $item) {
if(isset($item)) {
// 特殊文字へ置き換え
$cnvData[$key] = $this->_htmlDecode($item);
// スクリプトタグの削除
if($script) $cnvData[$key] = Sanitize::stripScripts($cnvData[$key]);
// 画像の削除
if($image) $cnvData[$key] = Sanitize::stripImages($cnvData[$key]);
// スペースの削除
if($space) $cnvData[$key] = Sanitize::stripWhitespace($cnvData[$key]);
}
}
} else {
if(isset($data)) {
// 特殊文字へ置き換え
$cnvData = $this->_htmlDecode($data);
// スクリプトタグの削除
if($script) $cnvData = Sanitize::stripScripts($cnvData);
// 画像の削除
if($image) $cnvData = Sanitize::stripImages($cnvData);
// スペースの削除
if($space) $cnvData = Sanitize::stripWhitespace($cnvData);
}
}
return $cnvData;
}
/**
* 配列、または文字列に含まれる『///n』を『/n』に置き換える
*
* @param string or array $data 『///n』を『/n』に置き換えたい配列、または文字列
* @param pool $conversion 置き換え後の『/n』を『
』タグに変更する場合、trueを指定
*
* @return string or array $data 処理後、引数に指定された形式で返す。
*
*/
public function nlCheck($data, $conversion = false) {
if(is_array($data)) {
$cnvData = array();
foreach($data as $key => $item) {
if(isset($item)) {
// 『/n』へ置き換え
$cnvData[$key] = $this->_nlDecode($item);
// 『
』へ置き換え
if($conversion) $cnvData[$key] = nl2br($cnvData[$key]);
}
}
} else {
if(isset($data)) {
// 『/n』へ置き換え
$cnvData = $this->_nlDecode($data);
// 『
』へ置き換え
if($conversion) $cnvData = nl2br($cnvData);
}
}
return $cnvData;
}
/**
* HTMLエンティティを特殊文字に置き換える
*
* @param string $data 置き換えたい文字列
*
* @return string 置き換え後の文字列
*/
protected function _htmlDecode($data) {
return preg_replace($this->_patterns['before'], $this->_patterns['after'], $data);
}
/**
* 『///n』を『/n』に置き換える
*
* @param string $data 置き換えたい文字列
*
* @return string 置き換え後の文字列
*/
protected function _nlDecode($data) {
return preg_replace('/\\\n/', "\n", $data);
}
}
『preg_replace』関数を使用し、正規表現で文字を置き換えていくだけのメソッドたちです。
あとは、コントローラーからコンポーネントを呼び出せば、他のコンポーネント同様に使用することができます。
▼コントローラー
class PostsController extends AppController {
public $name = 'Posts';
public $users = array('Post');
public $components = array('HtmlDecode');
public function index() {
/*
処理は省略します・・・
*/
$text = $this->HtmlDecode->nlCheck('登録時に『Sanitize::clean』を使用しサニタイズを行いました。\n\nこのテキストは確認用です。', true);
$this->set('text', $text);
}
}
▼ビュー
<?php echo $text; ?>
▼結果
登録時に『Sanitize::clean』を使用しサニタイズを行いました。 <br /> <br /> <br /> このテキストは確認用です。
コンポーネントを作成するのもとっても簡単ですね。
さすがCakePHPって感じです。
ちなみに、今回はコンポーネントとして作成しましたが、モデルの段階で処理したほうがいいのか(ビヘイビア)迷いました。
ビューで処理するのは、『コントローラーから渡されたデータをビュー側でループや条件分岐以外の処理をして表示する』のは間違っていると思うので止めましたが・・・
もっとMVCの理解を深めないといけないですね^^;
※記事を投稿後、『CakePHPを使ったMVC設計のベストプラクティス』を見て、モデルの段階で処理したほうがいい気がしてきました。
今回作成したコンポーネントと同じ処理を行うビヘイビアを作成しようと思います。
コメント
1. CakePHP 簡単なビヘイビアを作ってみる | Yasigani-ni Blog 2011 / 10 / 5 16:38
[…] 投稿ナビゲーション ← 前へ […]
2. cakephp初心者 2012 / 3 / 30 15:12
困っていたので大変助かりました。ありがとうございます~!
細かいですが、1行目に誤字があるようです。↓
class HtmlDecodeCompnent extends Object
× Compnent
○ Component
3. yasigani-ni 2012 / 3 / 30 16:11
ご指摘ありがとうございます^^
さっそく修正します><