Help us understand the problem. What is going on with this article?

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

はじめに

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

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">{{$item->comment}}</span>
    </div>
</div>

コメントを送信できるようにする

コメントをデータベースに保存する関数を作る

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>

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした