Crinsane / LaravelShoppingcart

A simple shopping cart implementation for Laravel
MIT License
3.67k stars 1.73k forks source link

All LaravelShoppingcart methods don't work when using api call in laravel #367

Open ahmedfaical opened 7 years ago

ahmedfaical commented 7 years ago

Hello i have i problem and i can't resolve it All LaravelShoppingcart methods don't work when using api call in laravel to retrieve session data? Any idea?

Crinsane commented 7 years ago

I need more information to debug this. Are the API calls using a session or not? What is the code you use, which version of Laravel and this package. How can I reproduce this problem. Otherwise I can't help you.

ahmedfaical commented 7 years ago

I'm using Redis driver with laravel 5.4

This is the code in my routes/api.php : 
Route::get('/test', "Frontoffice\CartController@test");

I access to my api in browser like this : www.example.com/api/test So when i'm using this function :

    public function test(){
        Cart::add(18, 'nameee', 2, 44, array('size' => 'De4', 'stock' => '2'));
        return Cart::content();
    }

I get content but when i delete the line Cart::add :

    public function test(){
        return Cart::content();
    }

I can't get old session data, i get nothing

ahmedfaical commented 7 years ago

Any idea please that can help me? it's like that a new session created or something like that, Can you help me?

matejsvajger commented 7 years ago

@leonfather Laravel routes in routes/api.php don't have a session by default. Either move your route to routes/web.php -> Route::get('/api/test', "Frontoffice\CartController@test"); or enable sessions via middleware in API route group.

ahmedfaical commented 7 years ago

@matejsvajger I still get the same problem

Crinsane commented 7 years ago

Does the normal laravel session work? Can you put something in the session and retreive it?

ahmedfaical commented 7 years ago

yes it works i'm using redis in session I store my session data using Redis::set('test', $value); And i retrieve this value Redis::get('test', $value);

Crinsane commented 7 years ago

That's not the Laravel session you're using. You're using Redis directly, and not via the session manager (which this package is using) Try with the Session facade please

https://laravel.com/docs/5.4/session

ahmedfaical commented 7 years ago

i'm using session facade i only change SESSION_DRIVER=redis from file to redis

ahmedfaical commented 7 years ago

But when i'm doing test to see if laravel session work or now i get those results :

public function test(Request $request){
    $request->session()->put('key', 'value');
    $key = $request->session()->get('key');
    return response($key);
}

in the same route /test i get result : value But when trying to access this value from an other route i get 'value'. Any idea from where i get the problem ?

matejsvajger commented 7 years ago

@leonfather you're setting and retrieving the session value in the same call. Try retrieving it in a different function.

ahmedfaical commented 7 years ago

yes i'm doing tests now and laravel session works fine, Any idea from where i get the problem ? This is my code : CartController.php

<?php

namespace App\Http\Controllers\Frontoffice;

use Gloudemans\Shoppingcart\Facades\Cart;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class CartController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index($prefix)
    {

        //Cart::destroy();
        //dd(Config::get(tldConfig().'.curr_symbol'));

        //$this->updateCartStock();

        //Cart::add(18, 'name one', 2, 44, array('size' => 'De4', 'stock' => '2'));

        if($prefix == translate('global.cart')){
            return view('frontoffice.cart.index');
        }
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */

    public function create()
    {

    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }

    public function addToCart(Request $request){
        $item = $request->input('item');
        $stock = $item['stock'] - $item['qty'];
        Cart::add($item['ref'], $item['name'], $item['qty'], $item['price'], array('size' => $item['size'], 'stock' => $stock));

        return response(Cart::content());
    }

    public function cartContent(){
        $cartContent = Cart::content();
        return response($cartContent);
    }

    public function removeFromCart(Request $request){
        $rowId = $request->input('rowId');
        Cart::remove($rowId);
    }

    public function updateCart(Request $request){
        $rowId = $request->input('rowId');
        $data = $request->input('data');
        Cart::update($rowId, $data[0]);
        $subtotal = Cart::subtotal(0);
        $countItem = Cart::count();
        return response(array('subTotal' => $subtotal, 'countItem' => $countItem));
    }

    public function cartSubTotal(){
        $subTotal = Cart::subtotal(0);
        return response($subTotal);
    }

    public function countItem(){
        $countItem = Cart::count();
        return response(array('countItem' => $countItem));
    }

    public function updateCartStock(){

        $cart = Cart::content();
        $refs = array();
        foreach($cart as $key => $value){
            $refs[] = $value->id;
        }

        $stocks = DB::table('products_references_has_stocks AS prhs')
            ->whereIn('prhs.prod_ref_id', $refs)->select('prhs.prod_ref_id', DB::raw("SUM(`prhs`.`stock`) AS stock"))
            ->groupBy('prhs.prod_ref_id')->get();

        $getStock = array();
        foreach($stocks->toArray() as $key => $value){
            $getStock[$value->prod_ref_id] = $value->stock;
        }

        foreach($cart as $key => $value){
            Cart::update($key, ['options'  => ['stock' => $getStock[$value->id] - $value->qty, 'size' => $value->options->size]]);
        }
    }

    public function test1(Request $request){
        //Cart::add(18, 'name one', 2, 44, array('size' => 'De4', 'stock' => '2'));
        //Cart::add(19, 'name two', 5, 55, array('size' => 'De4', 'stock' => '2'));

        $request->session()->put('key', 'value');

        $key = $request->session()->get('key');
        $response = Cart::content();
        return response($key);
    }

    public function test2(Request $request){
        //Cart::add(18, 'name one', 2, 44, array('size' => 'De4', 'stock' => '2'));
        //Cart::add(19, 'name two', 5, 55, array('size' => 'De4', 'stock' => '2'));

        $key = $request->session()->get('key');
        return response($key);
    }
}

cart/index.blade.php (cart file)

@section('content')
                    <table v-if="Object.keys(cartItems).length > 0" border="1">

                        <thead>
                            <tr>
                                <th width="5%">Photo </th>
                                <th width="50%">Name</th>
                                <th width="15%">Prix unitaire</th>
                                <th width="15%">Qty</th>
                                <th width="15%">Prix</th>
                            </tr>
                        </thead>

                        <tbody>

                        <tr v-for="item in cartItems">
                            <td>
                                <a @click="removeFromCart(item.rowId)">Delete</a>
                            </td>
                            <td> @{{ item.name }} - @{{ item.options.size?item.options.size : '' }} ----- Current Stock : @{{ item.options.stock }}</td>
                            <td>
                                @{{ item.price }} {{ Config::get(tldConfig().'.curr_symbol') }}
                            </td>
                            <td>
                                <v-btn @click.native="qtyLess(item)" fab dark small primary> - </v-btn>
                                <input width="2" v-model="item.qty" v-on:change="updateCart(item.rowId, [{'qty':item.qty}])"/>
                                <v-btn @click.native="qtyMore(item)" fab dark small primary> + </v-btn>
                            </td>
                            <td><transition name="fade-transition">
                                    <p v-if="!loading">@{{ item.price * item.qty }} {{ Config::get(tldConfig().'.curr_symbol') }} </p>
                                </transition>
                            </td>
                        </tr>

                        <tr>
                            <td></td>
                            <td></td>
                            <td>Sous total</td>
                            <td><transition name="fade-transition">
                                    <p v-if="!loading">@{{ subTotal }} {{ Config::get(tldConfig().'.curr_symbol') }}</p>
                                </transition>
                            </td>
                        </tr>

                        </tbody>
                    </table>

                    <p v-if="Object.keys(cartItems).length == 0">Votre panier ne contient aucun article</p>

                @endsection

vue js file :


require('./bootstrap');

import Vue from 'vue';

// Validation
import VeeValidate from "vee-validate";
import VeeValidateMessagesBR from "vee-validate/dist/locale/fr";
VeeValidate.Validator.addLocale(VeeValidateMessagesBR);
Vue.use(VeeValidate, {locale: 'fr', errorBagName: 'vErrors'})

import Vuetify from 'vuetify'
Vue.use(Vuetify)

Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name=_token]').getAttribute('content');

import headerMixin from './headerMixin'
import footerMixin from './footerMixin'

new Vue({
    el: "#app",
    mixins: [footerMixin, headerMixin],
    data () {
        return {
            subTotal : 0,
            loading : false,
            qty : 1,
            dialog : false,
            dialogContent : '',
            addToCartLoading : true,
                        countItem : 0,
            dialogWidth : '',
            cartItems :[]
        }
    },
    methods: {
        qtyMore(item){
            if(item.qty < item.options.stock){
                item.qty = item.qty + 1
                this.updateCart(item.rowId, [{'qty':item.qty}])
            }
        },
        qtyLess(item){
            if(item.qty > 1){
                item.qty = item.qty - 1
                this.updateCart(item.rowId, [{'qty':item.qty}])
            }
        },
        updateCart(rowId, data){
            this.loading = true
            this.$http.put('/api/updateCart', {rowId : rowId, data : data}).then(response => {
                this.loading = false
                this.subTotal = response.data.subTotal
                this.countItems()
            });
        },
        checkQty(item){
            if(item.qty <= 0){
                alert('Valeur minimal est 1')
                item.qty = 1
            }
            if(item.qty > Number(item.options.stock)){
                alert('Désolé, il n en reste que '+item.options.stock+' en stock')
                item.qty = item.options.stock
            }
        },
        removeFromCart(rowId){
            this.loading = true
            this.$http.post('/api/remove', {rowId : rowId}).then(response => {
                Vue.delete(this.cartItems, rowId);
                this.cartSubTotal()
                this.countItems()
                this.loading = false
            });
        },
               cartSubTotal(){
            this.loading = true
            this.$http.get('/api/cartSubTotal').then(response => {
                this.loading = false
                this.subTotal = response.data
            });
        },
        countItems(){
            this.loading = true
            this.$http.get('/api/countItem').then(response => {
                this.loading = false
                this.countItem = response.data.countItem
            });
        },
        cartContent() {
            this.$http.get('/api/cartContent').then(response => {
                this.cartItems = response.data
                this.cartSubTotal()
            });
        }
    },
        mounted: function () {
        this.countItems()
        this.cartContent()
        console.log(this.countItem)
    }
});
ahmedfaical commented 7 years ago

in CartController in index method :

public function index($prefix)
    {
        Cart::add(18, 'name one', 2, 44, array('size' => 'De4', 'stock' => '2'));
        if($prefix == translate('global.cart')){
            return view('frontoffice.cart.index');
        }
    }

With this code i get content in cart but if i comment Cart::add(18,...... i get nothing in cart content

hakobfromlightin commented 7 years ago

I have the same problem with cart, any help will be appreciated

jakus1 commented 7 years ago

I had this problem just now and this is how I fixed it. First you need to change the api middleware group to:

'api' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    'throttle:60,1',
    'bindings',
],

in

app/Http/Kernel.php

It is important that all entries are there and that they are in this order.

codeitlikemiley commented 6 years ago

well 3 things you need to observe since im using this basically for vue SPA, and using api calls... your api endpoints should be located in your routes/web.php secondly, you need to make session lifetime, that way, even if the user abandon it, laravel will still recognize the session , so all data about the cart will be still there... third , you need to use localstorage that will read the stored cart object , im using a modular store VUEX. by default the localstorage check for the cart object if stored if not check my global state initial state which also has the Cart Object. Lastly if it cannot find the cart , then it just an empty array

jsdecena commented 6 years ago

The API is session-less since it is token-based. Surely, you will not be able to retrieve the items added in the current session since the token might not know who is the currently logged user ( unless you make the app known based on token and logged it in )

OctaneInteractive commented 6 years ago

Hi @codeitlikemiley, I'm creating a Vue SPA.

I've switched to the web routes, but Cart::content() still isn't giving me anything.

Are you using sessions?

jordantsap commented 6 years ago

use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use App\Product; use Gloudemans\Shoppingcart\Facades\Cart; use Session;

jamalali commented 6 years ago

Is this still an isue for anyone else?

stanislavkhatko commented 6 years ago

It's still an issue for me. When I add those middlewares to 'api' group, it brakes Passport auth:api system.

The workaround solution is to move shopping cart routes to web.php, wherein 'web' middleware session already exists and retrieves cart correctly.

chrisvidal commented 5 years ago

I found a solution by inserting the 'web' middleware in the api routes.php

Route::group([
        'middleware' => ['web'],
        'prefix' => 'api',
        'namespace' => 'Api\Http\Controllers'
    ], function () {

hope that helps

kratos619 commented 5 years ago

api_add this is add function to add item into cart api_function this is cart content function api_route this is route api to call that function

but in response i dont get any data in android device please helpppppppppppppppp