Loop through form values from a dynamic php form - php

I building on top of an existing PHP based application to ability to update menu items name and prices.
I have generated a dynamic form which is populated with the results form the database. The idea is that the user can update the item name or price to update the information in the database.
The form works fine, but I am having dome trouble getting the info out of the form. each Item has a separate ID so I need to essentially do a foreach through the form and call the update function each time with the respective item id.
I can handle the DB side of things fine, but the application I am building on has a 'getInput' function to check input exists and to get the input form the form and I would like to use this.
This is the getInput function:
public static function exists($type = 'post') {
switch($type) {
case 'post':
return (!empty($_POST)) ? true : false;
break;
case 'get';
return (!empty($_GET)) ? true : false;
break;
default:
return false;
break;
}
}
public static function get($item) {
if(isset($_POST[$item])) {
return $_POST[$item];
} else if(isset($_GET[$item])) {
return $_GET[$item];
}
return '';
}
}
The problem I have is when calling this function it only returns the last item form the form. Is there a way i can iterate though the form and get each item?
This is the dynamic form and the getInput code so far:
$menuItems = DB::getInstance()->get('menu_items', array('cat_id', '=', $cat_id ));
if($menuItems->count()) {
echo '<form class="updateMenu" action="" method="post">';
echo '<table class="gridtable gridtableMenu">';
echo '<tr><th>Item Name</th><th>Item Price</th></tr>';
foreach($menuItems->results() as $item) {
echo '<tr>';
echo '<td class="menu-name"><input type="text" name="itemName" value="' . $item->item_name . '" required></td>';
echo '<td class="menu-price"><input type="number" step="any" name="itemPrice" value="' . $item->item_price . '" required></td>';
echo '<input type="hidden" name="id" value="' . $item->id . '">';
echo '</tr>';
}
echo '</table>';
echo '<input type="submit" name="updateMneu" value="Update Menu">';
echo '</form>';
} else {
echo '<div class="error">No items have been added to this menu</div>';
}
} // close categories foreach
} // close if category set
if(isset($_POST['updateMneu'])) {
echo Input::get('id'), '</br>';
echo Input::get('itemName'), '</br>';
echo Input::get('itemPrice'), '</br>';
} //close if isset updateMenu If
So I would like a foreach I think around this section:
if(isset($_POST['updateMneu'])) {
echo Input::get('id'), '</br>';
echo Input::get('itemName'), '</br>';
echo Input::get('itemPrice'), '</br>';
//update ite in the database, and move to gthe next item.
} //close if isset updateMenu If
I will handle data validation and what not later on.

As posted by 'noobHere' the answer was to set the input types name as arrays. e.g. name="itemName[]" instead of name="itemName"

Related

jQuery If checkbox in foreach loop is checked, include checkboxes and input values within that loop

I am creating a php email form with a foreach loop which creates a checkbox with several other checkboxes and input fields within the foreach loop. The loop might repeat several times, creating several sets of checkboxes, however I only want to include the checked checkbox and associated fields, not all of those within every loop. Only those selected would then be included in the 'servicelist' array and email.php.
My code below is incorrect as it is gathering all of the data from every loop. I understand this is because the input fields are populated with data, so the data is added to the array.
I think I need to add an 'if' statement to my jQuery, but I'm not sure how? I have tried changing the jQuery line 'if (checkbox.is(":checked"))' with the below line of code without success.
if ($("input[data-name='servicetitle[]'").prop(":checked")) {
PHP Form:
foreach ( $order->get_items() as $item_id => $item ) {
// Main checkbox to check if selected
echo '<div data-name="sup-checkbox-title[]">';
echo '<label for="servicetitle">Service:</label><br>';
echo '<input type="checkbox" id="servicetitle" data-name="servicetitle[]" value="' . $item->get_name() . '"><span>' . $item->get_name() .'</span><br>';
echo '</div><br>';
// Sub checkboxes and input fields to include in array if above checkbox checked
echo '<div data-name="sup-input[]"><br>';
echo '<label for="weightallowance">Weight Allowance Per Bin:</label><br>';
echo '<input type="text" id="weightallowance" value="Weight1" ><br>';
echo '</div><br>';
echo '<div data-name="sup-input-date[]">';
echo '<label for="servicestartdate">Service Start Date:</label><br>';
echo '<input type="date" id="servicestartdate" class="sup-required"><br>';
echo '</div><br>';
echo '<div data-name="sup-checkbox[]">';
echo '<label for="routenumberAln1">Route Number:</label><br>';
echo '<input type="checkbox" id="routenumberAln1" value="Aln1" >Aln1<br>';
echo '</div><br>';
echo '<div data-name="sup-input-costs[]">';
echo '<label for="supplierpriceperlift">Supplier Price Per Lift:</label><br>';
echo '<input type="text" id="supplierpriceperlift" value="£16.75"><br>';
echo '</div><br>';
}
echo '<div name="submit" class="button btnAction" onClick="sendSupplierForm();">Send Email</div>';
jQuery:
function sendSupplierForm() {
let values = [];
$("div[data-name='sup-checkbox-title[]'], div[data-name='sup-input[]'], div[data-name='sup-input-date[]'], div[data-name='sup-checkbox[]'], div[data-name='sup-input-costs[]']").each(function() {
const label = $(this).find('label');
const checkbox = $(this).find('input[type="checkbox"]');
const input = $(this).find('input[type="text"]');
const date = $(this).find('input[type="date"]');
if (checkbox.is(":checked")) {
values.push(label.html(), checkbox.val());
}
if (input.val()) {
values.push(label.html(), input.val());
}
if (date.val()) {
values.push(label.html(), date.val());
}
});
var data = {
servicelist: values,
};
jQuery.ajax({
url: "email.php",
data: data,
dataType:'text',
type: "POST",
success:function(data){
$("#EmailStatus").html(data);
},
error:function (){}
});
}
email.php
$mailto = "info#******.com";
$subject = "Test";
$headers = "From: info#******.com\nMIME-Version: 1.0\nContent-Type: text/html; charset=utf-8\n";
$serviceinfo = implode("<br>",array_map(function($i){
return implode(" ",$i);
},array_chunk($_POST['servicelist'],2)));
$message = "
<html>
<head>
<title>Form Details</title>
</head>
<body>
<p>" . $serviceinfo . "</p>
</body>
</html>
";
// PHP MAILER FUNCTION
$result1 = mail($mailto, $subject, $message, $headers);
// PHP MAILER MESSAGE
if ($result1) {
print "<div id='EmailStatusSuccess'>SUCCESS!!! The details have been sent.</div><br>";
} else {
print "<div id='EmailStatusFail'>ERROR... Sorry there is a problem sending the details. Please check and retry.</div><br>";
}
-----------------------------------------
EDIT: SOLUTION
-----------------------------------------
Thanks to the answer from #knetsi, I was able to create the following code which fixed my issue. Basically the code looks for a div with the class of ".service-row-items" and then looks for all checkboxes named "servicelist[]". All labels & inputs (text, date, checkbox etc) are then gathered and used in the array.
let values = [];
$(".service-row-items").each(function() {
const checkboxtitle = $(this).find('input[name="servicelist[]"]');
if (!checkboxtitle.is(":checked")) {
return;
}
$(this).find("span").each(function(){
const label = $(this).find('label');
const checkbox = $(this).find('input[type="checkbox"]');
const input = $(this).find('input[type="text"]');
const date = $(this).find('input[type="date"]');
const number = $(this).find('input[type="number"]');
const textarea = $(this).find('textarea');
if (checkbox.is(":checked")) {
values.push(label.html(), checkbox.val());
}
if (input.val()) {
values.push(label.html(), input.val());
}
if (date.val()) {
values.push(label.html(), date.val());
}
if (number.val()) {
values.push(label.html(), number.val());
}
if (textarea.val()) {
values.push(label.html(), textarea.val());
}
});
})
I would suggest having unique IDs for your inputs. But with small adaptation to your code you can achieve what you want. Even though would be nice to know what your end goal is so we could guide you to a better solution.
to begin with you can wrap each group of inputs under a single <div> let's call it <div class='row-item'>
foreach ( $order->get_items() as $item_id => $item ) {
echo '<div class="row-item">';
.... // rest of the code
echo '</div>';
}
then you could use a similar to this jQuery code
let values = [];
$(".row-item").each(function() {
const checkbox = $(this).find('input[type="checkbox"]');
if (!checkbox.is(":checked")) {
return;
}
$(this).find("div").each(function(){
const val = $(this).find("input").val();
if (!val){
return;
}
values.push($(this).find("label").html(), val);
});
what does this code do?
It loops through the newly added div then find the checkbox in that div and skips the processing if the checkbox is not checked.
Then I noticed that what you tried to do is to basically push in an array the combination of label and value. So you could simply go through each <div> element under the .row-item and add the label and val combinations.
I also created a small example for you in JSFiddle that has hardcoded the HTML instead of the PHP code.
https://jsfiddle.net/yjLqseax/5/
You must utilize the unique id of each item.
Below is the code (I used test data):
<?php
$data = array(
1 => array(
'name' => 'Jack'
),
2 => array(
'name' => 'John'
),
3 => array(
'name' => 'Josh'
),
);
foreach ( $data as $item_id => $item ) {
echo "-----------------------------------------------------------------";
// set the id of this item
echo '<div data-name="sup-checkbox-ids[]">';
echo '<input type="hidden" name="item_id" value="'.$item_id.'" >';
echo '</div>';
// Main checkbox to check if selected
echo '<div data-name="sup-checkbox-title[]">';
echo '<label for="servicetitle">Service:</label><br>';
echo '<input type="checkbox" id="servicetitle_'.$item_id.'" data-name="servicetitle[]" value="' . $item['name'] . '"><span>' . $item['name'] .'</span><br>';
echo '</div><br>';
// Sub checkboxes and input fields to include in array if above checkbox checked
echo '<div data-name="sup-input[]"><br>';
echo '<label for="weightallowance">Weight Allowance Per Bin:</label><br>';
echo '<input type="text" id="weightallowance" value="Weight1" ><br>';
echo '</div><br>';
echo '<div data-name="sup-input-date[]">';
echo '<label for="servicestartdate">Service Start Date:</label><br>';
echo '<input type="date" id="servicestartdate" class="sup-required"><br>';
echo '</div><br>';
echo '<div data-name="sup-checkbox[]">';
echo '<label for="routenumberAln1">Route Number:</label><br>';
echo '<input type="checkbox" id="routenumberAln1" value="Aln1" >Aln1<br>';
echo '</div><br>';
echo '<div data-name="sup-input-costs[]">';
echo '<label for="supplierpriceperlift">Supplier Price Per Lift:</label><br>';
echo '<input type="text" id="supplierpriceperlift" value="£16.75"><br>';
echo '</div><br>';
}
?>
<button id="select_values">Select values<button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
let values = [];
$("#select_values").click(function(){
var current_id = 0
$("div[data-name='sup-checkbox-ids[]'], div[data-name='sup-checkbox-title[]'], div[data-name='sup-input[]'], div[data-name='sup-input-date[]'], div[data-name='sup-checkbox[]'], div[data-name='sup-input-costs[]']").each(function() {
const id = $(this).find('input[name="item_id"]');
const label = $(this).find('label');
const checkbox = $(this).find('input[type="checkbox"]');
const input = $(this).find('input[type="text"]');
const date = $(this).find('input[type="date"]');
if(id.val()){
console.log('Current id is:'+id.val());
current_id = id.val();
}
if($('#servicetitle_'+current_id).is(':checked')){
if (checkbox.is(":checked")) {
values.push(label.html(), checkbox.val());
}
if (input.val()) {
values.push(label.html(), input.val());
}
if (date.val()) {
values.push(label.html(), date.val());
}
}
});
console.log(values); // Print the selected values, based upon the checkbox
values = []; // empty values
})
</script>
I hope it helps.

form does not get through POST

$product = '';
$stmt = $verbinding->query("SELECT
product_category, product_id, parent FROM
Productcategory ORDER BY product_category");
$categorien = $stmt->fetchAll();
foreach($categorien as $cats){
if($cats['parent'] === $producten){
echo '<form action="product-list.php" method="post">
<input type="submit" name="cats" value="'. $cats['product_category'] .'"></form>';
echo $producten;
//var_dump($_POST);
if(isset($_POST['cats'])){
echo $_POST['cats'];
echo $cats['product_category'];
echo $cats['product_id'];
if($_POST['cats'] === $cats['product_category']){
$product = $cats['product_id'];
echo $product;
echo "gelukt!!";
}
}
}
}
So to update my question this is code that does partly work but does not get past the if($_POST['cats'] === $cats['product_id']){ statement. The problem is that my $_POST['cats'] just sends NO information. I can't understand why though. I should say though that I use the same "name" value in another form, but if I don't it wont even go through the if(isset($_POST['cats'])){ statement.
From your form the action page is "product-list.php", is it the same page you are handling the form logic in?
If not then your you need to write the code below in the product-list.php you created.
....
if(isset($_POST['categorien'])){
echo "pastcategory?";
if($_POST['categorien'] === $cat['product_category']){
$producten = $cat['product_id'];
echo "pastcategory!!!!";
echo $producten;
}
}
....

Checkbox removing listing in a random way

I have a list of favorite cars which i have added to each favorite car a checkbox for letting the user to remove the favorite car from his favorite car list. The problem is that the checkbox is working in a different way: If I check any car (1st, second.. last or multiple cars) and after hit submit the car that will get removed is the last one added instead of removing the selected one. If I check multiple cars, happens same thing, removes only the last car added.
PHP
public function GetFavoriteCars() {
include("inc/membersite_config.php");
$email = $fgmembersite->UserEmail(); // this is how I take the e-mail of the
global $base_path;
$FavoriteCars = $this->QueryResult("SELECT * FROM favoritecar WHERE email='$email'");
if (count($FavoriteCars)) {
$mystring='http://';
echo '<form action="" class="deletebutton" method="post">';
echo '<input type="submit" name="deletebtn" id="deletebtn" value="Submit">';
echo '<div class="roster_slideri-login">';
foreach ($FavoriteCars as $FavoriteCar) {
$carlink = $FavoriteCar->favoritecarlink;
echo '<div class="car-info-col-login">';
echo '<input type="checkbox" name="checkbox" value="'.$carlink.'" class="checkbox-login">';
$val=strpos($FavoriteCar->favoritecarimg,$mystring);
if ($val !== false) {
if($FavoriteCar->favoritecarimg!='') {
echo '<a href="'.$base_path.'detail-page_'.$FavoriteCar->favoritecarlink.'">';
echo '<img src="'.$FavoriteCar->favoritecarimg.'" alt="'.$FavoriteCar->favoritecartitle.'" width="160" height="120" />';
echo '</a>';
echo '<div class="name">'.substr($FavoriteCar->favoritecartitle,0,20).'</div>';
echo '</div>'; //car-info-col-login
}
} else {
echo '<a href="'.$base_path.'detail-page_'.$FavoriteCar->favoritecarlink.'">';
echo '<img src="'.$base_path.'uploads/no-img.jpg" alt="'.$FavoriteCar->favoritecartitle.'" width="160" height="120" />';
echo '</a>';
echo '<div class="name">'.substr($FavoriteCar->favoritecartitle,0,20).'</div>';
echo '</div>';
}
}
echo '</form>';
if (isset($_POST["checkbox"])) {
$this->QueryResult("DELETE from favoritecar WHERE email='$email' AND favoritecarlink='$carlink'");
echo '<script type="text/javascript">alert("Car had been deleted");</script>';
}
echo '</div>'; // div roster_slideri-login
}
}
Explaning:
$email = $fgmembersite->UserEmail(); - this is how I take the e-mail of the current logged in user. It will echo "email_of_logged_in_user#domain.com"
QueryResult is a custom function that looks like this. I usually use it for SELECTING purposes but it seams that is working for deleting purposes too.
abstract class DBDetails {
protected $link = NULL;
protected function connector() {
global $DBHOSTNAME;
global $DBUSERNAME;
global $DBPASSWORD;
global $DBNAME;
$this->link = mysqli_connect($DBHOSTNAME, $DBUSERNAME, $DBPASSWORD, $DBNAME) or die("Can't connect to MySQL server on localhost");
}
protected function close() {
mysqli_close($this->link);
}
}
abstract class N2 extends DBDetails {
public function QueryResult($strQuery) {
$this->connector();
$query = mysqli_query($this->link, $strQuery);
$arr = array();
if ($query) {
while ($result = mysqli_fetch_object($query)) {
array_push($arr, $result);
}
}
$this->close();
return $arr;
}
}
Expected output
When I check the checkbox of a car, it should delete only that car. If I check the checkboxes of multiple cars, should delete the specific cars that I checked.
Please help, I am quite a noob in checkboxes. I have checked lots of questions from here, but did not find my answer.
In this line :
echo '<input type="checkbox" name="checkbox" value="'.$carlink.'" class="checkbox-login">';
--------------
When using multiple checkboxes with same name , you would need to include [] in the name :
echo '<input type="checkbox" name="checkbox[]" value="'.$carlink.'" class="checkbox-login">';
----------------
Then $_POST["checkbox"] will be an array and you can use foreach on it to get all the checked values .
if( isset( $_POST["checkbox"] ) )
{
foreach( $_POST["checkbox"] as $value )
{
/* $value contains $carlink */
echo $value; // For test purpose
/* Sanitize and use it to identify and delete the corresponding row */
}
}
( Rather than name="checkbox[]" it might be better to choose another name . )

multiple forms handled by one script php

I try to create an order page on php. I have created a form which stores data into the database. The form number is based on the user and it is created dynamic.
<?php
if(isset($_POST['submit_num']))
{
$number=$_POST['sky'];
for($i=0;$i<$number;$i++)
{
$item = $_SESSION['item'];
echo $item;
$rec_query = "SELECT * FROM ylika";
$rec_result= mysql_query($rec_query) or die("my eroors");
echo '<form action="user_order_form.php" method="POST">';
echo '<html>';
while($row_rec = mysql_fetch_array($rec_result))
{
echo '<input type="checkbox" name="yliko[]" value='.$row_rec['onoma'].'> '.$row_rec['onoma'].'';
echo '<br>';
}
echo '<br>';
echo '<input type="submit" name="submit" value="ORDER">';
echo '</form>';
}
}
?>
So I have many forms and 1 script to handle them. If I submit 1 form then it applies the data to the database but the other forms dissapear. This is the second php 'handler'.
<?php
if (isset($_POST['submit']))
{
$max_id = "SELECT MAX(id_order) FROM id_of_orders";
$x=mysql_query($max_id) or die("my eroors");
$id= mysql_fetch_array($x);
$xyz = $id['MAX(id_order)'];
$item = $_SESSION['item'];
$temp = $_POST['yliko'];
$temp2 = implode(",", $temp);
$inserts = ("INSERT INTO orders (order_id,product,ulika) VALUES ('$xyz' , '$item','$temp2')");
$inc_prod=("UPDATE proion SET Counter = Counter + 1 WHERE proion.onomasia='$item'");
mysql_query($inserts) or die(mysql_error());
mysql_query($inc_prod) or die(mysql_error());
}
?>
I want to submit all the forms. Should I try to create one submit button for all of the forms or is there a way to handle all of them separately ?
You can have many submit forms, but simply define one big <form> with all of them, then you will not lose any information.
<?php
if(isset($_POST['submit_num']))
{
$number=$_POST['sky'];
echo '<form action="user_order_form.php" method="POST">';
for($i=0;$i<$number;$i++)
{
$item = $_SESSION['item'];
echo $item;
$rec_query = "SELECT * FROM ylika";
$rec_result= mysql_query($rec_query) or die("my eroors");
echo '<html>';
while($row_rec = mysql_fetch_array($rec_result))
{
echo '<input type="checkbox" name="yliko[]" value='.$row_rec['onoma'].'> '.$row_rec['onoma'].'';
echo '<br>';
}
echo '<br>';
echo '<input type="submit" name="submit" value="ORDER">';
}
echo '</form>';
}
?>
now you can also add the ~$i~ identifier to input names, so you can easily distinguish which is which.

CodeIgniter appending to the beginning of the view when it shouldn't be

When I call regularDashboard(), it appends to the beginning of my view. In my view I'm calling $reg from inside a formatted style. So it shouldn't be echoing out at the beginning of the view... Any ideas as to why this is happening?
public function dcr() {
// pass all dashboard accesses through this function
$username = $this->session->userdata("username");
$query = $this->db->get_where('users', array('username' => $username));
$userType = $this->session->userdata('userType');
if ($userType == 'regular') {
foreach ($query->result() as $row) {
$data = array('reg' => $this->regularDashboard(), 'firstname' => $row->firstname);
$this->load->view('dashboard', $data);
} public function regularDashboard () {
$userid = $this->session->userdata('userid');
$results = $this->db->query("SELECT * FROM users");
foreach ($results->result() as $row) {
if($userid != $row->userid) {
echo $row->firstname . " " . $row->lastname;
echo "<form method='GET' action='processing/lib/process-send-friend-request.php?'>";
echo '<input name="accepted" type="submit" value="Send User Request" /><br />';
echo '<input name="AddedMessage" placeholder="Add a message?" type="textbox" />';
echo '<br>Select Friend Type: ' . '<br />Full: ';
echo '<input name="full_friend" type="checkbox"';
echo '<input type="hidden" name="id" value="' . $row->idusers . '" />';
echo '</form>';
echo "<br /><hr />";
} elseif ($userid == $row->userid) {
echo $row->firstname . " " . $row->lastname;
echo "<br />";
echo "You all are currently friends";
}
}
}
Views are buffered. When you echo something directly in a controller, it is sent before the buffer is flushed (therefore before the output containing the view is sent to the browser), that's why it appears before anything.
You shouldn't to this (sending a direct output/echoing something outside of views), you risk getting into troubles as soon as you use anything related to headers (redirect, cookies, CI's sessions...)
UPDATE:
To fix it, just assign all those string to a variable (as jeff showed), and send that to the view:
$data['form'] = $row->firstname . " " . $row->lastname;
$data['form'] .= "<form method='GET' action='processing/lib/process-send-friend-request.php?'>";
$this->load->view('formview',$data);
There, you just echo $form and you'll have all your strings output correctly.
EDIT :
all above if you're inside a Controller. If you're in a Model, just assign everything to a variable and return it to the Controller:
function regularDashboard()
{
$form = $row->firstname . " " . $row->lastname;
$form .= "<form method='GET' action='processing/lib/process-send-friend-request.php?'>";
return $form;
}
In the controller:
$data['form'] = $this->model->regularDashboard();
$this->load->view('formview',$data);
If you allow me, I'd suggest writing the form directly into the view, without the hassle (and the structural error) of creating something that's supposed to be "presentation" outdside of views.
It seems that your issue is the use of echo from within regularDashboard(). Try setting a variable that contains the form markup and return it instead of using echo.
Here is an example:
function regularDashboard()
{
$html = "";
$html .= "<form>";
//Append the rest of the form markup here
return $html;
}

Categories