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

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

## 概要

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

### 前回

- 第1回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第1回DB設計とMigration）](https://qiita.com/namizatop/items/d79017aa474966244073)
- 第2回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第2回Seeder->ログイン/新規登録）](https://qiita.com/namizatop/items/3c20c0d0565906cc6a1a)
- 第3回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第3回ユーザ関連とフォロー機能）](https://qiita.com/namizatop/items/0c81b0a94a1084cda6de)
- 第4回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第4回ツイートのCRUD機能）](https://qiita.com/namizatop/items/c9ed67f98fc3e5ce67c7)
- 第5回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第5回ツイートのCRUD機能 編集と削除）](https://qiita.com/namizatop/items/2273bd0dcc817785b131)
- 第6回 [【全6回】Laravel5.8でTwitterっぽいSNSツールを作る（第6回コメントといいね機能）](https://qiita.com/namizatop/items/0f3f8783c93f3dfa277d)

第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`に値に一致するツイートを取得します。

```php: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に渡す処理をします。

```php: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

```php: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
```

### ツイート編集画面

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

<img width="1440" alt="スクリーンショット 2019-09-19 2.05.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293438/4b014745-e6ca-34be-21e6-9b0e792d4ea6.png">

### Update(ツイート編集機能)

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

#### Model

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

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

```php: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`とほとんど同じなので説明は省きます。

```php: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`に一致したツイートを削除します。

```php: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()`メソッドに渡しています。

```php: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

```php: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

```php: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回コメントといいね機能）](https://qiita.com/namizatop/items/0f3f8783c93f3dfa277d)