I want get my product conditions as array in order to add them in cart, this is dd of my product when I try to add it in my cart:
array:6 [▼
"id" => 4
"name" => "product four"
"price" => null
"quantity" => "1"
"attributes" => array:1 [▼
"attr" => array:2 [▼
"name" => "weight"
"value" => "45"
]
]
"conditions" => array:2 [▼
0 => CartCondition {#685 ▼ // need to add this
-args: array:4 [▼
"name" => "Black"
"value" => "10000"
"type" => "additional"
"target" => "item"
]
-parsedRawValue: null
}
1 => CartCondition {#692 ▼ // need to add this
-args: array:4 [▼
"name" => "12 inch"
"value" => "25000"
"type" => "additional"
"target" => "item"
]
-parsedRawValue: null
}
]
]
As you see unlike my attributes my conditions not show just as
array but get values in -args: and -parsedRawValue: null
When I try to add product in cart I get this error:
Darryldecode \ Cart \ Exceptions \ InvalidItemException
validation.required
Error
This is my function (how I get my conditions and where i use them:
public function addingItem(Request $request, $id)
{
//finding product
$product = Product::findOrFail($id);
//get product weight
$weight = $product->weight;
//list of discounts
$discounts = Discount::all();
//get current time
$mytime = Carbon::now();
// get product weight in cart as attribute
$weightArray = [
'attr' => [
'name' => 'weight',
'value' => $weight,
]
];
$customAttributes = []; // my conditions comes from here
if(!empty($request->attr)){
foreach($request->attr as $sub) {
// find the suboption
$sub = Suboption::find($sub);
if (!empty($sub->id)) {
$itemCondition1 = new \Darryldecode\Cart\CartCondition(array(
'name' => $sub->title,
'value' => $sub->price,
'type' => 'additional',
'target' => 'item',
));
array_push($customAttributes, $itemCondition1);
}
}
}
//adding product, options and conditions to cart
Cart::add(array(
'id' => $product->id,
'name' => $product->title,
'price' => $request->input('harga'),
'quantity' => $request->input('quantity'),
'attributes' => $weightArray,
'conditions' => $customAttributes, // added here
));
Session::flash('success', 'This product added to your cart successfully.');
return redirect()->back();
}
any idea why i get this error and how to fix it?
SOLVED
validation issue was caused by empty price value and that was because my loop in front end while getting diffirent price on discounts time and other times, by fixing my price loop i have my product price all the time and it not return null in my function anymore.
thanks for helps.
if you want to convert a collection to array just use ->toarray()
Also it is a bad practice to run a query inside a foreach loop because of N + 1 query problem you may want to consider using of findMany() rather than find()
also you may want to read about array_filter too
Related
I have 2 arrays and I want to merge them. (I can merge them) but I also need to include their unique keys in merged results and that part I cannot achieve.
sample
$prices = [
['112802' => "500000"],
['113041' => "1000000"],
];
$notes = [
['112802' => "note 2"],
['113041' => "note 1"],
];
$collection = collect($prices);
$zipped = $collection->zip($notes);
$zipped->toArray();
Unique keys are 112802 and 113041.
When I merge my array all I get is this:
[
[
"1000000",
"note 1"
],
[
"500000",
"note 2"
]
]
What I'm looking for is like this:
[
[
"id" => "112802",
"price" => "500000",
"note" => "note 2",
],
[
"id" => "113041",
"price" => "1000000",
"note" => "note 1",
]
}]
any suggestion?
This does what you want with the data you provide.
NOTE it will only work if your 2 arrays are the same size and the the keys are in the same order.
If this data comes from a database, it is likely it could have been produced in the format you actually wanted rather than having to fiddle with the data post fetch.
$prices = [
['112802' => "500000"],
['113041' => "1000000"],
];
$notes = [
['112802' => "note 2"],
['113041' => "note 1"],
];
$new = [];
foreach ($prices as $i=>$pr){
$k = key($pr);
$new[] = [ 'id' => $k,
'price' => $pr[$k],
'note' => $notes[$i][$k] ];
}
print_r($new);
RESULT
Array
(
[0] => Array (
[id] => 112802
[price] => 500000
[note] => note 2
)
[1] => Array (
[id] => 113041
[price] => 1000000
[note] => note 1
)
)
Here's another solution using some of Laravel's Collection methods.
It's not the most elegant, but it can be a starting point for you.
$prices = collect([
['112802' => "500000"],
['113041' => "1000000"],
])->mapWithKeys(function($item) {
// This assumes that the key will always be the ID and the first element is the price.
// Everythng else for each element will be ignored.
$id = array_keys($item)[0];
return [$id => ["id" => $id, "price" => reset($item)]];
});
$notes = collect([
['112802' => "note 2"],
['113041' => "note 1"],
])->mapWithKeys(function($item) {
$id = array_keys($item)[0];
return [$id => ["id" => $id, "note" => reset($item)]];
});
$result = $prices->zip($notes)->map(function ($item) {
// Feel free to call `toArray()` here if you don't want a Collection.
return collect($item)->mapWithKeys(function ($a) { return $a; });
});
Below is the $result (called using dd()).
Illuminate\Support\Collection {#1886 ▼
#items: array:2 [▼
0 => Illuminate\Support\Collection {#1888 ▼
#items: array:3 [▼
"id" => 112802
"price" => "500000"
"note" => "note 2"
]
}
1 => Illuminate\Support\Collection {#1889 ▼
#items: array:3 [▼
"id" => 113041
"price" => "1000000"
"note" => "note 1"
]
}
]
}
It's achieved by extracting the ID so that the zip can join there, but then we need a little hack with the map and mapWithKeys in the $result.
That's just because otherwise each element in $result will still have two separate arrays for $prices and $notes.
I am having an error when I try to when updating multiple names of filters.
public function update(Request $request, Filter $filter)
{
$filters = collect([$request->filters]);
$filters->each(function ($item) use ($request, $filter) {
if (!isset($item['name']) && !isset($item['latin'])) {
foreach ($item as $key) {
$data = [
'category_id' => $request->category_id,
'name' => $item[$key]['name'],
'latin' => $item[$key]['latin'],
'field' => $item[$key]['field'],
];
$filter->update($data);
}
} else {
return ;
}
}
}
When I change this, the first record is updated.
'name' => $item[1]['name'],
'latin' => $item[1]['latin'],
'field' => $item[1]['field'],
I now had three records and I changed all three folds and hit the reserve. The first record changed, the second and the third did not change. I want it to be n.
When I try this
$filters->each(function ($item) use ($request, $filter) {
if (!isset($item['field'])) {
dd($item);
}
I see this message
array:2 [▼
5 => array:4 [▼
"name" => "Value RAM"
"latin" => "ram"
"field" => "0"
"value" => array:2 [▼
0 => "One Gigabayte"
1 => "Twoo Gigabayte"
]
]
6 => array:3 [▼
"name" => "Color"
"latin" => "color"
"field" => "1"
]
]
#irankhostravi you are trying to get the wrong key from the array:
You are calling 'latin' => $item[$key]['latin'] but $key is not an integer but the value, because you are looping too many times trough the array.
If I dump the output of the $key this is what I get:
array:3 [▼
"latin" => "ram"
"field" => "0"
"value" => array:2 [▶]
]
// dump($key)
"key: ram"
So you need to remove that extra foreach(), which isn't necessary.
Besides of that, your are checking if 'name' and 'latin' are not set, if so, then you try to get the value of these non-existing keys..
I've refactored some of your code and I think this is what you need:
public function update(Request $request, Filter $filter)
{
collect($request->filters)
->each(function ($item) use ($request, $filter) {
// Check if the keys exists in the $item, otherwise return.
// Changed && to || because if one of them is missing, you want to abort,
// unless your database is accepting empty/nullable values.
// But please use validation rules here instead: https://laravel.com/docs/master/validation#quick-writing-the-validation-logic
if (! isset($item['name']) || ! isset($item['latin']) || ! isset($item['field'])) {
return;
}
$filter->update([
'category_id' => $request->category_id,
'name' => $item['name'],
'latin' => $item['latin'],
'field' => $item['field'],
]);
});
}
i have a function that it fills the one array like below :
if (isset($options[$attribute->id][$optionId])) {
foreach ($options[$attribute->id][$optionId] as $item) {
. . . .
$attributeOptionsData[] = [
'id' => $optionId,
'label' => $attributeOption->label ? $attributeOption->label : $attributeOption->admin_name,
'swatch_value' => $attribute->swatch_type == 'image' ? $attributeOption->swatch_value_url : $attributeOption->swatch_value,
'products' => $options[$attribute->id][$optionId],
'images' => $productImage ?? null,
];
dd($attributeOptionsData);
}
the result of this dd is like below :
array:1 [▼
0 => array:5 [▼
"id" => 1
"label" => "black"
"swatch_value" => "#000000"
"products" => array:1 [▶]
"images" => "product/4618/rAkC2aC3QJB6kMiAAzIGk6nUzGHxpdfIS55g3T0P.jpeg"
]
]
now what i want to do is that after the last line add some content to this array and make it like below:
array:1 [▼
0 => array:5 [▼
"id" => 1
"label" => "مشکی"
"swatch_value" => "#000000"
"products" => array:1 [▶]
"images" => "product/4618/rAkC2aC3QJB6kMiAAzIGk6nUzGHxpdfIS55g3T0P.jpeg"
"custom_field" => "some value"
]
]
on the line that i dd the array i want add the customfield to it . how can i do that thanks in advance.
the reason i dont insert like others in that i want to add the custom field in a foreach loop based on 1 field of that array
So, if you simply want to add something at the bottom of an array, just use array_push().
In your case, you would need to retrieve the whole $attributeOptionsData[] in a foreach loop and append the array to the key you're in, during that loop. Be aware that this is somehow inefficient. If you want to add a line based on a value you can retrieve in the first foreach loop, you could've just made an if-statement asking for that value and add it with array_push() afterwards.
Either way, I think this is what you're looking for:
if (isset($options[$attribute->id][$optionId])) {
foreach ($options[$attribute->id][$optionId] as $item) {
$attributeOptionsData[] = [
'id' => $optionId,
'label' => $attributeOption->label ? $attributeOption->label : $attributeOption->admin_name,
'swatch_value' => $attribute->swatch_type == 'image' ? $attributeOption->swatch_value_url : $attributeOption->swatch_value,
'products' => $options[$attribute->id][$optionId],
'images' => $productImage ?? null,
];
}
foreach($attributeOptionsData as $key=>$data){
array_push($attributeOptionsData[$key], ["custom_field" => "some value"])
}
}
$attributeOptionsData is an associative array. You can assign values to it by specifying the array $key:
$attributeOptionsData[$key] = $value;
Question background
Hello, I have the following array of movie crew members:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ed7"
"department" => "Writing"
"id" => 139098
"job" => "Story"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story"
"name" => "Ben Coccio"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee3"
"department" => "Writing"
"id" => 139098
"job" => "Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
4 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee9"
"department" => "Writing"
"id" => 132973
"job" => "Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
5 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
11 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
As you can see this is a list of credits I'm getting via the TMDb API. The first step of building the above array was to filter out all jobs that I don't want to display, here's how I did that:
$jobs = [ 'Director', 'Director of Photography', 'Cinematography', 'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer' ];
$crew = array_filter($tmdbApi, function ($crew) use ($jobs) {
return array_intersect($jobs, $crew);
});
My question
I'd like to figure out how to take the above result one step further and combine jobs where the id is the same, so as to end up with something like this, for example:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
I have also considered ditching doing this in my logic and instead doing it in my blade template, but I'm not sure how to achieve that.
How would you accomplish this?
You could nicely use Laravel's Collection in such a situation, which has a great number of methods which will help you in this case.
First, turn this array (the one you already filtered on jobs) to a Collection:
$collection = collect($crew);
Second, group this Collection by it's ids:
$collectionById = $collection->groupBy('id');
Now, the results are grouped by the id and transformed to a Collection in which the keys correspond to the id, and the value an array of 'matching' results. More info about it here.
Finally, just a easy script that iterates through all the results for each id and combines the job field:
$combinedJobCollection = $collectionById->map(function($item) {
// get the default object, in which all fields match
// all the other fields with same ID, except for 'job'
$transformedItem = $item->first();
// set the 'job' field according all the (unique) job
// values of this item, and implode with ', '
$transformedItem['job'] = $item->unique('job')->implode('job', ', ');
/* or, keep the jobs as an array, so blade can figure out how to output these
$transformedItem['job'] = $item->unique('job')->pluck('job');
*/
return $transformedItem;
})->values();
// values() makes sure keys are reordered (as groupBy sets the id
// as the key)
At this point, this Collection is returned:
Collection {#151 ▼
#items: array:4 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story, Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
}
Note: to use this Collection as an array, use:
$crew = $combinedJobCollection->toArray();
There are multiple ways to achieve this, for example: search the array for overlapping id's, but I think this is the easiest way to achieve this.
Goodluck!
Since you are trying to edit the array elements and its size, I believe array_map() or array_filter() won't be a solution to this.
This is what I could come up with...
$jobs = [
'Director', 'Director of Photography', 'Cinematography',
'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer'
];
$crew = [];
foreach($tmdbApi as $key => $member) {
if($member['id'] == $id && in_array($member['job'], $jobs)) {
if(!isset($crew[$key])) {
$crew[$key] = $member;
} else {
$crew_jobs = explode(', ', $crew[$key]['job']);
if(!in_array($member['job'], $crew_jobs)) {
$crew_jobs[] = $member['job'];
}
$crew[$key]['job'] = implode(', ', $crew_jobs);
}
}
}
Hope this answers your question :)
I am making a minimalist eCommerce web application using laravel framework and I am a newbie.
What I am trying to achieve is when a product exists in the session, I want to update the quantity of that product when Add to Cart button is clicked. And if it doesn't exists in the session, I want to insert it in the session.
Code that I have tried so far:
public function store( $id ) {
$product = Product::findOrFail( $id );
if ( \Session::has( 'cart' ) && is_array( \Session::get('cart') ) ) {
\Session::push('cart', ['product' => (int)$id, 'quantity' => 1 ]);
} else {
\Session::put('cart', ['product' => (int)$id, 'quantity' => 1 ]);
}
\Session::flash('added_product', 'Product Added in the cart');
return \Redirect::back();
}
The result of the above code is:
array:3 [▼
0 => array:2 [▼
"product" => 1
"quantity" => 1
]
1 => array:2 [▼
"product" => 2
"quantity" => 1
]
2 => array:2 [▼
"product" => 1
"quantity" => 1
]
]
Desired Result is:
array:2 [▼
0 => array:2 [▼
"product" => 1
"quantity" => 2
]
1 => array:2 [▼
"product" => 2
"quantity" => 1
]
]
Kindly help me out with this. Thanks.
UPDATE 1:
After Youssef Answer, I got the following result:
array:4 [▼
"product" => 1
"quantity" => 1
0 => array:2 [▼
"product" => 3
"quantity" => 1
]
1 => array:2 [▼
"product" => 2
"quantity" => 1
]
]
I don't know Laravel but i think you can just process the array like this:
public function store( $id ) {
$product = Product::findOrFail( $id );
if ( \Session::has( 'cart' ) && is_array( \Session::get('cart') ) ) {
$cart = \Session::get('cart');
$found = false;
foreach($cart as $i=>$el)
{
if($el['product'] == $id)
{
$cart[$i]['quantity']++;
$found = true;
}
}
if(!$found) {
$cart[] = ['product' => $i, 'quantity' => 1];
}
\Session::put('cart', $cart);
} else {
\Session::put('cart', [['product' => (int)$id, 'quantity' => 1 ]]);
}
\Session::flash('added_product', 'Product Added in the cart');
return \Redirect::back();
}
If the entry exists in the session you are creating and pushing a yet another item to the array which results in a duplicate result. You should probably change the if block to the following:
$value = Session::pull( 'cart', ['product' => int($id), 'quantity' => 0 ]);
$value['quantity'] += 1;
Session::put('cart', $value);
The pull method call will get you the cart value if it exists or create a new one if it doesn't exist (with quantity 0). It increments the quantity, which means it will rise by 1 if it's already there or set to 1 if it's the one you created in the pull call. The value is removed from session when you call pull so you will put back the new value into the session by calling put. Hope this gives a more concise code.
You can add array safety checks to the increment statement as: array_key_exists('quantity')