I am trying to create a cart controller. I am using Laravel's Http Session to achieve this. However, I am getting this error:
Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR) Cannot use assign-op operators with string offsets
Previous exceptions - Illegal string offset 'quantity' (0)
This is my current code which is causing this error:
public function addOrUpdate(Request $request) {
if(!isset($request->productName) && !isset($request->productId))
return Redirect::back()->withErrors(['Please fill in all the required fields.'])->withInput();
# Init cart if not yet set
if(!$request->session()->has('cart'))
$request->session()->put('cart', []);
# Pull and delete the old value
$product = $request->session()->pull("cart.{$request->productId}", "cart.{$request->productId}");
# If we managed to pull anything, lets increase the quantity
if(isset($product)) {
$product['quantity']++;
$request->session()->push('cart', [$request->productId => $product]);
var_dump($request->session('cart')); # Confirmation
return true;
}
# Nothing was pulled, lets add it
$request->session()->push('cart', [$request->productId => [
'productName' => $request->productName,
'quantity' => 1
]]);
var_dump($request->session('cart')); # Confirmation
return true;
}
When I do a var_dump($product)
before I pass it through the isset()
condition, it gives me a value of string(6) "cart.1"
.
If I do a var_dump(session('cart'))
before I pass it through the isset()
condition, it gives me (with test data)
array(1) { [0]=> array(1) { [1]=> array(2) { ["productName"]=> string(3) "foo" ["quantity"]=> int(1) } } }
In Laravel's documentation,
#Retrieving & Deleting An Item
The pull method will retrieve and delete an item from the session in a single statement:
$value = $request->session()->pull('key', 'default');
How can I get the current product stored in the ID, remove it, edit it and then re-insert it because this seems to be returning the array I am trying to get.
Update
public function addOrUpdate(Request $request) {
if(!isset($request->productName) && !isset($request->productId))
return Redirect::back()->withErrors(['Please fill in all the required fields.'])->withInput();
# Init cart if not yet set
if(!session()->has('cart'))
session()->put('cart', []);
$cart = session('cart');
if(isset($cart[$request->productId])){
# Pull and delete the old value
$product = session()->pull("cart.{$request->productId}", "cart.{$request->productId}");
# If we managed to pull anything, lets increase the quantity
if(isset($product)) {
$product['quantity']++;
session()->push("cart.{$request->productId}", $product);
echo 'Updated';
dd(session('cart'));
return true;
}
return false;
}
# Nothing was pulled, lets add it
session()->push("cart.{$request->productId}", [
'productName' => $request->productName,
'quantity' => 1
]);
echo 'Added';
dd(session('cart'));
return true;
}
This now seems to be adding the correct information but never updating. Do I need to flash()
the session at all?
The main issue here was the fact that the HTTP Session in Laravel is only used once. In order to keep the values, it is imperative to flash()
or reFlash()
the cart.
public function addOrUpdate(Request $request) {
if(!isset($request->productName) && !isset($request->productId))
return Redirect::back()->withErrors(['Please fill in all the required fields.'])->withInput();
# Init cart if not yet set
if(!session()->has('cart')) {
session()->put('cart', []);
session()->flash('cart');
}
$cart = session('cart');
if(isset($cart[$request->productId])){
# Pull and delete the old value
$product = session()->pull("cart.{$request->productId}", "cart.{$request->productId}");
# If we managed to pull anything, lets increase the quantity
if(isset($product)) {
$product[0]['quantity']++;
session()->push("cart.{$request->productId}", $product[0]);
session()->reFlash('cart');
}
} else {
# Nothing was pulled, lets add it
session()->push("cart.{$request->productId}", [
'productName' => $request->productName,
'quantity' => 1
]);
session()->reFlash('cart');
}
}
The only issue here is that if the user navigates any where else, the other routes do not reFlash the cart. So this must be implemented.
I achieved this by adding this line of code in the boot()
method of my RouteServiceProvider.php
file:
if(session()->has('cart'))
session()->reFlash('cart');