{"id":655,"date":"2025-09-05T11:54:22","date_gmt":"2025-09-05T11:54:22","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=655"},"modified":"2025-09-05T11:54:25","modified_gmt":"2025-09-05T11:54:25","slug":"how-to-build-a-shopping-cart-in-laravel","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/how-to-build-a-shopping-cart-in-laravel\/","title":{"rendered":"How to Build a Shopping Cart in Laravel"},"content":{"rendered":"\n<p>A shopping cart is one of the most common features in e-commerce applications. In Laravel, you can implement it in a clean, modular way using controllers, models, Blade views, and session or database storage. In this guide, we\u2019ll build a minimal yet extensible shopping cart system that supports adding products, updating quantities, removing items, persisting to database (optional), and rendering a clean UI. We\u2019ll also cover validation, middleware guards, and testing to ensure reliability.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Database Setup for Products<\/strong><\/h2>\n\n\n\n<p>Products should be stored in the database. For simplicity, our cart will use the <code>products<\/code> table.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">php artisan make:model Product -m<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ database\/migrations\/xxxx_xx_xx_create_products_table.php<\/span>\nSchema::create(<span class=\"hljs-string\">'products'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(Blueprint $table)<\/span> <\/span>{\n    $table-&gt;id();\n    $table-&gt;string(<span class=\"hljs-string\">'name'<\/span>);\n    $table-&gt;decimal(<span class=\"hljs-string\">'price'<\/span>, <span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">2<\/span>);\n    $table-&gt;unsignedInteger(<span class=\"hljs-string\">'stock'<\/span>)-&gt;default(<span class=\"hljs-number\">0<\/span>);\n    $table-&gt;timestamps();\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Seed your products table with some demo items for testing.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Session-Based Cart Structure<\/strong><\/h2>\n\n\n\n<p>We\u2019ll store cart items inside the session as an array keyed by product ID:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&#91;\n    <span class=\"hljs-number\">1<\/span> =&gt; &#91;<span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'Laptop'<\/span>, <span class=\"hljs-string\">'price'<\/span> =&gt; <span class=\"hljs-number\">999.99<\/span>, <span class=\"hljs-string\">'quantity'<\/span> =&gt; <span class=\"hljs-number\">2<\/span>],\n    <span class=\"hljs-number\">3<\/span> =&gt; &#91;<span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'Mouse'<\/span>, <span class=\"hljs-string\">'price'<\/span> =&gt; <span class=\"hljs-number\">25.00<\/span>, <span class=\"hljs-string\">'quantity'<\/span> =&gt; <span class=\"hljs-number\">1<\/span>],\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This structure keeps cart operations simple. Later, you can swap to a database-backed cart for authenticated users without changing much logic.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Cart Controller &amp; Routes<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">CartController<\/span>;\n\nRoute::prefix(<span class=\"hljs-string\">'cart'<\/span>)-&gt;name(<span class=\"hljs-string\">'cart.'<\/span>)-&gt;group(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    Route::get(<span class=\"hljs-string\">'\/'<\/span>, &#91;CartController::class, <span class=\"hljs-string\">'index'<\/span>])-&gt;name(<span class=\"hljs-string\">'index'<\/span>);\n    Route::post(<span class=\"hljs-string\">'\/add\/{product}'<\/span>, &#91;CartController::class, <span class=\"hljs-string\">'add'<\/span>])-&gt;name(<span class=\"hljs-string\">'add'<\/span>);\n    Route::post(<span class=\"hljs-string\">'\/update\/{product}'<\/span>, &#91;CartController::class, <span class=\"hljs-string\">'update'<\/span>])-&gt;name(<span class=\"hljs-string\">'update'<\/span>);\n    Route::post(<span class=\"hljs-string\">'\/remove\/{product}'<\/span>, &#91;CartController::class, <span class=\"hljs-string\">'remove'<\/span>])-&gt;name(<span class=\"hljs-string\">'remove'<\/span>);\n    Route::post(<span class=\"hljs-string\">'\/clear'<\/span>, &#91;CartController::class, <span class=\"hljs-string\">'clear'<\/span>])-&gt;name(<span class=\"hljs-string\">'clear'<\/span>);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/CartController.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">Product<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CartController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">index<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $cart = $request-&gt;session()-&gt;get(<span class=\"hljs-string\">'cart'<\/span>, &#91;]);\n        $total = collect($cart)-&gt;sum(fn ($item) =&gt; $item&#91;<span class=\"hljs-string\">'price'<\/span>] * $item&#91;<span class=\"hljs-string\">'quantity'<\/span>]);\n        <span class=\"hljs-keyword\">return<\/span> view(<span class=\"hljs-string\">'cart.index'<\/span>, compact(<span class=\"hljs-string\">'cart'<\/span>,<span class=\"hljs-string\">'total'<\/span>));\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">add<\/span><span class=\"hljs-params\">(Request $request, Product $product)<\/span>\n    <\/span>{\n        $cart = $request-&gt;session()-&gt;get(<span class=\"hljs-string\">'cart'<\/span>, &#91;]);\n\n        $qty = (int) $request-&gt;input(<span class=\"hljs-string\">'quantity'<\/span>, <span class=\"hljs-number\">1<\/span>);\n        <span class=\"hljs-keyword\">if<\/span> ($qty &lt; <span class=\"hljs-number\">1<\/span>) $qty = <span class=\"hljs-number\">1<\/span>;\n\n        <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($cart&#91;$product-&gt;id])) {\n            $cart&#91;$product-&gt;id]&#91;<span class=\"hljs-string\">'quantity'<\/span>] += $qty;\n        } <span class=\"hljs-keyword\">else<\/span> {\n            $cart&#91;$product-&gt;id] = &#91;\n                <span class=\"hljs-string\">'name'<\/span> =&gt; $product-&gt;name,\n                <span class=\"hljs-string\">'price'<\/span> =&gt; $product-&gt;price,\n                <span class=\"hljs-string\">'quantity'<\/span> =&gt; $qty,\n            ];\n        }\n\n        $request-&gt;session()-&gt;put(<span class=\"hljs-string\">'cart'<\/span>, $cart);\n        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'success'<\/span>, <span class=\"hljs-string\">'Product added to cart.'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">update<\/span><span class=\"hljs-params\">(Request $request, Product $product)<\/span>\n    <\/span>{\n        $cart = $request-&gt;session()-&gt;get(<span class=\"hljs-string\">'cart'<\/span>, &#91;]);\n        <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($cart&#91;$product-&gt;id])) {\n            $cart&#91;$product-&gt;id]&#91;<span class=\"hljs-string\">'quantity'<\/span>] = max(<span class=\"hljs-number\">1<\/span>, (int) $request-&gt;input(<span class=\"hljs-string\">'quantity'<\/span>, <span class=\"hljs-number\">1<\/span>));\n            $request-&gt;session()-&gt;put(<span class=\"hljs-string\">'cart'<\/span>, $cart);\n        }\n        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'success'<\/span>, <span class=\"hljs-string\">'Cart updated.'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">remove<\/span><span class=\"hljs-params\">(Request $request, Product $product)<\/span>\n    <\/span>{\n        $cart = $request-&gt;session()-&gt;get(<span class=\"hljs-string\">'cart'<\/span>, &#91;]);\n        <span class=\"hljs-keyword\">unset<\/span>($cart&#91;$product-&gt;id]);\n        $request-&gt;session()-&gt;put(<span class=\"hljs-string\">'cart'<\/span>, $cart);\n        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'success'<\/span>, <span class=\"hljs-string\">'Item removed.'<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">clear<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $request-&gt;session()-&gt;forget(<span class=\"hljs-string\">'cart'<\/span>);\n        <span class=\"hljs-keyword\">return<\/span> back()-&gt;with(<span class=\"hljs-string\">'success'<\/span>, <span class=\"hljs-string\">'Cart cleared.'<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The controller uses session storage to track cart items and provides endpoints for all core operations.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Blade UI for Cart<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!-- resources\/views\/cart\/index.blade.php --&gt;\n&lt;h2&gt;Shopping Cart&lt;\/h2&gt;\n\n@<span class=\"hljs-keyword\">if<\/span>(<span class=\"hljs-keyword\">empty<\/span>($cart))\n    &lt;p&gt;Your cart is <span class=\"hljs-keyword\">empty<\/span>.&lt;\/p&gt;\n@<span class=\"hljs-keyword\">else<\/span>\n    &lt;table&gt;\n        &lt;thead&gt;\n            &lt;tr&gt;&lt;th&gt;Product&lt;\/th&gt;&lt;th&gt;Qty&lt;\/th&gt;&lt;th&gt;Price&lt;\/th&gt;&lt;th&gt;Total&lt;\/th&gt;&lt;th&gt;&lt;\/th&gt;&lt;\/tr&gt;\n        &lt;\/thead&gt;\n        &lt;tbody&gt;\n        @<span class=\"hljs-keyword\">foreach<\/span>($cart <span class=\"hljs-keyword\">as<\/span> $id =&gt; $item)\n            &lt;tr&gt;\n                &lt;td&gt;{{ $item&#91;<span class=\"hljs-string\">'name'<\/span>] }}&lt;\/td&gt;\n                &lt;td&gt;\n                    &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('cart.update',$id) }}\"<\/span>&gt;\n                        @csrf\n                        &lt;input type=<span class=\"hljs-string\">\"number\"<\/span> name=<span class=\"hljs-string\">\"quantity\"<\/span> value=<span class=\"hljs-string\">\"{{ $item&#91;'quantity'] }}\"<\/span> min=<span class=\"hljs-string\">\"1\"<\/span> \/&gt;\n                        &lt;button&gt;Update&lt;\/button&gt;\n                    &lt;\/form&gt;\n                &lt;\/td&gt;\n                &lt;td&gt;${{ number_format($item&#91;<span class=\"hljs-string\">'price'<\/span>],<span class=\"hljs-number\">2<\/span>) }}&lt;\/td&gt;\n                &lt;td&gt;${{ number_format($item&#91;<span class=\"hljs-string\">'price'<\/span>] * $item&#91;<span class=\"hljs-string\">'quantity'<\/span>],<span class=\"hljs-number\">2<\/span>) }}&lt;\/td&gt;\n                &lt;td&gt;\n                    &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('cart.remove',$id) }}\"<\/span>&gt;\n                        @csrf\n                        &lt;button&gt;Remove&lt;\/button&gt;\n                    &lt;\/form&gt;\n                &lt;\/td&gt;\n            &lt;\/tr&gt;\n        @<span class=\"hljs-keyword\">endforeach<\/span>\n        &lt;\/tbody&gt;\n    &lt;\/table&gt;\n\n    &lt;p&gt;&lt;strong&gt;Total:&lt;\/strong&gt; ${{ number_format($total,<span class=\"hljs-number\">2<\/span>) }}&lt;\/p&gt;\n\n    &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('cart.clear') }}\"<\/span>&gt; @csrf\n        &lt;button&gt;Clear Cart&lt;\/button&gt;\n    &lt;\/form&gt;\n@<span class=\"hljs-keyword\">endif<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The Blade template loops through session items, calculates totals, and offers controls for updating and removing products.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Adding to Cart from Product List<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!-- resources\/views\/products\/index.blade.php --&gt;\n@<span class=\"hljs-keyword\">foreach<\/span>($products <span class=\"hljs-keyword\">as<\/span> $product)\n    &lt;div&gt;\n        &lt;h3&gt;{{ $product-&gt;name }}&lt;\/h3&gt;\n        &lt;p&gt;${{ number_format($product-&gt;price,<span class=\"hljs-number\">2<\/span>) }}&lt;\/p&gt;\n\n        &lt;form method=<span class=\"hljs-string\">\"POST\"<\/span> action=<span class=\"hljs-string\">\"{{ route('cart.add',$product) }}\"<\/span>&gt;\n            @csrf\n            &lt;input type=<span class=\"hljs-string\">\"number\"<\/span> name=<span class=\"hljs-string\">\"quantity\"<\/span> value=<span class=\"hljs-string\">\"1\"<\/span> min=<span class=\"hljs-string\">\"1\"<\/span> \/&gt;\n            &lt;button&gt;Add to Cart&lt;\/button&gt;\n        &lt;\/form&gt;\n    &lt;\/div&gt;\n@<span class=\"hljs-keyword\">endforeach<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This simple UI lets users add products to the cart with quantity input. The form posts to <code>cart.add<\/code>, which handles insertion into the session.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Persisting Cart for Authenticated Users<\/strong><\/h2>\n\n\n\n<p>For logged-in users, you may want to store carts in the database. Create a <code>carts<\/code> table linked to users and move session data into persistent storage on login or checkout. This allows users to resume shopping across devices.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">Schema::create(<span class=\"hljs-string\">'carts'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">(Blueprint $table)<\/span> <\/span>{\n    $table-&gt;id();\n    $table-&gt;foreignId(<span class=\"hljs-string\">'user_id'<\/span>)-&gt;constrained()-&gt;onDelete(<span class=\"hljs-string\">'cascade'<\/span>);\n    $table-&gt;json(<span class=\"hljs-string\">'items'<\/span>);\n    $table-&gt;timestamps();\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Sync session data to the user\u2019s cart record on login or checkout for persistence.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Testing the Cart<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ tests\/Feature\/CartTest.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">Product<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Tests<\/span>\\<span class=\"hljs-title\">TestCase<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CartTest<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">TestCase<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">test_can_add_product_to_cart<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        $product = Product::factory()-&gt;create();\n\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;post(<span class=\"hljs-string\">'\/cart\/add\/'<\/span>.$product-&gt;id, &#91;<span class=\"hljs-string\">'quantity'<\/span> =&gt; <span class=\"hljs-number\">2<\/span>])\n            -&gt;assertSessionHas(<span class=\"hljs-string\">'success'<\/span>);\n\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;assertEquals(<span class=\"hljs-number\">2<\/span>, session(<span class=\"hljs-string\">'cart'<\/span>)&#91;$product-&gt;id]&#91;<span class=\"hljs-string\">'quantity'<\/span>]);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">test_can_update_and_remove_cart_item<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        $product = Product::factory()-&gt;create();\n\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;post(<span class=\"hljs-string\">'\/cart\/add\/'<\/span>.$product-&gt;id);\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;post(<span class=\"hljs-string\">'\/cart\/update\/'<\/span>.$product-&gt;id, &#91;<span class=\"hljs-string\">'quantity'<\/span> =&gt; <span class=\"hljs-number\">5<\/span>]);\n\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;assertEquals(<span class=\"hljs-number\">5<\/span>, session(<span class=\"hljs-string\">'cart'<\/span>)&#91;$product-&gt;id]&#91;<span class=\"hljs-string\">'quantity'<\/span>]);\n\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;post(<span class=\"hljs-string\">'\/cart\/remove\/'<\/span>.$product-&gt;id);\n        <span class=\"hljs-keyword\">$this<\/span>-&gt;assertArrayNotHasKey($product-&gt;id, session(<span class=\"hljs-string\">'cart'<\/span>, &#91;]));\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Tests confirm that cart operations work correctly. Extend tests to include edge cases like invalid quantities and stock limits.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wrapping Up<\/strong><\/h2>\n\n\n\n<p>We built a minimal shopping cart in Laravel using session storage, complete with add, update, remove, and clear functionality. The Blade UI renders cart contents and totals, and we discussed persisting carts for authenticated users. This foundation can be extended with product stock checks, coupons, checkout workflows, and payment integrations.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What\u2019s Next<\/strong><\/h2>\n\n\n\n<p>Continue building your Laravel e-commerce toolkit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/building-a-simple-saas-billing-system-with-laravel-and-cashier\">Building a Simple SaaS Billing System with Laravel and Cashier<\/a><\/li>\n\n\n\n<li><a href=\"\/blog\/how-to-integrate-stripe-payments-in-laravel\">How to Integrate Stripe Payments in Laravel<\/a><\/li>\n\n\n\n<li><a href=\"\/blog\/handling-file-uploads-and-image-storage-in-laravel\">Handling File Uploads and Image Storage in Laravel<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A shopping cart is one of the most common features in e-commerce applications. In Laravel, you can implement it in a clean, modular way using controllers, models, Blade views, and session or database storage. In this guide, we\u2019ll build a minimal yet extensible shopping cart system that supports adding products, updating quantities, removing items, persisting [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":657,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[96,152,153,24,87],"class_list":["post-655","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-blade","tag-cart","tag-ecommerce","tag-sessions","tag-testing"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=655"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/655\/revisions"}],"predecessor-version":[{"id":658,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/655\/revisions\/658"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/657"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}