Halu_wimps
@Halu_wimps (シガラキ)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Laravel / @methodについて

解決したいこと

研修の練習として模擬Twitterの作成を行っているのですが、ツイート編集画面で編集とツイート削除の両方できるようにしたいのですが、
@method('DELETE')を付けてbutton設置すると編集ボタンを押してもツイートが削除されてしまいます。

削除ボタンを設置する前に編集ボタンの動作を確認しましたが問題なく編集が更新できる状態でした。@method('DELETE')を付けてbutton設置すると編集ボタンを押しても削除されてしまいます。

勉強中でネットを調べてもよくわからなかったため、ご教授・ご指摘をいただけたら幸いです。

Model

app\Models\Models\Tweet.php
<?php

namespace App\Models\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\softDeletes;
use App\Models\User;


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 getTimeLines(Int $user_id, Array $follow_ids)
   {
       // 自身とフォローしているユーザIDを結合する
       $follow_ids[] = $user_id;
       return $this->whereIn('user_id', $follow_ids)->orderBy('created_at', 'DESC')->paginate(50);
    }

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

   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();
    }

  }

Controllers

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

namespace App\Http\Controllers;

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

class TweetsController extends Controller
{
    public function index(Tweet $tweet, Follower $follower)
    {
        $user = auth()->user();
        $follow_ids = $follower->followingIds($user->id);
        // followed_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 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 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 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 redirect('tweets');
    }

}

routes 

routes\web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

Route::group(['middleware' => 'auth'], function() {

    // ユーザ関連
    Route::resource('users', 'App\Http\Controllers\UsersController', ['only' => ['index', 'show', 'edit', 'update']]);

    // フォロー/フォロー解除を追加
    Route::post('users/{id}/follow', 'App\Http\Controllers\UsersController@follow')->name('follow');
    Route::delete('users/{id}/unfollow', 'App\Http\Controllers\UsersController@unfollow')->name('unfollow');

    // ツイート関連
    Route::resource('tweets', 'App\Http\Controllers\TweetsController', ['only' => ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']]);

    // コメント関連
    Route::resource('comments', 'App\Http\Controllers\CommentsController', ['only' => ['store']]);

    // いいね関連
    Route::resource('favorites', 'App\Http\Controllers\FavoritesController', ['only' => ['store', 'destroy']]);

});

blade

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', ['tweet' => $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>

                                @method('DELETE')
                               <button type="submit" class="btn btn-primary dropdown-ite del-btn">ツイート削除</button>
                            </div>
                        </div>

                    </form>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

まだまだ勉強不足でネットで調べてもよくわからなく躓いてしまっている状態ですので、もしよろしければご教授・ご指摘をお願いいたします。

0

2Answer

送信はformの単位なのでformを分けるかjsでformのactionを変更して送信すれば解決しますよ。

0Like

Comments

  1. @Halu_wimps

    Questioner

    こめんとありがとうございます!!
    教えていただいたやり方の
    formを2つ用意する方法で進めようとしているのですが、
    「The POST method is not supported for this route. Supported methods: GET, HEAD, PUT, PATCH, DELETE.」
    というエラーが出てしまいます・・・

    どのような書き方が好ましいのでしょうか?

Comments

  1. @method('DELETE')
    これが無いのでは?
  2. @Halu_wimps

    Questioner

    ```resources\views\tweets\edit.blade.php
    <form method="POST" action="{{ route('tweets.update', ['tweet' => $tweets]) }}">

    @method('DELETE')
    <button type="submit" class="btn btn-primary dropdown-ite del-btn">ツイート削除</button>

    </form>
    ```
    試しにこれでやってみたところ、ボタンを押した後に
    419|PAGE EXPIRED
    というページが表示されてしまいます・・・
  3. formのaction間違えてるからじゃない?
    人に聞く前にログとかちゃんと確認した方が良いよ。

Your answer might help someone💌