はじめに
この記事では、片方がコメントを送信したら、もう片方の人はリロードしなくても、コメントが表示されるチャットアプリを作っていきたいと思います。
完成物
ソースコード:https://github.com/Alesion30/ChatApp
認証機能の実装
雛形の生成
$ laravel new ChatApp
マイグレーションの実行
$ cd ChatApp
$ php artisan migrate
laravel/uiのインストール
$ composer require laravel/ui
ログイン機能の実装
$ php artisan ui vue --auth
$ npm install
$ npm run dev
resources/views/welcome.blade.php
resources/views/auth/login.blade.php
resources/views/auth/register.blade.php
パスワードを8文字以上から4文字以上に変更する
app/Http/Controllers/Auth/RegisterController.phpの55行目の箇所を以下のように書き換える。
'password' => ['required', 'string', 'min:4', 'confirmed']
DBとの接続をする
phpMyAdminで、ChatAppというデータベースを作成する。
.envファイルのAPP_NAME
とDB_USERNAME
とDB_PASSWORD
にそれぞれ対応した値を記述する。
APP_NAME=ChatApp
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ChatApp
DB_USERNAME=(phpMyAdminのユーザー名)
DB_PASSWORD=(phpMyAdminのパスワード)
見た目を作る
home.blade.phpを編集する
ホーム画面に、コメントを表示するボードとコメントを入力する欄と送信ボタンをつける。
@extends('layouts.app')
@section('content')
<div class="chat-container row justify-content-center">
<div class="chat-area">
<div class="card">
<div class="card-header">Comment</div>
<div class="card-body chat-card">
</div>
</div>
</div>
</div>
<div class="comment-container row justify-content-center">
<div class="input-group comment-area">
<textarea class="form-control" placeholder="input massage" aria-label="With textarea"></textarea>
<button type="input-group-prepend button" class="btn btn-outline-primary comment-btn">Submit</button>
</div>
</div>
@endsection
cssでデザインを整える
public/cssフォルダに新しくview.cssを作る。
.chat-container {
width: 100%;
height: 100%;
}
.chat-card {
height: 67vh;
overflow: auto;
}
.chat-area {
width: 70%;
}
.comment-container {
position: fixed;
bottom: 20px;
text-align: center;
width: 100%;
}
.comment-area {
width: 70%;
}
.comment-btn {
margin: 0px 10px;
}
.comment-body {
padding: 5px 30px 20px 30px;
}
.comment-body:hover {
background-color: #dfdfdf;
}
.comment-body-user {
font-weight: bold;
font-size: 20px;
}
.comment-body-time {
font-size: 10px;
margin-top: 10px;
margin-left: 5px;
color: #a0a0a0;
}
/*# sourceMappingURL=view.css.map */
view側で、view.cssを読み込む。resources/views/layouts/app.blade.phpに下のコードを追加する。
<link href="{{ asset('css/view.css') }}" rel="stylesheet">
コメントを表示する部品を作る
resources/viewsフォルダに新しくcomponentsフォルダを作り、その中にcomment.blade.phpを作成する。
<div class="media">
<div class="media-body comment-body">
<div class="row">
<span class="comment-body-user">TestName</span>
<span class="comment-body-time">2020-01-06 12:16:45</span>
</div>
<span class="comment-body-content">
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio,
vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec
lacinia congue felis in faucibus.
</span>
</div>
</div>
home.blade.phpにコメントを表示する部品を埋め込む
@extends('layouts.app')
@section('content')
<div class="chat-container row justify-content-center">
<div class="chat-area">
<div class="card">
<div class="card-header">Comment</div>
<div class="card-body chat-card">
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
@include('components.comment')
</div>
</div>
</div>
</div>
<div class="comment-container row justify-content-center">
<div class="input-group comment-area">
<textarea class="form-control" placeholder="input massage" aria-label="With textarea"></textarea>
<button type="input-group-prepend button" class="btn btn-outline-primary comment-btn">Submit</button>
</div>
</div>
@endsection
コメントを保存するテーブルを作る
マイグレーションの作成
$ php artisan make:migration create_comments_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCommentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('login_id');
$table->string('name');
$table->string('comment');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
}
モデルの作成
$ php artisan make:model Comment
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $fillable = [
'login_id', 'name', 'comment'
];
protected $guarded = [
'create_at', 'update_at'
];
}
データベースからデータを取得して、画面に反映させる
HomeController.phpを開いて、use App\Comment;
を追加し、index関数を以下のように書き換える。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Comment;
use Illuminate\Support\Facades\Auth;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$comments = Comment::get();
return view('home', ['comments' => $comments]);
}
}
foreachで、コメントを表示させる。comment.blade.phpにも、データを渡す。
<div class="card-body chat-card">
@foreach ($comments as $item)
@include('components.comment', ['item' => $item])
@endforeach
</div>
<div class="media">
<div class="media-body comment-body">
<div class="row">
<span class="comment-body-user">{{$item->name}}</span>
<span class="comment-body-time">{{$item->created_at}}</span>
</div>
<span class="comment-body-content">{!! nl2br(e($item->comment)) !!}</span>
</div>
</div>
コメントは複数行表示出来るように、e()でエスケープ→nl2brで改行をbrタグに変換→タグがエスケープされないように{!! !!}で囲んでいる。
コメントを送信できるようにする
コメントをデータベースに保存する関数を作る
HomeController.phpでadd関数を作る。
public function add(Request $request)
{
$user = Auth::user();
$comment = $request->input('comment');
Comment::create([
'login_id' => $user->id,
'name' => $user->name,
'comment' => $comment
]);
return redirect()->route('home');
}
add関数をweb.phpに登録する
Route::post('/add', 'HomeController@add')->name('add');
フォームを作る
home.blade.phpのコメントを送信する部分を、以下のように書き換える。
<form method="POST" action="{{route('add')}}">
@csrf
<div class="comment-container row justify-content-center">
<div class="input-group comment-area">
<textarea class="form-control" id="comment" name="comment" placeholder="input massage"
aria-label="With textarea"></textarea>
<button type="submit" class="btn btn-outline-primary comment-btn">Submit</button>
</div>
</div>
</form>
Shift+Enterでコメントを送信できるようにする。
home.blade.phpのコメントを送信する部分を、以下のように書き換える。
<form method="POST" action="{{route('add')}}">
@csrf
<div class="comment-container row justify-content-center">
<div class="input-group comment-area">
<textarea class="form-control" id="comment" name="comment" placeholder="push massage (shift + Enter)"
aria-label="With textarea"
onkeydown="if(event.shiftKey&&event.keyCode==13){document.getElementById('submit').click();return false};"></textarea>
<button type="submit" id="submit" class="btn btn-outline-primary comment-btn">Submit</button>
</div>
</div>
</form>
今回はここまで。次回は、本題である非同期通信を用いて、リアルタイムでチャットができるようにしたいと思います。