LoginSignup
7
4

More than 3 years have passed since last update.

【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第5回ツイートのCRUD機能 編集と削除)

Last updated at Posted at 2019-10-02

Laravelで始めるTwitter風(Twitterクローン)のSNSツール開発チュートリアル

概要

スクールとかの課題だったりLaravelを初めてみたいけど何を作ろうって迷ってる人向けによくあるTwitter風のWEBサイトを作ってみます。

前回

第4回ツイートのCRUD機能の続きを追加していきます。
今回はツイートの編集(Update)と削除(Delete)をやっていきます。

前提

  • PHPをある程度理解している
  • Laravelが使える環境がある
  • MVC構造をある程度理解している

環境

  • Mac
  • Homestead
  • Laravel 5.8

リダイレクト先

ついでに現在ログインすると/homeに飛ぶようになっているのでこちらも/tweetsにリダイレクトするように設定しましょう(忘れてた)

  • 対象のファイル名
    • LoginController.php
    • RegisterController.php
    • ResetPasswordController.php
    • VerificationController.php
    • RedirectIfAuthenticated.php

上記のファイルから/homeの部分を全て/tweetsに変更してください。

そうするとログイン後も/tweetsにリダイレクトするようになります!

Update(ツイート編集機能)

ではツイート内容の編集機能を実装していきましょう。

Update(ツイート編集画面)

では次はCRUDのUpdateをやっていきましょう!
まずはツイート投稿と同じく編集画面から作っていきます。

Model

$user_id$tweet_idに値に一致するツイートを取得します。

app/Models/Tweet.php
    public function getEditTweet(Int $user_id, Int $tweet_id)
    {
        return $this->where('user_id', $user_id)->where('id', $tweet_id)->first();
    }

Controller

編集するツイートを先ほどのgetEditTweet$tweet_idを渡してその結果をViewに渡す処理をします。

app/Http/Controllers/TweetsController.php
    public function edit(Tweet $tweet)
    {
        $user = auth()->user();
        $tweets = $tweet->getEditTweet($user->id, $tweet->id);

        if (!isset($tweets)) {
            return redirect('tweets');
        }

        return view('tweets.edit', [
            'user'   => $user,
            'tweets' => $tweets
        ]);
    }

View

resources/views/tweets/edit.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Update</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('tweets.update', ['tweets' => $tweets]) }}">
                        @csrf
                        @method('PUT')

                        <div class="form-group row mb-0">
                            <div class="col-md-12 p-3 w-100 d-flex">
                                <img src="{{ asset('storage/profile_image/' .$user->profile_image) }}" class="rounded-circle" width="50" height="50">
                                <div class="ml-2 d-flex flex-column">
                                    <p class="mb-0">{{ $user->name }}</p>
                                    <a href="{{ url('users/' .$user->id) }}" class="text-secondary">{{ $user->screen_name }}</a>
                                </div>
                            </div>
                            <div class="col-md-12">
                                <textarea class="form-control @error('text') is-invalid @enderror" name="text" required autocomplete="text" rows="4">{{ old('text') ? : $tweets->text }}</textarea>

                                @error('text')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-12 text-right">
                                <p class="mb-4 text-danger">140文字以内</p>
                                <button type="submit" class="btn btn-primary">
                                    ツイートする
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

ツイート編集画面

ツイート一覧ページから自身のツイートのみ表示されるボタン「・・・←これを縦にしたアイコン 笑」を押すと編集ボタンが表示されるのでそれを押すとこのページに行けます!

スクリーンショット 2019-09-19 2.05.48.png

Update(ツイート編集機能)

では先ほどの編集画面から実際に編集した内容で更新する処理を書いていきましょう!

Model

この辺はただ上書きしているだけなので、特に触れません。

もしわからない人がいれば第3回のUser情報を更新するときと流れは一緒なのでもう一度見てみてください。

app/Models/Tweet.php
    public function tweetUpdate(Int $tweet_id, Array $data)
    {
        $this->id = $tweet_id;
        $this->text = $data['text'];
        $this->update();

        return;
    }

Controller

こちらも先ほど作成したstoreとほとんど同じなので説明は省きます。

app/Http/Controllers/TweetsController.php
    public function update(Request $request, Tweet $tweet)
    {
        $data = $request->all();
        $validator = Validator::make($data, [
            'text' => ['required', 'string', 'max:140']
        ]);

        $validator->validate();
        $tweet->tweetUpdate($tweet->id, $data);

        return redirect('tweets');
    }

これで編集ができるようになっていると思います!

Delete(ツイート削除)

次はツイートの削除を行ってみようと思います👨‍🚀

Delete(ツイート削除機能)

Model

$user_id$tweet_idに一致したツイートを削除します。

app/Models/Tweet.php
    public function tweetDestroy(Int $user_id, Int $tweet_id)
    {
        return $this->where('user_id', $user_id)->where('id', $tweet_id)->delete();
    }

Controller

$user_id$tweet_idを先ほど作成したtweetDestroy()メソッドに渡しています。

app/Http/Controllers/TweetsController.php
    public function destroy(Tweet $tweet)
    {
        $user = auth()->user();
        $tweet->tweetDestroy($user->id, $tweet->id);

        return back();
    }

これで削除機能を実装できましたので、先ほどの編集画面に遷移する方法と同様に削除するボタンがあるので試してみてください。

振り返り(ModelとControllerファイルの全体)

今回第4,5回とModelとControllerの行き来が多かったのでとりあえず全体も載せておきます!
ここまで問題なく動いたよって人はスルーしてください。

Model

app/Models/Tweet.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\softDeletes;

class Tweet extends Model
{
    use SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'text'
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function favorites()
    {
        return $this->hasMany(Favorite::class);
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    public function getUserTimeLine(Int $user_id)
    {
        return $this->where('user_id', $user_id)->orderBy('created_at', 'DESC')->paginate(50);
    }

    public function getTweetCount(Int $user_id)
    {
        return $this->where('user_id', $user_id)->count();
    }

    // 詳細画面
    public function getTweet(Int $tweet_id)
    {
        return $this->with('user')->where('id', $tweet_id)->first();
    }

    // 一覧画面
    public function getTimeLines(Int $user_id, Array $follow_ids)
    {
        $follow_ids[] = $user_id;
        return $this->whereIn('user_id', $follow_ids)->orderBy('created_at', 'DESC')->paginate(50);
    }

    public function tweetStore(Int $user_id, Array $data)
    {
        $this->user_id = $user_id;
        $this->text = $data['text'];
        $this->save();

        return;
    }

    public function getEditTweet(Int $user_id, Int $tweet_id)
    {
        return $this->where('user_id', $user_id)->where('id', $tweet_id)->first();
    }

    public function tweetUpdate(Int $tweet_id, Array $data)
    {
        $this->id = $tweet_id;
        $this->text = $data['text'];
        $this->update();

        return;
    }

    public function tweetDestroy(Int $user_id, Int $tweet_id)
    {
        return $this->where('user_id', $user_id)->where('id', $tweet_id)->delete();
    }
}

Controller

app/Http/Controllers/TweetsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\Tweet;
use App\Models\Comment;
use App\Models\Follower;

class TweetsController extends Controller
{
    public function index(Tweet $tweet, Follower $follower)
    {
        $user = auth()->user();
        $follow_ids = $follower->followingIds($user->id);
        $following_ids = $follow_ids->pluck('followed_id')->toArray();

        $timelines = $tweet->getTimelines($user->id, $following_ids);

        return view('tweets.index', [
            'user'      => $user,
            'timelines' => $timelines
        ]);
    }

    public function create()
    {
        $user = auth()->user();

        return view('tweets.create', [
            'user' => $user
        ]);
    }

    public function store(Request $request, Tweet $tweet)
    {
        $user = auth()->user();
        $data = $request->all();

        $validator = Validator::make($data, [
            'text' => ['required', 'string', 'max:140']
        ]);
        $validator->validate();

        $tweet->tweetStore($user->id, $data);

        return redirect('tweets');
    }

    public function show(Tweet $tweet, Comment $comment)
    {
        $user = auth()->user();
        $tweet = $tweet->getTweet($tweet->id);
        $comments = $comment->getComments($tweet->id);

        return view('tweets.show', [
            'user'     => $user,
            'tweet'    => $tweet,
            'comments' => $comments
        ]);
    }

    public function edit(Tweet $tweet)
    {
        $user = auth()->user();
        $tweets = $tweet->getEditTweet($user->id, $tweet->id);

        if (!isset($tweets)) {
            return redirect('tweets');
        }

        return view('tweets.edit', [
            'user'   => $user,
            'tweets' => $tweets
        ]);
    }

    public function update(Request $request, Tweet $tweet)
    {
        $data = $request->all();
        $validator = Validator::make($data, [
            'text' => ['required', 'string', 'max:140']
        ]);

        $validator->validate();
        $tweet->tweetUpdate($tweet->id, $data);

        return redirect('tweets');
    }

    public function destroy(Tweet $tweet)
    {
        $user = auth()->user();
        $tweet->tweetDestroy($user->id, $tweet->id);

        return back();
    }
}

以上です。

次回 -> 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第6回コメントといいね機能)

7
4
1

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
7
4