60
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelで非同期チャットアプリを作ろう(1)

Last updated at Posted at 2020-01-17

はじめに

この記事では、片方がコメントを送信したら、もう片方の人はリロードしなくても、コメントが表示されるチャットアプリを作っていきたいと思います。

Laravelで非同期チャットアプリを作ろう(2)

完成物

chat2.gif

ソースコード: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
スクリーンショット 2020-01-06 10.00.49.png
resources/views/auth/login.blade.php
スクリーンショット 2020-01-06 10.01.31.png
resources/views/auth/register.blade.php
スクリーンショット 2020-01-06 10.01.43.png

パスワードを8文字以上から4文字以上に変更する

app/Http/Controllers/Auth/RegisterController.phpの55行目の箇所を以下のように書き換える。

app/Http/Controllers/Auth/RegisterController.php
'password' => ['required', 'string', 'min:4', 'confirmed']

DBとの接続をする

phpMyAdminで、ChatAppというデータベースを作成する。

.envファイルのAPP_NAMEDB_USERNAMEDB_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のパスワード)

見た目を作る

スクリーンショット 2020-01-06 12.34.14.png

home.blade.phpを編集する

ホーム画面に、コメントを表示するボードとコメントを入力する欄と送信ボタンをつける。

resources/views/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を作る。

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に下のコードを追加する。

resources/views/layouts/app.blade.php
<link href="{{ asset('css/view.css') }}" rel="stylesheet">

コメントを表示する部品を作る

スクリーンショット 2020-01-06 12.45.12.png

resources/viewsフォルダに新しくcomponentsフォルダを作り、その中にcomment.blade.phpを作成する。

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にコメントを表示する部品を埋め込む

resources/views/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
database/migrations/2020_01_05_064658_create_comments_table.php
<?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
app/Comment.php
<?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関数を以下のように書き換える。

app/Http/Controllers/HomeController.php
<?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にも、データを渡す。

resources/views/home.blade.php
<div class="card-body chat-card">
    @foreach ($comments as $item)
    @include('components.comment', ['item' => $item])
    @endforeach
</div>
resources/views/components/comment.blade.php
<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関数を作る。

app/Http/Controllers/HomeController.php
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に登録する

routes/web.php
Route::post('/add', 'HomeController@add')->name('add');

フォームを作る

home.blade.phpのコメントを送信する部分を、以下のように書き換える。

resources/views/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のコメントを送信する部分を、以下のように書き換える。

resources/views/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>

今回はここまで。次回は、本題である非同期通信を用いて、リアルタイムでチャットができるようにしたいと思います。

60
60
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
60
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?