Laravel | Cart | Cart ページの作成

ホーム  

概要

2025年8月14日
スマホでも「カートに入れる」ボタンや、数量変更をしても、ページトップに戻らないようにしました。 staticposition.js が変更になっています。注意してください。

このページでは、ショッピングサイトの Cart ページを作ります。完成図は次のようになります。


Darryldecode/cart のインストール

Cart 機能を追加する Darryldecode/cart をインストールします。ターミナルで cart プロジェクトに移動して、 次のようにコマンドしてください。


composer require darryldecode/cart


ルートの追加

Cart ページ用にルートを追加します。routes / web.php を次のように変更してください。


<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CartController;

Route::get('/', [CartController::class, 'index'])->name('cart.index');
// ここから
Route::post('/cart/add', [CartController::class, 'addToCart'])->name('cart.add');
Route::get('/cart', [CartController::class, 'showCart'])->name('cart.show');
Route::post('/cart/update', [CartController::class, 'updateCart'])->name('cart.update');
Route::post('/cart/remove', [CartController::class, 'removeItem'])->name('cart.remove');
Route::post('/cart/clear', [CartController::class, 'clearCart'])->name('cart.clear');
// ここまで追加

CartController の変更

app / Http / Controllers の CartController.php を次のように変更してください。


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Darryldecode\Cart\Facades\CartFacade as Cart;
use App\Models\Product;
use Illuminate\Testing\Constraints\SeeInOrder;
use Nette\Schema\Expect;

class CartController extends Controller
{
    public function index()
    {
        $products = Product::all();
        return view('products', compact('products'));
    }
    
    // ここから
    public function addToCart(Request $request)
    {
        $product = [
            'id' => $request->id,
            'name' => $request->name,
            'price' => $request->price,
            'quantity' => $request->quantity,
            'attributes' => ['added_at' => now()]
        ];

        Cart::add($product);

        return redirect('/');
        // return $this->showCart();
    }

    public function showCart()
    {
        $cartContent = Cart::getContent()->sortBy("attributes.added_at")->values();


        return view('cart.show', compact('cartContent'));
    }

    public function updateCart(Request $request)
    {
        Cart::update($request->id, [
            'quantity' => [
                'relative' => false,
                'value' => $request->quantity,
            ]
        ]);

        return $this->showCart();
    }

    public function removeItem(Request $request)
    {
        Cart::remove($request->id);

        return $this->showCart();
    }

    public function clearCart()
    {
        Cart::clear();
        
        return $this->index();
    }
     // ここまで追加
}



CSS ファイルの変更

public フォルダの style.css を次のように変更してください

8月12日。
デザイン変更のため、変更しました。


/*****************************
style.css
copyright    : vivacocoa.jp
last modified: Aug. 12, 2025
*****************************/

body {
    background-color: #ffffff;
    margin: 0;
}

.spc {
    display: flex;
    background-color: #000000;
}

.spc>div:nth-child(1) {
    text-align: left;
    width: 30%;
}

.spc>div:nth-child(2) {
    text-align: center;
    width: 40%;
}

.spc>div:nth-child(3) {
    text-align: right;
    width: 30%;
}

h1 {
    font-size: large;
    margin: 16px;
    color: #ffffff;
}

h1 a {
    color: #ffffff;
    text-decoration: none;
}

h1 a:hover {
    border: 1px #ffffff solid;
    padding: 8px px;
    margin: 0px;

}

#btn-cart {
    background-color: #ffd600;
    color: #000000;
    border: 0;
    border-radius: 16px;
    text-align: center;
    font-size: small;
    padding: 4px;
    width: 100px;
    margin: 16px;
    font-weight: bolder;

}

#container {
    margin-top: 16px;
    margin-left: 8px;
}

.d-flex {
    display: flex;
    flex-wrap: wrap;
    justify-content: left;
}

.product {
    margin: 8px;
    text-align: center;
}

.btn-yellow {
    background-color: #ffd600;
    border: 0;
    border-radius: 16px;
    text-align: center;
    font-size: small;
    margin-bottom: 8px;
    width: 85%;
    padding: 4px;
}

/* ここから */
#btn-checkout {
    background-color: #ffd600;
    color: #000000;
    border: 0;
    border-radius: 16px;
    text-align: center;
    font-size: small;
    padding: 4px;
    width: 85%;
    margin: 16px;
    font-weight: bolder;
}

.a-center {
    text-align: center;
}

table {
    width: 100%;
}

.flex {
    display: inline-flex;
}

.btn-delete {
    text-decoration: underline;
    color: blue;
    border: 0;
    background-color: #ffffff;
    margin-top: 8px;

}
/* ここまで追加 */


JavaScript

2025年8月14日
public / staticposition.js は、スマホでも「カートに追加」や数量を変更してもページトップに戻らないように、 次のように変更しました。


history.scrollRestoration = "manual";

window.addEventListener("load", () => {
    const scrollPosition = sessionStorage.getItem("scrollPosition");
    if (scrollPosition) {
        window.scrollTo(0, parseInt(scrollPosition));
    }
});

window.addEventListener("scroll", () => {
    sessionStorage.setItem("scrollPosition", window.scrollY.toString());
});

window.addEventListener("beforeunload", () => {
    sessionStorage.setItem("scrollPosition", window.scrollY.toString());
});


Cart ページ

resources / views の中に cart というフォルダを作り、その中に show.blade.php というファイルを作り、次のように記述してください。

8月12日。
デザイン変更のため、変更しています。


{{----------------------------
show.blade.php
copyright    : vivacocoa.jp
last modified: Aug. 12, 2025
-----------------------------}}

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{{url('style.css')}}">
    <script src="{{url('staticposition.js')}}"></script>
    <title>ショッピングカート</title>
</head>
<body>
<div class="spc">
    <div>
    <h1><a href="{{ route('cart.index') }}">AMAZONESS</a></h1>
    </div>
    <div></div>
    <div>
    <form>
        @csrf
        <button type="button" id="btn-checkout"><strong>レジに進む</strong></button>
    </form>
    </div>
</div>
<div id="container">
<table>
        @foreach($cartContent as $item)
        <tr>
            <td>
                <div class="a-center">
                    <p><strong>{{ $item->name }}</strong></p>
                </div>
            </td>
            <td>
                <div>
                    <p><small>¥</small> {{ number_format($item->price) }} <small>税込</small></p>
                </div>
            </td>
            <td>
                <div class="flex">
                    <form method="POST" action="{{route('cart.update')}}">
                    @csrf
                    <input type="hidden" name="id" value="{{$item->id}}">
                    <input type="number" name="quantity" onchange="submit()" style="width: 50px;" value="{{$item->quantity}}"> <small>個</small>
                    </form>
                     
                    <form method="POST" action="{{route('cart.remove')}}">
                    @csrf
                    <input type="hidden" name="id" value="{{$item->id}}">
                    <button type="submit" class="btn-delete">削除</button>
                    </form>
                </div>
            </td>
            <td>
                <div>
                    <p><small>&yen;</small> {{ number_format($item->price * $item->quantity) }} <small>税込</small></p>
                </div>
            </td>

        </tr>
            @endforeach
        <tr>
            <td colspan="2">
                <a href="{{ route('cart.index') }}"><button type="button" class="btn-yellow"><strong>ショッピングを続ける</strong></button></a>
            </td>
            <td class="a-right">
                <form method="POST" action="{{ route('cart.clear') }}">
                @csrf
                <button type="submit" class="btn-yellow"><strong>カートを空にする</strong></button>
                </form>
            </td>
            <td class="a-right">
                <small>合計</small> 
                <small>&yen;</small> {{ number_format(Cart::getSubTotalWithoutConditions()) }} <small>税込</small>
            </td>

        </tr>
</table>
</div>
</body>
</html>


商品ページの変更

商品ページで止めていたリンクを張り直します。resources / views の products.blade.php を次のように変更してください。 変更箇所は3箇所で4行です。


{{----------------------------
products.blade.php
copyright    : vivacocoa.jp
last modified: Aug. 12, 2025
-----------------------------}}

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{{url('style.css')}}">
    <script src="{{url('staticposition.js')}}"></script>
    <title>Amazoness</title>
</head>
<body>
    <div class="spc">
    <<div>
    <h1><a href="{{ route('cart.index') }}">AMAZONESS</a></h1>
    </div>
    <div></div>
    <div>
        {{-- 次の2行が変更されています。--}}
        <a href="{{route('cart.show')}}"><button type="button" id="btn-cart">
        カート [ {{Cart::getTotalQuantity()}} ]
        {{-- 上の2行が変更されています。--}}
        </button></a>
    </div>
    </div>
<div id="container">
<div class="d-flex">
@foreach ($products as $product)
<div class="product">
<img src="{{ $product->image }}">
<h4>{{$product->name}}</h4>
<p>{{$product->desc}}</p>
<p><small>&yen;</small>  {{number_format($product->price)}}  <small>税込</small></p>
{{-- 次の1行が変更されています。--}}
<form method="POST" action="{{route('cart.add')}}">
{{-- 次の1行が変更されています。--}}
@csrf
<input type="hidden" name="id" value="{{$product->id}}">
<input type="hidden" name="name" value="{{$product->name}}">
<input type="hidden" name="price" value="{{$product->price}}">
<input type="hidden" name="quantity" value="{{$product->quantity}}">
<input type="hidden" name="desc" value="{{$product->desc}}">
{{-- 次の1行が変更されています。--}}
<button type="submit" class="btn-yellow">カートに追加</button>
{{-- 次の1行が変更されています。--}}
</form>
</div>
@endforeach
</div>
</div>
</body>
</html>

お使いのブラウザで、localhost:8000 もしくは 127.0.0.1:8000 にアクセスしてください。 「レジに進む」以外のボタンは、すべて機能しています。



3320 visits
Posted: Aug. 10, 2025
Update: Aug. 14, 2025

ホーム   目次