newlaravelcoder's avatar

Property [weight] does not exist on this collection instance.

Guys, I'm brand new to the Laravel universe, and I apologize for this long message. I'm putting the finishing touches on my first ecommerce store, but I'm having issues getting the shipping api to function so I can charge the customer for shipping rates. I decided to go to with Shippo for the api because I heard it was compatible with Laravel, but it is difficult. I managed to get the code to read the customer's submitted address dynamically, but I can't seem to do the same for the weight, thus the error

Property [weight] does not exist on this collection instance.

I'm using the

use Gloudemans\Shoppingcart\Facades\Cart;
  $carts = Cart::content();

to read the cart data on the payment page and it works. When I do a die dump with $carts, I can read the content data, but when I try to execute the following code like so

$parcel = array(
    'length'=> '6',
    'width'=> '5',
    'height'=> '5',
    'distance_unit'=> 'in',
    'weight'=> $carts->weight,
    'mass_unit'=> 'lb',
);

I get the Property[weight] error. Does anybody know how to solve this issue?

0 likes
16 replies
Sinnbeck's avatar

Carts seems to be multiple

dd($carts);
$parcel = array(
    'length'=> '6',
    'width'=> '5',
    'height'=> '5',
    'distance_unit'=> 'in',
    'weight'=> $carts->weight,
    'mass_unit'=> 'lb',
);
newlaravelcoder's avatar

@Sinnbeck Yes, there is a lot of information in the cart, but I only need the weight and the quantity. I'm at a total loss, considering that a die dump or a php echo of $carts clearly shows the data. You mentioned show content method. What exactly do you mean?

newlaravelcoder's avatar

@Sinnbeck a die dump of Cart::content() does the same thing as the die dump of $carts. No difference.

Illuminate\Support\Collection {#1758 ▼
  #items: array:1 [▼
    "d7526188f20e4280f12c233cba5251ce" => Gloudemans\Shoppingcart\CartItem {#1755 ▼
      +rowId: "d7526188f20e4280f12c233cba5251ce"
      +id: "22"
      +qty: 6
      +name: "Prairie Sage Heritage Soap Bar"
      +price: 6.5
      +weight: 0.6
      +options: Gloudemans\Shoppingcart\CartItemOptions {#1756 ▼
        #items: array:3 [▼
          "image" => "images/products/1714987607816402.jpg"
          "color" => null
          "size" => null
        ]
        #escapeWhenCastingToString: false
      }
      +taxRate: 21
      -associatedModel: null
      -discountRate: 0
    }
  ]
  #escapeWhenCastingToString: false
}

Sinnbeck's avatar

@newlaravelcoder yes I know. I asked to see what it refers to. Anyways.. If you want the first cart, you can do

$parcel = array(
    'length'=> '6',
    'width'=> '5',
    'height'=> '5',
    'distance_unit'=> 'in',
    'weight'=> $carts->first()->weight,
    'mass_unit'=> 'lb',
);
newlaravelcoder's avatar

@Sinnbeck Thanks for that. That works, but I feel that's not getting the appropriate weight. Right now I have six of the same item with a weight of 0.6, thus the total weight should be 3.6 libs. I tried to mimic your code like this

'weight'=> $carts->first()->weight * $carts-.>qty,

but it triggers an error

Sinnbeck's avatar

@newlaravelcoder if there is multiple, then use sum like snapey suggested

'weight'=> $carts->sum('weight') * $carts->sum('qty') 
Snapey's avatar

if carts is a collection then maybe you have multiple weights (one per item) that you need to iterate over and sum.

If you have just one item in the cart then it might look like $carts->weight is directly accessible but actually its a property of the child item

newlaravelcoder's avatar

@Snapey I need to plan for both contigencies, but right now, I only have six of the same item in the cart. The weight is the same at 0.6, but the total weight has to reflect the number of items in the cart. Yes $carts is a collection, but I'm at a loss of how to do this. I'm brand new to laravel and am learning on the fly. Any suggesstions?

newlaravelcoder's avatar

@Snapey Thank you. When I take your suggestion and amplify it with $carts->sum('weight') * $carts->sum('qty'), I get the correct weight.

Snapey's avatar

@newlaravelcoder This is not correct solution.

You need to add all of quantity * weight for each item in the cart not total weight * total items

So you will probably need to iterate over the cart items getting the total weight for each

eg, you could have

  • 5 items at 1 kilo
  • 2 items at 6 kilos

Your calculation for weight will give 7 * 7 kilos = 49 when actually the weight is 5 + 12 = 17 kilos

'weight' = $carts->reduce(function ($carry, $item) {
        return $carry + $item->qty * $item->weight;
    }),

https://laravel.com/docs/8.x/collections#method-reduce

newlaravelcoder's avatar

Thank you all for your help, but just when one problem is solved, another arises. Now that the Shippo shipping api works, I'm having a hard time selecting one shipping rate among the listed rates, and adding it to the overall cart total to process payment.

The Shippo code for this is a bit confusing, here is what it has listed

$rates = $shipment['rates'];

echo "Available rates:" . "\n";
foreach ($rates as $rate) {

}
echo "\n";


// This would be the index of the rate selected by the user
$selected_rate_index = count($rates) - 1;

// After the user has selected a rate, use the corresponding object_id
$selected_rate = $rates[$selected_rate_index];
$selected_rate_object_id = $selected_rate['object_id'];

$transaction = Shippo_Transaction::create(array(
'rate'=> $selected_rate_object_id,
'async'=> false,
));

After researching the internet, I came across an old article with Shippo and he used a foreach loop to show the rates, which works, but selecting one and passing it to the overall cart total

{{ $cartTotal }}

The foreach rates loop is like this

<h1>Shipping</h1>

   <form action="#" method="post">
       @csrf
       <table class="table">
           <tr>
               <th>Name</th>
               <th>Price</th>
           </tr>
           @foreach ($rates as $rate)
           <tr>
               <td>
                   <img src="{{ $rate->provider_image_75 }}" alt="">
                   {{ $rate->provider }} ({{ $rate->duration_terms }})
               </td>
               <td width="20%">
                   <input type="radio" class="pull-right" name="rate" value="{{ $rate->object_id }}">
                   ${{ $rate->amount }}
               </td>
           </tr>

           @endforeach
       </table>

   </form>

I thought it would be as simple as adding

{{ $cartTotal }} with {{ $rate->amount }}

but no dice.

Please or to participate in this conversation.