トップページ
Laravel学習サイトLaravelやるばい

目次

つぶやきの表示・編集・削除

今回はつぶやきの表示・編集・削除ができるようにします。

以前つぶやきアプリを作成した時とかぶるコードが結構あるのでサクサク進めます。

コードの意味が分からなくなったら以前作ったつぶやきアプリを作り直して復習をした方がいいです。

毎回ルーティング→コントローラー→ビューの順にコードを考えます。


つぶやきを一覧ページに表示する

web.phpのコードを下記にします。

Route::middleware('auth', 'verified')->group(function () {
    Route::controller(TweetController::class)->group(function() {
        Route::get('/tweet/create', 'create')->name('tweet.create');

        Route::post('/tweet/store', 'store')->name('tweet.store');

        Route::get('/tweet/index', 'index')->name('tweet.index');     //この行を追加
    });
});

TweetControllerにindexアクションの記述をします。

下記の記述をして下さい。

class TweetController extends Controller
{
    public function create()
    {
        return view('tweet.create');
    }

    public function store(Request $request)
    {
        $tweets = new Tweet();
        $tweets->body = $request->body;
        $tweets->save();
        return back()->with('message', 'つぶやきを作成しました');
    }
    

    //ここから追加
    public function index()
    {
        $tweets = Tweet::all();

        return view('tweet.index', compact('tweets'));
    }
    //ここまで追加


}

「Tweet::all()」でtweetsテーブルの情報を取得して「compact('tweets')」で変数$tweetsとしてビューに情報を渡します。

ビュー(index.blade.php)のコードを下記にします。

<div class="wrap">
    <h2>つぶやき一覧</h2>
    @foreach ($tweets as $tweet)
        <div class="tweet">
            <p>{{ $tweet->body }}</p>
        </div>
    @endforeach
</div>

<style>
    .wrap{
        width: 80%;
        margin-left:auto;
        margin-right:auto;
        padding-top: 50px;
    }
    .tweet{
        margin-bottom: 40px;
    }
    p{
        background-color:#f2eeed;
        padding: 5px;
    }
</style>

{{ $tweet->body }}」の「body」はカラム名です。

「http://localhost:8888/tweet/index」で下記のように作成したつぶやきが表示されればコードは正しいです。

20241211_215123_tweet28.jpg

次はつぶやきの編集をします。


つぶやきの編集

 つぶやきを編集するページに移動できるようにします。

web.phpに下記の記述をします。

Route::middleware('auth', 'verified')->group(function () {
    Route::controller(TweetController::class)->group(function() {
        Route::get('/tweet/create', 'create')->name('tweet.create');

        Route::post('/tweet/store', 'store')->name('tweet.store');

        Route::get('/tweet/index', 'index')->name('tweet.index');

        Route::get('/tweet/{id}/edit', 'edit')->name('tweet.edit');         //この行を追加
    });
});

TweetController.phpにeditアクションの記述をします。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Tweet;

class TweetController extends Controller
{
    public function create()
    {
        return view('tweet.create');
    }

    public function store(Request $request)
    {
        $tweets = new Tweet();
        $tweets->body = $request->body;
        $tweets->save();
        return back()->with('message', 'つぶやきを作成しました');
    }

    public function index()
    {
        $tweets = Tweet::all();

        return view('tweet.index', compact('tweets'));
    }


    //ここから追加
    public function edit(Tweet $tweet)
    {
        return view('tweet.edit', compact('tweet'));
    }
    //ここまで追加

    
}

editアクションの引数の「$tweet」はルーティングで記述した「{tweet}」です。

Route::get('/tweet/{tweet}/edit', 'edit')->name('tweet.edit');


「Tweet $tweet」のTweetはTweetモデルのことです。

この記述をすることでルーティングのtweetをコントローラーで使うことができるようになります。

コードの作法って感じなので覚えていいです。

次はビューですがedit.blade.phpを記述する前にindex.blade.phpに編集のリンクを付けます。

index.blade.phpに下記の記述をします。

<div class="wrap">
    <h2>つぶやき一覧</h2>
    @foreach ($tweets as $tweet)
        <div class="tweet">
            <p>{{$tweet->body}}</p>
            <a href="{{ route('tweet.edit', $tweet) }}"><button>編集</button></a>      //この行を追加
        </div>
    @endforeach
</div>

<style>
    .wrap{
        width: 80%;
        margin-left:auto;
        margin-right:auto;
        padding-top: 50px;
    }
    .tweet{
        margin-bottom: 40px;
    }
    p{
        background-color:#f2eeed;
        padding: 5px;
    }
</style>

「tweet」が何度も出てきて頭がこんがらがる(私がLaravelを勉強したての時は訳が分からなかったです)と思うので突っ込んで説明します。

編集のページに移動する時はindex.blade.phpの「$tweet」からスタートします。

<a href="{{ route('tweet.edit', $tweet) }}">

リンクをクリックした時に「$tweet」をルーティングの「{tweet}」に渡します。

Route::get('/tweet/{tweet}/edit', 'edit')->name('tweet.edit');

ルーティングでは「$」を取って「{}」を付けます。

そして「tweet」をeditアクションに渡します。

public function edit(Tweet $tweet)

そしてeditアクションにcompactがあるのでedit.blade.phpで「$tweet」を変数として使うことができます。

まだ説明していませんでしたがhrefの中身は下記の書き方をします。

{{ route('web.phpのnameの中身', パラメーター) }}

「web.phpのnameの中身」は「->name('tweet.edit')」のことでパラメーターは「$tweet」です。

パラメーターを使わないリンクの場合は第2引数を付けなくていいです。

次はedit.blade.phpです。

コードを下記にします。

<div class="wrap">
    <h1>つぶやきの編集</h1>
    <form method="post" action="">
        @csrf
        @method('put')
        <div>
            <textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く">{{ $tweet->body }}</textarea>
        </div>
        <button type="submit">つぶやく</button>
    </form>
</div>

<style>
    .wrap{
        width: 80%;
        margin-left:auto;
        margin-right:auto;
        padding-top: 50px;
    }
    button{
        margin-top: 20px;
    }
</style>

これでつぶやき一覧のページ(http://localhost:8888/tweet/index)で編集ボタンを押すとつぶやきの編集ページに遷移します。

フォームの中には編集する前の内容が表示されます。

20241213_074733_tweet29.jpg

次はつぶやきの内容の更新ができるようにします。


つぶやきの更新

web.phpに下記の記述をします。

Route::middleware('auth', 'verified')->group(function () {
    Route::controller(TweetController::class)->group(function() {
        Route::get('/tweet/create', 'create')->name('tweet.create');

        Route::post('/tweet/store', 'store')->name('tweet.store');

        Route::get('/tweet/index', 'index')->name('tweet.index');

        Route::get('/tweet/{tweet}/edit', 'edit')->name('tweet.edit');

        Route::put('/tweet/{tweet}/update', 'update')->name('tweet.update');     //この行を追加
    });
});

Httpリクエストは更新なのでputです。

更新するのにファイルは必要ないのでupdate.blade.phpは作成しません。

「->name('tweet.update')」の「tweet.update」はedit.blade.phpで使います。

コントローラーにupdateアクションの記述をします。

public function update(Request $request, Tweet $tweet)
{
    $tweet->body = $request->body;
    $tweet->save();
    return back();
}

edit.blade.phpに追記します。

<div class="wrap">
    <h1>つぶやきの編集</h1>
    <form method="post" action="{{ route('tweet.update', $tweet) }}">       //この行を修正
        @csrf
        @method('put')
        <div>
            <textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く">{{ $tweet->body }}</textarea>
        </div>
        <button type="submit">つぶやく</button>
    </form>
</div>

<style>
    .wrap{
        width: 80%;
        margin-left:auto;
        margin-right:auto;
        padding-top: 50px;
    }
    button{
        margin-top: 20px;
    }
</style>

少し突っ込んで説明すると下記のコードに違和感を感じませんか?

<form method="post" action="{{ route('tweet.update', $tweet) }}">

method="post"はHttpリクエストのことです。

更新をする時はputなのにpostの記述をしています。

更新・削除の時も「method="post"」にしないといけません。

その代わり「@csrf」の下の行に更新の場合は「@method('put')」を記述して削除の場合は「@method('delete')」を記述します。

作成の時は「@method('put')」・「@method('delete')」に該当する記述はありません。(下記のコード参照)

<div class="wrap">
    @if(session('message'))
        <p class="flash">{{ session('message') }}</p>
    @endif
    <h1>つぶやきの作成</h1>
    <form method="post" action="{{ route('tweet.store') }}">
        @csrf     //@csrfの下の行に「@method('put')」・「@method('delete')」に該当する記述がない
        <div>
            <textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く"></textarea>
        </div>
        <button type="submit">つぶやく</button>
    </form>
</div>

これでつぶやきを更新できます。

最後は削除です。

あと少しで解説が終わるので頑張って下さい。


つぶやきの削除

web.phpに下記の記述をします。

Route::middleware('auth', 'verified')->group(function () {
    Route::controller(TweetController::class)->group(function() {
        Route::get('/tweet/create', 'create')->name('tweet.create');

        Route::post('/tweet/store', 'store')->name('tweet.store');

        Route::get('/tweet/index', 'index')->name('tweet.index');

        Route::get('/tweet/{tweet}/edit', 'edit')->name('tweet.edit');

        Route::put('/tweet/{tweet}/update', 'update')->name('tweet.update');

        Route::delete('/tweet/{tweet}/delete', 'delete')->name('tweet.delete');        //この行を追加
    });
});

TweetController.phpにdeleteアクションの記述をします。

class TweetController extends Controller
{
    public function create()
    {
        return view('tweet.create');
    }

    public function store(Request $request)
    {
        $tweets = new Tweet();
        $tweets->body = $request->body;
        $tweets->save();
        return back()->with('message', 'つぶやきを作成しました');
    }

    public function index()
    {
        $tweets = Tweet::all();

        return view('tweet.index', compact('tweets'));
    }

    public function edit(Tweet $tweet)
    {
        return view('tweet.edit', compact('tweet'));
    }
    
    public function update(Request $request, Tweet $tweet)
    {
        $tweet->body = $request->body;
        $tweet->save();
        return back();
    }

    public function delete(Tweet $tweet)
    {
        $tweet->delete();
        return back();
    }
}

index.blade.phpに削除ボタンを設置して削除の機能をさせます。

<div class="wrap">
    <h2>つぶやき一覧</h2>
    @foreach ($tweets as $tweet)
        <div class="tweet">
            <p>{{$tweet->body}}</p>
            <a href="{{ route('tweet.edit', $tweet) }}"><button>編集</button></a>


            //ここから追加
            <form method="post" action="{{route('tweet.delete', $tweet)}}">
                @csrf
                @method('delete')
                <button type="submit">削除</button>
            </form>
            //ここまで追加

            
        </div>
    @endforeach
</div>

<style>
    .wrap{
        width: 80%;
        margin-left:auto;
        margin-right:auto;
        padding-top: 50px;
    }
    .tweet{
        margin-bottom: 40px;
    }
    p{
        background-color:#f2eeed;
        padding: 5px;
    }
</style>

これで削除ボタンが機能します。

これでリソースコントローラーを使わないつぶやきアプリの完成です。

今回はここまでです。次回の解説からアプリの難易度を少し上げますのでLaravelを初めたての人はここまでの解説を何度も繰り返した方がいいです。

丸暗記しなくていいので作成の流れを体に覚え込ませて下さい。















戻る