Search code examples
laravelvue.jslocal-storagee-commerce

Lavarel & Vue e-commerce: how to post an order as array of products instead of single product


I am kinda new to both Laravel and Vue and I am working on a school project. I have been following a guide and trying to develop the product but I have the following problem: in the guide was only possible to do an order with a single product. Using LocalStorage a created a Cart component where you can add several products instead. How do I use axios.post to correctly post the order in the database now?

app/Http/Controllers/OrderController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Order;
use Auth;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function index()
    {
        return response()->json(Order::with(['product'])->get(),200);
    }

    public function store(Request $request)
    {
        $order = Order::create([
            'product_id' => $request->product_id,
            'user_id' => Auth::id(),
            'quantity' => $request->quantity,
            'address' => $request->address
        ]);

        return response()->json([
            'status' => (bool) $order,
            'data'   => $order,
            'message' => $order ? 'Order Created!' : 'Error Creating Order'
        ]);
    }

    public function show(Order $order)
    {
        return response()->json($order,200);
    }

Resources/JS/views/Checkout.vue (between < script > tag):

     placeOrder(e) {
                e.preventDefault()

                let address = this.address
                let product_id = this.product.id
                let quantity = this.quantity

                axios.post('api/orders/', {address, quantity, product_id})
                     .then(response => this.$router.push('/confirmation'))
            },

App/Http/Models/Order.php

<?php
    namespace App\Models;

    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;

    class Order extends Model
    {
        use SoftDeletes;

        protected $fillable = [
            'product_id', 'user_id', 'quantity', 'address' 
        ];

        public function user()
        {
            return $this->belongsTo(User::class, 'user_id');
        }

        public function product()
        {
            return $this->belongsTo(Product::class, 'product_id');
        }

    }

Solution

  • Actually, You can achieve your goal by changing many lines of code instead of using your current code at backend (laravel Model-Controller) and frontend (Vue). I will show you how to do by adding hasMany relationship in your User model structure, then changing saving method at controller, and axios request payload. This method has limitation, you have to post an array of products of the same user ID.

    1. Add hasMany relationship in your User Model. Read this
    class User extends Model
    {
        //add this line
        public function order()
        {
            return $this->hasMany(Order::class);
        }
    
    1. Use createMany function to save multiple rows in your controller. Read this
    public function store(Request $request)
        {
            //use this lines to store array of orders
            $user = Auth::user();
            $orderStored = $user->order()->createMany($request->data);
    
            //return your response after this line
        }
    
    1. Change your axios payload from vue method
    data(){
        return {
            //add new key data to store array of order
            arrayOfOrders:[];
       };
    },
    methods:{
        placeOrder(e) {
            e.preventDefault()
    
            let address = this.address
            let product_id = this.product.id
            let quantity = this.quantity
            //remark these lines, change with storing to arrayOfOrders data instead of doing post request
            //axios.post('api/orders/', {address, quantity, product_id})
                    //.then(response => this.$router.push('/confirmation'))
    
            this.arrayOfOrders.push({
                product_id:product_id,
                quantity:quantity, 
                address:address
            });
        },
        //create new function to make post request and call it from your button
        postData(){
            let instance = this;
            axios.post('api/orders/', {
                data:instance.arrayOfOrders
            }).then(response => this.$router.push('/confirmation'))
        }
    }