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

目次

つぶやきの編集と削除

今回はつぶやきの編集と削除をします。

つぶやきアプリ作成の最後の解説になります。


つぶやき一覧に編集ボタンを設置

つぶやき一覧のページにつぶやきを編集する為のボタンを設置します。

index.blade.phpを修正します。

<div class="wrap">
    <h2>つぶやき一覧</h2>
    @foreach ($tweets as $tweet)
        <div class="tweet">
            <p>{{$tweet->body}}</p>
            <a href=""><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>

下記の表示になるかを確認して下さい。

20241124_170401_tweet24.jpg

まだ編集ボタンは機能していませんがこれから機能させます。


つぶやきの編集の流れ

あなたがつぶやきを編集する時をイメージすると考えやすいと思います。

つぶやきを編集する時はまず編集のページに移動してつぶやきの内容を変更して更新すると思います。

だからまず編集のページに移動する為のアクションを設定します。


つぶやきの編集ページに移動する為のアクション

TweetController.phpを編集します。

public function edit(string $id)
{
    return view('tweet.edit');
}

「return view('  ');」の中身を「tweet.edit」にしたのは「php artisan route:list」をした時に下記の表示の中のeditアクションを見たからです。

tweet ................. tweet.index › TweetController@index
tweet ................. tweet.store › TweetController@store
tweet/create .......... tweet.create › TweetController@create
tweet/{tweet} ......... tweet.show › TweetController@show
tweet/{tweet} ......... tweet.update › TweetController@update
tweet/{tweet} ......... tweet.destroy › TweetController@destroy
tweet/{tweet}/edit .... tweet.edit › TweetController@edit

次はビューです。


ビュー

編集ページは作成ページとほぼ同じなのでひとまずcreate.blade.phpをコピーして「tweet > resources > views > tweet」の下にedit.blade.phpを作成して貼り付けます。

一応ファイルの中身を掲載します。

<div>
    <h1>つぶやきの作成</h1>
    <form method="post" action="{{route('tweet.store')}}">
        @csrf
        <div>
            <textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く"></textarea>
        </div>
        <button type="submit">つぶやく</button>
    </form>
</div>

ページにアクセスして表示されるかを確認したいのでURLをチェックする為に「php artisan route:list」をすると下記の表示になります。

tweet ................. tweet.index › TweetController@index
tweet ................. tweet.store › TweetController@store
tweet/create .......... tweet.create › TweetController@create
tweet/{tweet} ......... tweet.show › TweetController@show
tweet/{tweet} ......... tweet.update › TweetController@update
tweet/{tweet} ......... tweet.destroy › TweetController@destroy
tweet/{tweet}/edit .... tweet.edit › TweetController@edit

今回該当するURLを見ると今までとは違うことが分かります。

「{tweet}」が今まではありませんでした。

これはパラメーターと言います。

パラメーターは1・2・3・4などの数値のことです。

もっと言うとtweetsテーブルのレコードのidカラムの値が該当します。

20241124_175455_tweet25.jpg

上記の例だとtweetに1が入った「tweet/1/edit」にアクセスしてつぶやきを作成するページと同じ表示になったら大丈夫です。

ちなみになぜパラメーターが必要かですがつぶやきを編集するのにパラメーターがないとどのつぶやきを編集するかが分からないからです。

だから編集・更新・削除する場合は必ずパラメーターが必要になります。

見た目を修正する為に下記のコードに変更します。

<div class="wrap">
    <h1>つぶやきの編集</h1>
    <form method="post" action="{{route('tweet.store')}}">
        @csrf
        <div>
            <textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く"></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>

下記の表示になるのを確認して下さい。

20241124_181210_tweet26.jpg
つぶやきを編集する時はフォームの中に編集したい内容が表示されてないと変ですよね。

だからコードを下記に修正します。

<div class="wrap">
    <h1>つぶやきの編集</h1>
    <form method="post" action="{{route('tweet.store')}}">
        @csrf
        <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>

「$tweet->body」の「body」はカラム名ですが「$tweet」何なのか分からないと思います。

コントローラーのeditアクションを修正します。

public function edit(Tweet $tweet)
{
    return view('tweet.edit', compact('tweet'));
}

editアクションの引数を「Tweet $tweet」にしていますがTweetはモデル名でtweetsテーブルのデータを$tweetという変数として使うことができるという認識で大丈夫です。

そしてcompactで$tweetをビューに渡してビューで「{{ $tweet->body }}」と記述することでつぶやきの内容を表示しています。

これで「tweet/1/edit」を再読み込みするとつぶやきの内容がフォームに入っているのを確認できます。

20241124_191804_tweet27.jpg

それではつぶやきの更新をします。


つぶやきの更新

アクションは下記のどれになるか分かりますか?

tweet ................. tweet.index › TweetController@index
tweet ................. tweet.store › TweetController@store
tweet/create .......... tweet.create › TweetController@create
tweet/{tweet} ......... tweet.show › TweetController@show
tweet/{tweet} ......... tweet.update › TweetController@update
tweet/{tweet} ......... tweet.destroy › TweetController@destroy
tweet/{tweet}/edit .... tweet.edit › TweetController@edit

updateになります。

TweetController.phpのupdateアクションの記述を下記に変更します。

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

updateアクションの引数に「Tweet $tweet」を追加しています。

edit.blade.phpに「{{ $tweet->body }}」があったのを覚えていますか?

<textarea name="body" cols="40" rows="10" placeholder="ここにつぶやきの内容を書く">{{ $tweet->body }}</textarea>

これの値を変更する為にupdateアクションの引数に「Tweet $tweet」を追加しました。

下記のコードはつぶやきの作成の時と全く同じです。

$tweet->body = $request->body;
$tweet->save();
return back();

「$tweet->body」はtweetsテーブルのbodyカラムの内容で「$request->body」は編集フォームの内容です。

「$tweet->save();」は変更したつぶやきの内容を保存して「return back();」は更新後に同じページにリダイレクトします。

これでコントローラーの修正はできましたがビュー(edit.blade.php)の修正はしていないので修正します。

ビューの修正

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) }}"」に「$tweet」が追加されていますがこれはパラメーターになります。

先ほど確認した「{tweet}」です。

tweet/{tweet}/edit .... tweet.edit › TweetController@edit

それと更新するときは「@csrf」の下の行に「@method('put')」を書かないとエラーになる仕様になっています。

これでビューも完成です。

ところでupdateアクションに対してビューを作成してないですがなぜか分かりますか?

更新は処理だけで表示するビューがなくても成立するからupdateの時はビュー作を成しません。

同様に作成するstoreアクション・削除するdestroyアクションもビューを作成しないくていいです。


編集ボタンの機能

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>

これでつぶやき一覧のページ(http://localhost:8888/tweet)で編集ボタンをクリックするとつぶやきの編集ができます。

最後につぶやきを削除できるようにします。


つぶやきの削除

つぶやき一覧のページで削除ボタンを設置します。

index.blade.phpのコードを下記に変更します。

<div class="wrap">
    <h2>つぶやき一覧</h2>
    @foreach ($tweets as $tweet)
        <div class="tweet">
            <p>{{$tweet->body}}</p>
            <div class="flex">
                <a href="{{ route('tweet.edit', $tweet) }}"><button>編集</button></a>
                <form method="post" action="{{route('tweet.destroy', $tweet)}}">
                    @csrf
                    @method('delete')
                    <button type="submit">削除</button>
                </form>
            </div>
        </div>
    @endforeach
</div>

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

ここまでの解説が理解できた人は理解が楽だと思いますが2点違いがあります。

1点目は「@method('delete')」です。

削除する時はこれを付けないとエラーが出る仕様になっています。

2点目は削除の時はformタグを使う点です。

削除の時はformタグを使うと覚えていいです。

コントローラーの記述をしていないのでTweetController.phpのコードを下記にします。

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

引数の「Tweet $tweet」はupdateアクションの時と考え方が全く同じで「$tweet」は削除しようとしているtweetsテーブルの該当のレコードになります。

それを「->delete()」で削除します。

これでつぶやきアプリの作成は完成です。

5回に渡る解説を読んでいただきありがとうございました。

通常のアプリではログインを先にしないとつぶやきを投稿したり編集したり削除できないですがあえてログイン機能を入れていません。

またルーティングの設定とコントローラーの記述が楽なリソースコントローラーをあえて使っていますが次のアプリの作成からログイン機能とリソースコントローラーではないコントローラーを使います。

戻る