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

目次

商品をカートに追加・カートの商品の削除

今回は商品をカートに追加してカートの商品の削除・購入ができるようにします。

前回リレーションの解説をしていますがリレーションが何かを知らない人は読んでいないと今回の記事は理解できないので必ず読んで下さい。

商品をカートに追加する為のweb.phpの設定から始めます。


web.php

下記の記述をします。

Route::middleware('auth')->group(function () {
    Route::controller(ShopController::class)->group(function () {
        Route::get('/stock/create', 'create')->name('shop.create');

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

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

        Route::delete('/stock/{stock}/delete', 'delete')->name('shop.delete');

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

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

        Route::post('/mycart/add', 'addMyCart')->name('shop.addmycart');
    });
});

「shop / index.blade.php」に下記の記述をします。

<div class="item-wrap">
    @forelse($items as $item)
        <div class="item">
            <h2>{{ $item->name }}</h2>
            <img src="{{ asset('storage/images/' . $item->image) }}" alt="">
            <p>{{ $item->detail }}</p>
            <form method="post" action="{{ route('shop.delete', ['stock' => $item->id]) }}">
                @csrf
                @method('DELETE')
                <button class="delete-button" onClick="return confirm('本当に削除しますか?');">削除</button>
            </form>
            <a class="item-edit" href="{{ route('shop.edit', ['stock' => $item->id]) }}">編集</a>


            //ここから追加
            <form action="{{ route('shop.addmycart') }}" method="post">
                @csrf
                <input type="hidden" name="stock_id" value="{{ $item->id }}">
                <input type="submit" value="カートに入れる">
            </form>
            //ここまで追加


        </div>
    @empty
        <p>登録商品がまだありません。</p>
    @endforelse
</div>

値の保存をする時に今までは「<input type="hidden"」の記述をしていませんでした。

保存するidの指定をしなくてよかったからですが今回はカートに追加するidを指定しないといけないので「<input type="hidden"」の記述しています。


カートに追加する処理

addMyCardメソッドの記述をする前にカート用のテーブルを作成します。

テーブル名をcartsとします。

下記のコマンドを叩きます。

php artisan make:model Cart -m

マイグレーションファイルに記述しますがcartsテーブルに必要な情報は下記になります。

user_idはリレーションを使う時のカラムの書き方になっていますがユーザーのidはリレーションを使わなくても取得できるのでリレーションをする為の記述ではないです。

マイグレーションファイルに下記の記述をします。

public function up(): void
{
    Schema::create('carts', function (Blueprint $table) {
        $table->id();
        $table->unSignedBigInteger('stock_id');
        $table->integer('user_id');
        $table->timestamps();
    });
}

「unSignedBigInteger」は初めて登場したデータ型ですがリレーションをする時に使います。

下記のコマンドを叩きます。

php artisan migrate

それではリレーションの設定をします。

1つの商品情報(stocksテーブル)が色んな人のカート(cartsテーブル)に追加されるのでStockが親モデルでCartが子モデルです。

前回のリレーションの解説では親テーブルから子テーブルの情報を取得しましたが今回は親テーブルの情報をcartsテーブルに登録しないといけないので子テーブルから親テーブルの情報を取得します。

だから子モデルにリレーションの設定をするのでCartモデルに下記の記述をします。

public function stock() {
    return $this->belongsTo(Stock::class);
}

子テーブルから親テーブルの情報を取得する時の関数名は親テーブル名の最後のsを取ります。

「belongsTo」は子モデルに記述する場合です。(親モデルの場合はhasManyでした)

それではaddMyCartメソッドの記述をします。

use App\Models\Cart;


public function addMyCart(Request $request, Cart $cart) {
    $cart->addCart($request->stock_id);

    return back()->with('message', 'カートに追加しました');
}

Cartモデルに下記の記述をします。

public function addCart($stock_id) {
    return Cart::firstOrCreate(['stock_id' => $stock_id,'user_id' => Auth::id()]);
}

「firstOrCreate」メソッドはレコードがあったらそれを取得してない場合はレコードを作成します。

カートに商品を追加する時にcartsテーブルにレコードはないので今回は作成します。

カラムに保存する値は引数に連想配列の形式で記述します。

「Auth::id()」がログインユーザーのidになります。

リレーションで取得することもできますが必要ないのでしていません。

これでカートに追加する処理ができました。

商品一覧で「カートに入れる」ボタンをクリックすると下記の表示になります。

20250306_113632_ec8.jpg

cartsテーブルを見るとレコードが作成されているが確認できます。

20250306_114218_ec9.jpg

CartモデルのfirstOrCreateメソッドでカートに追加する処理をしたので同じ商品を何度も追加できません。

本格的なECサイトではないので今回はこの記述で先に進めます。

次はマイカートの表示をします。


マイカートの表示

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

Route::middleware('auth')->group(function () {
    Route::controller(ShopController::class)->group(function () {
        Route::get('/stock/create', 'create')->name('shop.create');

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

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

        Route::delete('/stock/{stock}/delete', 'delete')->name('shop.delete');

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

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

        Route::post('/mycart/add', 'addMyCart')->name('shop.addmycart');

        Route::get('/mycart', 'myCart')->name('shop.mycart');
    });
});

Cartモデルに下記の記述をします。

public static function cartIndex() {
        return Cart::where('user_id', Auth::id())->get();
    }

Shopコントローラーに下記の記述をします。

public function myCart() {
    $carts = Cart::cartIndex();
    
    return view('shop.mycart', compact('carts'));
}

「shop / index.blade.php」に下記の記述をします。

<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>マイカート</title>
    </head>
    <body>
        <div class="item-container">
            <h1>マイカート</h1>
            @if(session('message'))
                <div class="flash">
                    {{ session('message') }}
                </div>
            @endif
            <div class="item-wrap">
                @forelse($carts as $cart)
                    <div class="item">
                        <h2>{{ $cart->stock->name }}</h2>
                        <img src="{{ asset('storage/images/' . $cart->stock->image) }}" alt="">
                        <form method="post" action="">
                            @csrf
                            @method('DELETE')
                            <button class="delete-button" onClick="return confirm('本当に削除しますか?');">カートから削除</button>
                        </form>
                    </div>
                @empty
                    <p>カートは空っぽです。</p>
                @endforelse
            </div>
        </div>
    </body>
</html>

<style>
    .item-container {
        width: 80%;
        margin-left: auto;
        margin-right: auto;
    }
    .item-wrap{
        display: flex;
        flex-wrap:wrap;
        gap:1%;
    }
    .item{
        width: 32%;
    }
    .item img{
        width: 100%;
    }
    .item h2{
        font-size: 18px;
        margin-bottom: 10px;
        text-align: center;
    }
    @media screen and (min-width: 1023px) {
        .item h2 {
            font-size: 25px;
        }
    }
    .item p{
        font-size: 13px;
        margin-top: 5px;
    }
    @media screen and (min-width: 1023px) {
        .item p {
            font-size: 16px;
        }
    }
    h1 {
        font-size: 18px;
        text-align: center;
    }
    @media screen and (min-width: 1023px) {
        h1 {
            font-size: 25px;
        }
    }
    .delete-button{
        font-size: 13px;
    }
    .flash {
        font-size: 13px;
        border: 1px solid red;
        padding: 10px;
        text-align: center;
    }
    @media screen and (min-width: 1023px) {
        .flash {
            font-size: 16px;
        }
    }
</style>

下記の表示になったら成功です。

20250306_133553_ec10.jpg
値の表示に関して説明します。

商品名を表示している部分に「{{ $cart->stock->name }}」と記述しています。

リレーションの解説をした時に親テーブルから子テーブルの情報を表示した時と考え方が全く同じです。

stockはCartモデルに記述したstockメソッドのことでnameはstocksテーブルのnameカラムのことです。

最後にカートに表示している商品の削除をします。


マイカートの商品を削除

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

Route::middleware('auth')->group(function () {
    Route::controller(ShopController::class)->group(function () {
        Route::get('/stock/create', 'create')->name('shop.create');

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

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

        Route::delete('/stock/{stock}/delete', 'delete')->name('shop.delete');

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

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

        Route::post('/mycart/add', 'addMyCart')->name('shop.addmycart');

        Route::get('/mycart', 'myCart')->name('shop.mycart');

        Route::delete('/mycart/{cart}/delete', 'cartDelete')->name('mycart.delete');
    });
});

Shopコントローラーに下記の記述をします。

public function cartDelete(Cart $cart) {
    $cart->cartDelete();

    return back()->with('message', '削除しました');
}

Cartモデルに下記の記述をします。

public function cartDelete() {
    $this->delete();
}

「shop /mycart.blade.php 」を修正します。

<div class="item-wrap">
    @forelse($carts as $cart)
        <div class="item">
            <h2>{{ $cart->stock->name }}</h2>
            <img src="{{ asset('storage/images/' . $cart->stock->image) }}" alt="">
            <form method="post" action="{{ route('mycart.delete', ['cart' => $cart->id]) }}">         //この行を修正
                @csrf
                @method('DELETE')
                <button class="delete-button" onClick="return confirm('本当に削除しますか?');">カートから削除</button>
            </form>
        </div>
    @empty
        <p>カートは空っぽです。</p>
    @endforelse
</div>

これで削除ボタンが動作します。

今回の解説はここまでです。


次の解説

下記のリンクからどうぞ。

https://laravelyarubai.newsite-make.com/post/34/view







戻る