Laravelshoppingcart: Associate Model with Relationship

Created on 7 Aug 2015  路  6Comments  路  Source: Crinsane/LaravelShoppingcart

If I have a 'Product' and 'ProductAttribute' model, and I want to get the data from the ProductAttribute model, how do I associate them both with associate()?
Is it possible?

something like this Cart::associate('Product')->with('attribute')->add();

Most helpful comment

@skoellen Great work, thx.:) Association a cartItem with the 'AppProduct' model results in so many duplicate queries! I followed your idea but had no need to use an intermediate model. My code is as following:

CartController.php

public function store (Request $request, Product $product)
{
    Cart::add($product, $request->quantity, ['size' => $request->size]);

    return back();
}

public function show()
{
    $cartItems = Cart::content();

    $ids = $cartItems->pluck('id');

    $products = Product::findMany($ids);

    return view('carts.show', compact('cartItems', 'products'));
}

carts\show.blade.php

@foreach ($cartItems as $item)
    <div>
        {{ $products->find($item->id)->name }}
        {{ $products->find($item->id)->price }}
        {{ $products->find($item->id)->description }}
        {{ $item->options->size }}
        {{ $item->rowId }}
        {{ $item->qty }}
   </div>
 @endforeach

This way, my debug bar shows only one query:
select * from `products` where `products`.`id` in ('1', '2', '3')

All 6 comments

you mean associate to 2 models? if it's 2 models I will add second model data as option.

I'm interested in this functionality too. My models have several Relationships and queries get out of hand with just 2 products in the cart. I've tried using lazy eager loading ( http://laravel.com/docs/5.0/eloquent#eager-loading ), but since load() is a method of Database Collections and not Support Collections, method fails.

I've tried creating a new Database Collection from Cart::instance('main')->content() but I get this error
Call to undefined method Gloudemans\Shoppingcart\CartRowCollection::newQuery()

Dang this would be cool.

You can access relationships via the associated model if that model has the proper HasOne, hasMany etc relations coded into it.

If someone else comes here from search, I was testing around with this package and implemented a little workaround to reduce my queries when accessing cart-content and related information. Maybe this is helpful for someone:

In this example I have product_variants that each belong to a product.

  • Product
  • ProductVariant

I associated cartItems with my model ProductVariant, where actual price and stock etc. is stored. But I also wanted to access global product information like "title", "description" etc. in my cart overview. This is where I got the query problem people already mentioned here.

Cart::content() returns a collection, so I extracted the related / associated models and passed them separately to my view:

$cartItems = Cart::content();

// Get the ids from associated models of the cartItems
$ids = $cartItems->pluck('id');

// Here you can go wild on eager loading your relationships
$models = ProductVariant::with('product')->findMany($ids);

return view('cart-overview', ['cartItems' => $cartItems, 'models' => $models]);

In cart-overview.blade.php:

@foreach($cartItems as $item)

    <div class="panel panel-default">

    <div class="panel-heading">
        {{ $models->firstWhere('id', $item->id)->product->title }}
    </div>

    <div class="panel-body">
        {{ $models->firstWhere('id', $item->id)->product->description }}
            <hr>
            {{ $item->price }}
    </div>

    <a href="/cart/delete-item/{{ $item->rowId }}">Delete from cart</a>

    </div>

@endforeach

So I'm still looping over the cartItems within the view. But now with no additional queries (like e.g. $cartItem->model->product->title). The information is already eager loaded and is connected via the model ids and firstWhere(). And I can still use my cartItem information like $item->rowId.

@skoellen Great work, thx.:) Association a cartItem with the 'AppProduct' model results in so many duplicate queries! I followed your idea but had no need to use an intermediate model. My code is as following:

CartController.php

public function store (Request $request, Product $product)
{
    Cart::add($product, $request->quantity, ['size' => $request->size]);

    return back();
}

public function show()
{
    $cartItems = Cart::content();

    $ids = $cartItems->pluck('id');

    $products = Product::findMany($ids);

    return view('carts.show', compact('cartItems', 'products'));
}

carts\show.blade.php

@foreach ($cartItems as $item)
    <div>
        {{ $products->find($item->id)->name }}
        {{ $products->find($item->id)->price }}
        {{ $products->find($item->id)->description }}
        {{ $item->options->size }}
        {{ $item->rowId }}
        {{ $item->qty }}
   </div>
 @endforeach

This way, my debug bar shows only one query:
select * from `products` where `products`.`id` in ('1', '2', '3')

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shahin7511 picture shahin7511  路  8Comments

hasanali05 picture hasanali05  路  6Comments

wasid picture wasid  路  8Comments

shakhawatfci picture shakhawatfci  路  10Comments

nasirkhan picture nasirkhan  路  8Comments