Laravelに搭載できるリッチテキストエディタ(WYSISYGエディタ)はいくつか種類があります。
今回はそのなかで、無料で使えるsummernote(サマーノート)を紹介します。
サンプルページはこちらをご覧ください。(保存機能はつけていません)。
今回の記事ではsummernoteのフォームを通じて投稿されたデータを、MySQLデータベースに保存する方法まで解説しますね。
すべて手順を説明したところ、長ーい記事になっちゃいました。
気長にお付き合いください。
Summernoteでフォームを作る
まずはLaravelのプロジェクトの準備をしましょう。
次のような流れで進めていきます。
- Laravelの環境構築
- モデルとデータベースの作成
- ルートの作成
- コントローラーの作成
- ビューファイルの作成
すでに搭載可能な場合には、この部分は飛ばしてください。
1.Laravelの環境構築
Laravelのインストールを行います。
こちらのページを参考にしてください。
2.モデルとマイグレーションファイルでテーブルを作成
モデルファイルとデータベースを作ります。
下記のコマンドを入力してください。今回はArticleという名前のモデルを作成します。
1 |
php artisan make:model Article -m |
モデルの編集
appフォルダの直下(Laravel8では app/Modelフォルダの中)にモデルファイル Article.phpができています。
下記のようにコードを書き加えます。
1 |
protected $guarded =[]; |
protected $quarded =[] は、フォームに入れた値でデータベースを更新できるようにするためのコードです。
編集後は、下記のようになります。
マイグレートを実行してテーブルを作成
次にdatabase/migrationファイルを開き、下記のように入力します。
1 2 3 4 |
$table->id(); $table->string('title'); $table->longText('body'); $table->timestamps(); |
マイグレートを実行します。
1 |
>php artisan migrate |
PHPMyAdminにログインして、articlesテーブルが作成されているか確認してみてください。
3.ルートの作成
routes/web.phpファイルを開きます。
こちらは、ルートファイルを指定するファイルになります。
次のふたつのルートを指定しておきましょう。
1 2 |
Route::post('/posts/store', 'ArticleController@store')->name('posts.store'); Route::get('/posts/create', 'ArticleController@create')->name('posts.create'); |
4.コントローラーの作成
ルートから処理を受け渡されるコントローラーを作ります。
まずは次のコマンドでコントローラーファイルを作成しましょう。
1 |
php artisan make:controller ArticleController |
app/Http/Controllers/ArticleControllerファイルを開きます。
ファイルの上に、下記を入れます。
1 |
use App\Article; |
class名以下に、次のように、showとstoreのコントローラーを作成しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public function create(){ return view('posts.create'); } public function store(Request $request){ $article=new Article(); $article->fill([ 'title'=>request('title'), 'body'=>request('body') ]); $article->save(); } |
全体のコードは次のようになります。
5.ビューファイルの作成
次にビューファイルを作成します。
resource/viewフォルダの中にpostsフォルダを作り、この中にcreate.blade.phpファイルを作成します。
ファイルの中に、次のようなフォームをいれておきます。
textareの【id】に【summernote】と指定するようにしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<html lang="ja"> <head> <meta charset="UTF-8"> <title>Summernote with Bootstrap 4</title> <script src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script> @if(session('created')) <div class="alert alert-success">{{session('created')}}</div> @endif <div class="container"> <div class="row"> <div class="col-md-7 offset-3 mt-4"> <div class="card-body"> <form method="post" action="{{route('posts.store')}}" enctype="multipart/form-data"> @csrf <div class="form-group"> <label for="title">件名</label> <input type="text" name="title" class="form-control" id="title" placeholder="Enter Title"> </div> <div class="form-group"> <label for ="body">投稿本文</label> <textarea class="form-control" name="body" id="summernote" cols="30" rows="10"></textarea> </div> <button type=”submit” class="btn btn-danger btn-block">保存</button> </form> </div> </div> </div> </div> <script> $('#summernote').summernote({ placeholder: 'Hello Bootstrap 4', tabsize: 2, height: 100 }); </script> </body> </html> |
ご留意事項
なお、下記のようにテンプレートファイルを組み込んでいる場合は、まずは、上記のようにテンプレートを外した形で試してみてください。
1 2 3 4 |
@extends('layouts.app') @section('content') コンテンツの中身 @endsection |
テンプレートファイル内で読み込んでいるjavaScriptとバッティングしたりして、うまく動作しない場合があるためです。
まずはテンプレートなしで動かしてみて、うまくいったら、テンプレートも組み込んでみてくださいね。
*上記は、下記の公式マニュアルを参考に、Bootstrap4を使う方法を紹介しています。
6.フォームをテストしてみる
それでは、Laravelのページを確認してみましょう。
【ドメイン名/posts/create】を開きます。
下記のように表示されていれば、成功です。
実際に投稿をしてみます。
画像を挿入したり書式を付けたりできます。
7.投稿後にデータベースを確認する
投稿後、phpMyAdminにログインして、きちんと保存されているかチェックしてみましょう。
こんなふうにHTMLのタグ入りで保存されていれば成功です。
summernoteの投稿内容を表示させる
それでは次に、データベースに投稿した内容を表示させるファイルも作ってみます。
1.ルートの作成
routex/webファイルに下記を追加します。
1 |
Route::get('/posts/view', 'ArticleController@show')->name('posts.show'); |
2.コントローラーの作成
ArticleContollerファイルに下記のshowメソッドを追加します。
1 2 3 4 |
public function show(){ $articles=Article::all(); return view('posts.view', compact('articles')); } |
3.表示用ファイルを作る
保存したデータを表示させるファイルを作ります。
resources/view/postsの中にview.blade.phpファイルを作ります。
下記のコードを入力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@foreach($articles as $article) <!-- Title --> <h1 class="mt-4">{{$article->title}}</h1> <hr> <!-- Date/Time --> <p>{{$article->created_at}}</p> <hr> <!-- Preview Image --> <img class="img-fluid rounded" src="{{$article->post_image}}" alt=""> <hr> <!-- Post Content --> <p>{!!$article->body!!}</p> @endforeach |
上記のコードでは、【body】部分は {!!$article->body!!} としています。
これは、エスケープ処理をしないために行っています。
通常は、エスケープ処理のはめに {{}}で値を囲みますが、こうしてしまうと、HTMLのコードが無効になってしまいます。
そこで今回は、エスケープ処理無効の設定にしています。
4.URLをチェックする
それでは、Laravelのページを確認してみましょう。
【ドメイン名/posts/view】を開きます。
下記のように表示されていれば、成功です。
Summernoteのメリットとデメリット
最後に、summernoteのメリット・デメリットをまとめておきます。
【summernoteのメリット】
・インストールせずとも手軽に使える
【summernoteのデメリット】
コードで保存すると使いにくい上、データ量がすごいことになってしまいます。
本格的に画像を使うなら、GitHubなどにファイルマネージャーがあるので、これらを組み合わせて使う手があります。
コードが組める方なら、自分でも作れるかと思います。
わたしはがんばって、自分でsummernoteに画像保存機能を追加しましたが、正直、結構メンドウ。
方法は、また別の記事にしていきますね。
summernote以外のリッチテキストエディタについては、こちらの記事をどうぞ。
★2021/05/17 追加しました:
【ご留意事項】を追加しました。テンプレートを読み込んでエラーになった場合は、テンプレートなしで試してみてください。