Laravelで始めるTwitter風(Twitterクローン)のSNSツール開発チュートリアル
概要
スクールとかの課題だったりLaravelを初めてみたいけど何を作ろうって迷ってる人向けによくあるTwitter風のWEBサイトを作ってみます。
前回
- 第1回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第1回DB設計とMigration)
- 第2回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第2回Seeder->ログイン/新規登録)
- 第3回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第3回ユーザ関連とフォロー機能)
- 第4回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第4回ツイートのCRUD機能)
- 第5回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第5回ツイートのCRUD機能 編集と削除)
- 第6回 【全6回】Laravel5.8でTwitterっぽいSNSツールを作る(第6回コメントといいね機能)
第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
に値に一致するツイートを取得します。
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に渡す処理をします。
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
@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
ツイート編集画面
ツイート一覧ページから自身のツイートのみ表示されるボタン「・・・←これを縦にしたアイコン 笑」
を押すと編集ボタンが表示されるのでそれを押すとこのページに行けます!
Update(ツイート編集機能)
では先ほどの編集画面から実際に編集した内容で更新する処理を書いていきましょう!
Model
この辺はただ上書きしているだけなので、特に触れません。
もしわからない人がいれば第3回のUser情報を更新するときと流れは一緒なのでもう一度見てみてください。
public function tweetUpdate(Int $tweet_id, Array $data)
{
$this->id = $tweet_id;
$this->text = $data['text'];
$this->update();
return;
}
Controller
こちらも先ほど作成したstore
とほとんど同じなので説明は省きます。
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
に一致したツイートを削除します。
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()
メソッドに渡しています。
public function destroy(Tweet $tweet)
{
$user = auth()->user();
$tweet->tweetDestroy($user->id, $tweet->id);
return back();
}
これで削除機能を実装できましたので、先ほどの編集画面に遷移する方法と同様に削除するボタンがあるので試してみてください。
振り返り(ModelとControllerファイルの全体)
今回第4,5回とModelとControllerの行き来が多かったのでとりあえず全体も載せておきます!
ここまで問題なく動いたよって人はスルーしてください。
Model
<?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
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();
}
}
以上です。