背景
laravel-adminでhtmlページを入稿する機能を作ることってよくある(?)と思うのですが、
標準で利用できるeditorのCKEditorだと、htmlタグがエスケープされてしまう。
その結果思った通りの入稿ができない
その対策について
環境
- laravel 5.5
- php 7.1
- laravel-admin 1.5.14
どういうことか?
フレームワークにのっとってformを作成する際に
$form->editor
って記述しておくと、laravel-adminが用意してくれているeditor(CKEditor)がformとして以下のように表示されるのですが、
これにhtmlタグ入力すると自動でエスケープされます。
<strong>トピックス</strong>
って入力してpostすると
<strong>トピックス</strong>
ってデータがエスケープされてまう・・・。
対処方法
標準だとform描画の際には以下のクラスのrenderが呼ばれるのですが、
<?php
namespace Encore\Admin\Form\Field;
use Encore\Admin\Form\Field;
class Editor extends Field
{
protected static $js = [
'//cdn.ckeditor.com/4.5.10/standard/ckeditor.js',
];
public function render()
{
$this->script = "CKEDITOR.replace('{$this->column}');";
return parent::render();
}
}
な感じでレンダリングの際にCKEDITORに差し替えているのですが、
このCKeditorでは当然様々なconfigを設定することが可能でして
CKEDITOR.replace('{$this->column}', {
allowedContent: true, // クラスの記述を許容するか
basicEntities: false, // 自動エスケープオフ
entities : false // 自動エスケープオフ(これも)
});
な感じでreplaceの際に第二引数にconfigを渡すことができます。
(ざっくりした説明なので詳しいオプションの意味は公式で確認して見てください)
namespace App\Admin\Extensions\Widgets;
use Encore\Admin\Form\Field;
class HtmlEditor extends Field
{
/**
* @var string
*/
protected $view = 'admin::form.editor';
/**
* @var array
*/
protected static $js = [
'//cdn.ckeditor.com/4.5.10/standard/ckeditor.js',
];
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function render()
{
$this->script = "
CKEDITOR.replace('{$this->column}', {
allowedContent: true,
basicEntities: false,
entities : false
});
";
return parent::render();
}
}
で、app/Admin/bootstrap.php
から、上で作成したクラスを使うように指示する
use App\Admin\Extensions\Widgets\HtmlEditor;
// form->editorの対応クラスを上書き
Encore\Admin\Form::extend('editor', HtmlEditor::class);
これでformからの入力がエスケープされずにパスされるようになったぞ。
(逆いうとエスケープされないので気をつけてね)
補足
なんでプロパティのviewを設定しているの?
設定しないとフレームワークさんがおそらくクラス名からhtmleditor
というviewを探そうとして死ぬからです。
今回は既存のeditorをそのまま使うので意図的に明言しておきます。
継承しません
Editorを継承した方が綺麗だったんですが、そうするとrender()で設定したconfigが上書きされてしまいます。
で、vendorのファイルには手を入れたくないので継承はやりません。