Trying to figure out how to delete item from cart in PHP - php

I am trying to make an e-commerce website and I can't quite figure out how to get the cart to function. I am able to add amounts to the cart before purchase but I want it to delete the item from the cart when the quantity is set to 0.
if (isset($_POST['update'])) {
for ($i = 0; $i < sizeof($_SESSION['quantity']); $i++) {
$postID = 'qty' . $i;
$_SESSION['quantity'][$i] = $_POST[$postID];
if ($_SESSION['quantity'][$i] == 0) {
unset($_SESSION['shoppingcart'][$i]);
unset($_SESSION['quantity'][$i]);
unset($_SESSION['name'][$i]);
unset($_SESSION['price'][$i]);
}
}
}
Here is the cart variable that creates a table of all the products added
<form method="post">
<?php
if (!empty($_SESSION['shoppingcart'])) {
for ($i = 0; $i < sizeof($_SESSION['shoppingcart']); $i++) {
$cart .= '<tr>';
$cart .= '<td>' . $_SESSION['name'][$i] . '</td>';
$cart .= '<td><input type="text" id="quantity"name="qty' . $i . '"value="' . $_SESSION['quantity'][$i] . '" onkeyup="checkInput()"></td>';
$cart .= '<td>$' . $_SESSION['price'][$i] . '</td';
$cart .= '<td>$' . $_SESSION['quantity'][$i] * $_SESSION['price'][$i] . '</td>';
$cart .= '</tr>';
$total += ($_SESSION['quantity'][$i] * $_SESSION['price'][$i]);
$totalDiscounted += ($_SESSION['quantity'][$i] * $_SESSION['price'][$i]) / 100 * 30;
}
</form>
This works when I delete things going from the last piece in the array, going to the first thing added in the array in that order, but when I try to delete the first element or anything out of order first, it gives me an error. "Warning: Undefined array key 0". What am I doing wrong?

The undefined index come from the use of unset(). The indexes of the array will not be re-ordered after unset() call.
Exemple:
$array = [1, 2, 3];
unset($array[1]);
print_r($array); // indexes : 0 and 2.
You could:
use array_values() to re-index arrays.
unset($_SESSION['shoppingcart'][$i]);
$_SESSION['shoppingcart'] = array_values($_SESSION['shoppingcart']);
or, check the presence of the data in the loop :
for ($i = 0; $i < sizeof($_SESSION['shoppingcart']); $i++) {
if (!isset($_SESSION['name'][$i])) {
continue;
}
$cart .= '<tr>';
//...
}
Another way is to use a data structure for the order:
// add
$_SESSION['shoppingcart'][] = [
'quantity' => 1,
'name' => 'item',
'price' => 1.00,
];
// to update an index
$_SESSION['shoppingcart'][$index]['quantity'] = 2;
// to remove an index
unset($_SESSION['shoppingcart'][$index]);
then, use a foreach() to list
foreach ($_SESSION['shoppingcart'] => $data) {
// display item
}

Related

Add new data in foreach loop multidimensional array

I try to add new data in a multidimensional array for each loop, but it wont work.
This shows the values in my array:
$keys = array_keys($klanten);
for($i = 0; $i < count($klanten); $i++) {
foreach($klanten[$keys[$i]] as $key => $value) {
echo $key . " : " . $value . "<br>";
$klanten['newData'] = 'test';
}
}
With $klanten['newData'] = 'test'; I try to add "test" to each array, but it won't work.
I also tried to use this, AFTER the script above:
foreach ($klanten as &$item ){
$item['newData'] = 'test';
}
That will work, but I think there must be an option to do it in the foreach loop above the first time. How can I do that?
Hi so you got most of it right but, you see when you are looping around a variable and adding a new item in it you have to make sure to give a index for that new array index so...
$keys = array_keys($klanten);
for($i = 0; $i < count($klanten); $i++) {
foreach($klanten[$keys[$i]] as $key => $value) {
echo $key . " : " . $value . "<br>";
// $klanten['newData'] = 'test'; // instead of this
$klanten[$key]['newData'] = 'test'; // do this
}
}
This will save each and every value of newData index according to its key in $klanten array.

Fill a php Multidimensional array in a html table

I was given to fill this html table according to this multidimensional array.
$eleves=array(
"Z200"=>array(
"Salima",
"module"=>array(
"Math"=>array("note"=>10,"cof"=>5),
"Physique"=>array("note"=>10,"cof"=>2),
"Langue"=>array("note"=>10,"cof"=>2)
)
),
"Z103"=>array(
"Ali",
"module"=>array(
"Math"=>array("note"=>2,"cof"=>5),
"Physique"=>array("note"=>5,"cof"=>2),
"Langue"=>array("note"=>7,"cof"=>2)
)
),
"Z109"=>array(
"Hind",
"module"=>array(
"Math"=>array("note"=>13,"cof"=>2),
"Physique"=>array("note"=>13,"cof"=>2),
"Langue"=>array("note"=>11# ,"cof"=>2)
)
)
);
I tried the foreach loop. I succeed to fill the first head tables.
But when it comes to calculate the notes it's diffcult to call the values
Can you help me guys please ?
You need a first foreach to browse $eleves. For each student, you need a second foreach to add all grades and evaluate the mean.
function evalMoyenne ($grades) {
$gradeSum = 0;
$coeffCount = 0;
foreach ( $grades as $subject => $grade ) {
$gradeSum += $grade['note'] * $grade['cof'];
$coeffCount += $grade['cof'];
}
return $gradeSum / $coeffCount;
}
foreach ( $eleves as $matricule => $row ) {
$moyenne = evalMoyenne( $row['module'] );
echo "<td>$matricule</td>"
. '<td>' . $row[0] . '</td>'
. '<td>' . $moyenne . '</td>'
}
Usually, if you have an array in an array, you need a foreach in a foreach. As an alternative, if there are a fixed subject count, you could also hardcode the meaning calculation:
$gradeSum = $row['module']['Math']['note'] * $row['module']['Math']['cof']
+ $row['module']['Physique']['note'] * $row['module']['Physique']['cof']
+ $row['module']['Langue']['note'] * $row['module']['Langue']['cof']
$cofSum = $row['module']['Math']['cof'] + $row['module']['Physique']['cof'] + $row['module']['Langue']['cof'];
$moyenne = $gradeSum / $cofSum;

PhP howto sizeof(JSON:array[])

I have a bug in my code but the solution is buried deep in a JSON return
https://api.instagram.com/v1/users/self/media/liked?access_token=207436640.c57b856.b0a8944d1e0c4e70a6ec581679c656b5
There are array[17] I must loop through
foreach ($arr['data'][0]['likes']['data'] as $liker){
echo '<img src="'.$liker['profile_picture'].'" /></br>';
echo '<p> '.$liker['username'].'</p></br>';
}
Works fine for one, but
for($i = 0; $i < sizeof($arr['data'][]); $i++){
echo '<img src="'.$arr['likes']['data']['profile_picture'].'" /></br>';
echo '<p> '.$liker['username'].'</p></br>';
}
has less than desirable results.
Fatal error: Cannot use [] for reading in /var/www/localhost/htdocs/instagram2.php on line 68
or if I remove the [], I get 'undefined 'likes'.
How do I properly loop through a JSON subarray?
You way of approaching the for compared to the foreach is wrong. In the foreach the current item during the iteration is automatically assigned to $liker, however nothing like this occurs in the for. You are only incrementing the value of $i.
/// #shaddy has said, this is the correct way to access the array size
/// it is more optimal to calculate it outside of the loop.
$len = sizeof($arr['data']);
/// with a for loop, you have to use $i to calculate the item
for($i = 0; $i < $len; $i++){
$item = $arr['data'][$i];
/// and then access each of the subitems inside $item
...
}
But you also have other problems. You are seemingly trying to output the image of each of the profile_pictures for the likers; but this is also an array of data. In your first example you are directly stepping through this array, so everything works. In your second however you are only looping the container array, and not the list of likers. To get this to work you must have a second loop:
$len = sizeof($arr['data']);
/// with a for loop, you have to use $i to calculate the item
for($i = 0; $i < $len; $i++){
$item = $arr['data'][$i];
/// best to check for existence before accessing to avoid errors
if ( !empty($item['likes']['data']) ) {
$likers = $item['likes']['data'];
$len2 = sizeof($likers);
/// step each of the likers
for($k = 0; $k < $len2; $k++){
$liker = $likers[$k];
if ( !empty($liker['profile_picture']) ) {
echo '<img src="'.$liker['profile_picture'].'" /></br>';
}
/// the username field is also part of the user array inside item
if ( !empty($liker['username']) ) {
echo '<p> '.$liker['username'].'</p></br>';
}
}
}
}
However the above all looks quite complicated, I usually don't use for loops in php, foreach has a much nicer interface to work with, and is designed to work with arrays:
foreach ( $arr['data'] as $i => $item ) {
if ( !empty($item['likes']['data']) ) {
foreach ( $item['likes']['data'] as $k => $liker ) {
if ( !empty($liker['profile_picture']) ) {
echo '<img src="' . $liker['profile_picture'] . '" /></br>';
}
if ( !empty($liker['username']) ) {
echo '<p> ' . $liker['username'] . '</p></br>';
}
}
}
}
Of course you may just have been wanting to loop through the likers array just like in your first example, to do that with a for you just need:
$likers = $arr['data'][0]['likes']['data'];
$len = sizeof($likers);
for( $i = 0; $i < $len; $i++ ){
echo '<img src="' . $likers[$i]['profile_picture'] . '" /></br>';
echo '<p> ' $likers[$i]['username'] . '</p></br>';
}
please note:
There is also another caveat to be aware of, and this will cause some of the above snippets to fail if it is not true. All the above code is always working with arrays, and so the $arr array must only contain arrays. However your dataset shows a mixture of arrays and objects. When dealing with objects in PHP you need to use a different accessor.
As I am unable to see how you are loading your JSON it is difficult to advise, as depending on the manner objects can be converted into arrays. All your examples have been treating every part of your structure as an array, and that is why I have assumed the same in the above.
However the standard way would be to use json_decode which would/should preserve the array/object difference by default. This means where ever there is an object you will need to use $obj -> prop rather than $obj['prop'], so my preferred example above would look like this:
foreach ( $arr['data'] as $i => $item ) {
if ( !empty($item->likes['data']) ) {
foreach ( $item->likes['data'] as $k => $liker ) {
if ( !empty($liker->profile_picture) ) {
echo '<img src="' . $liker->profile_picture . '" /></br>';
}
if ( !empty($liker->username) ) {
echo '<p> ' . $liker->username . '</p></br>';
}
}
}
}
Also if you prefer working just with arrays, you could use something like this:
https://coderwall.com/p/8mmicq/php-convert-mixed-array-objects-recursively
Well $arr['data'][] is invalid way to reference the data value of the array the correct one is $arr['data']
for($i = 0; $i < sizeof($arr['data']); $i++){
foreach ($arr['data'][$i]['likes']['data'] as $liker) {
echo '<img src="'.$liker['profile_picture'].'" /></br>';
echo '<p> '.$liker['username'].'</p></br>';
}
}
You can read more about arrays here http://php.net/manual/en/language.types.array.php .

Remove Data from Variable if Input Fields contain Placeholder text

I'm using the following code to validate a 'set' of input fields. 4 fields per set (width/height/length/weight). If a set of my input fields are empty then it won't display that row of data in my final $all variable.
Here is a previous topic on the subject: Removing Data from Variable if Input Fields incomplete - PHP - this works great.
However, this time I am using "Placeholder" text (input field value attribute) and therefore I need my PHP to check whether that placeholder value exists.
Here is my Pseudo Code, however I'm unsure how to achieve with regular PHP:
if ((pNUM-VALUEheight = "Height (cm)" OR pNUM-VALUEwidth = "Width (cm)" OR pNUM-VALUElength = "Length (cm)" OR pNUM-VALUEweight = "Weight (kg)"))
Then
// Don't store in $all variable
Else
// Do store set of values in $all variable
End If
Here is my current PHP code:
...
$ierrors = array();
$all = '';
// Loop over the values 1 through 20
foreach( range( 1, 20) as $i)
{
// Create an array that stores all of the values for the current number
$values = array(
'p' . $i . 'height' => $_POST['p' . $i . 'height'],
'p' . $i . 'width' => $_POST['p' . $i . 'width'],
'p' . $i . 'length' => $_POST['p' . $i . 'length'],
'p' . $i . 'weight' => $_POST['p' . $i . 'weight']
);
// Assume all values are empty.
$allEmpty = true;
// Validate every value
foreach( $values as $key => $value)
{
if( empty($value))
$ierrors[] = "Value $key is not set";
else
$allEmpty = false;
// You can add more validation in here, such as:
if( !is_numeric( $value) )
$ierrors[] = "Value $key contains an invalid value '$value'";
}
// Join all of the values together to produce the desired output
if (!$allEmpty)
$all .= implode( '|', $values) . "\n\n";
}
...
Many thanks for any pointers here or please let me know if any clarity is needed.
Thank you
As you're using jQuery, I'd use a bit of JavaScript to clear the input fields on submit:
$('form').submit(function() {
$(this).find('input[type=text]').each(function() {
var domElement = $(this).get(0);
if (domElement.value == domElement.defaultValue) {
domElement.value = '';
}
});
});
Watch out for typos, didn't test.
You can then check in your PHP file for empty strings and don't have to explicitly state all the possible values (they might change slightly, after all):
if ($_POST['inputName'] == '')
OR
you could use a simple for loop:
for ($i = 0, $numFields = 20; $i <= $numFields; ++$i) {
if ($_POST['p' . $i . 'width'] != 'Width (cm)' && $_POST['p' . $i . 'height'] != 'Height (cm)') {
// add row to table
}
}
What about doing something like this with your HTML:
<input type="text" name="length[]">
<input type="text" name="width[]">
Then you can do something like this in PHP:
if(array_keys($_POST['length']) != array_keys($_POST['width']))
{
// Incomplete post
}
$all_keys = array_merge(array_keys($_POST['length']), array_keys($_POST['width']));
foreach($all_keys as $curr_key)
{
// $_POST['length'][$curr_key]
// $_POST['width'][$curr_key]
}
While using JS is good to validate information from the client before submission. You should always check your values server side as well.

Help with PHP loop

Suppose I have a multi-dimensional array of the form:
array
(
array('Set_ID' => 1, 'Item_ID' => 17, 'Item_Name' = 'Whatever'),
array('Set_ID' => 1, 'Item_ID' => 18, 'Item_Name' = 'Blah'),
array('Set_ID' => 2, 'Item_ID' => 19, 'Item_Name' = 'Yo')
)
The array has more sub-arrays, but that's the basic form-- Items in Sets.
How can I loop through this array so that I can echo the number of items in each set along with the all the items like so:
Set 1 has 2 Items: 17: Whatever and 18: Blah
Set 2 has 1 Items: 19: Yo
I'm aware that this could be done with two loops-- one to build an array, and another to loop through that array. However, I'd like to do this all with only one loop.
In your answer, you should assume that there are two display functions
display_set($id, $count) //echo's "Set $id has $count Items"
display_item($id, $name) //echo's "$id: $name"
UPDATE: Forgot to mention that the data is sorted by Set_ID because its from SQL
Right, all the examples below rely on an ordered set, the OP states it is ordered initially, but if needed a sort function could be:
// Sort set in to order
usort($displaySet,
create_function('$a,$b',
'return ($a['Set_ID'] == $b['Set_ID']
? ($a['Set_ID'] == $b['Item_ID']
? 0
: ($a['Item_ID'] < $b['Item_ID']
? -1
: 1))
: ($a['Set_ID'] < $b['Set_ID'] ? -1 : 1));'));
Straight example using a single loop:
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item display for later
ob_start();
display_item($cItem['Item_ID'], $cItem['Item_Name');
$cSetEntries[] = ob_get_clean();
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
Using a recursive function it could be something like this:
// Define recursive display function
function displayItemList($itemList) {
if (!empty($itemList)) {
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name');
if (!empty($itemList)) {
echo " and ";
}
}
displayItemList($itemList);
}
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item for later
$cSetEntries[] = $cItem;
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
Amusingly, it can be one single recursive function:
function displaySetList($setList, $itemList = NULL) {
// First call, start process
if ($itemList === NULL) {
$itemList = array(array_shift($setList));
displaySetList($setList, $itemList);
return;
}
// Check for display item list mode
if ($setList === false) {
// Output first entry in the list
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name']);
if (!empty($itemList)) {
// Output the next
echo " and ";
displaySetList(false, $itemList);
} else {
echo "\n";
}
return;
}
if (empty($setList) || $setList[0]['Set_ID'] != $itemList[0]['Set_ID']) {
// New Set detected, output set
display_set($itemList[0]['Set_ID'], count($itemList));
echo ": ";
displaySetList(false, $itemList);
$itemList = array();
}
// Add next item and carry on
$itemList[] = array_shift($setList);
displaySetList($setList, $itemList);
}
// Execute the function
displaySetList($displaySet);
Note that the recursive example here is grossly inefficient, a double loop is by far the quickest.
<?php
$sets = array();
foreach ($items as $item)
{
if (!array_key_exists($item['Set_ID'], $sets))
{
$sets[$item['Set_ID']] = array();
}
$sets[$item['Set_ID']][] = $item;
}
foreach ($sets as $setID => $items)
{
echo 'Set ' . $setID . ' has ' . count($items) . ' Items: ';
foreach ($items as $item)
{
echo $item['Item_ID'] . ' ' . $item['Item_Name'];
}
}
?>
Something like this i guess?
EDIT:
After i posted this i saw the display functions where added. But you get the point.
The need to not print out any items until we know how many there are in the set makes this difficult. At some point, we'll need to doing some buffering, or else backtracking. However, if I'm allowed internal loops, and sets are contiguous in the "master" array, then with some hacking around:
$set = 0;
$items;
foreach ($arr as $a) {
if ($a['Set_ID'] != $set) {
if ($set != 0) {
display_set($set, count($items));
foreach ($items as $i)
display_item($i)
}
$set = $a['Set_ID'];
$items = array();
}
$items[] = $a;
}
How about this:
$previous_set = false;
$items = '';
$item_count = 0;
foreach ($rows as $row)
{
if ($row['Set_ID'] != $previous_set)
{
if ($previous_set)
{
echo display_set($row['Set_ID'], $item_count);
echo $items;
}
$previous_class = $row['Set_ID'];
$item_count = 0;
$items = '';
}
$items .= display_item($row['Item_ID'], $row['Title']);
$item_count++;
}
echo display_set($row['Set_ID'], $item_count);
echo $items;

Categories