How to count a dynamic HTML form input array with PHP? - php

I have a button on a page that when a user pushes it, it creates another "Contact" field on the page. The Contact field allows them to add a new contact to their profile. Also, they can click the button as many times as they want, and it will create that many "Contact" fields.
The problem though is that I am having a hard time figuring how many "Contact" fileds have been added. Here is some HTML that is generated when the button is clicked:
<div class="item">
<label for="in-1v">First Name <span>*</span></label>
<div class="text">
<input type="text" id="in-1-0" name="member[0][fname]" value="" />
</div>
</div>
<div class="item">
<label for="in-2-0">Last Name <span>*</span></label>
<div class="text">
<input type="text" id="in-2-0" name="member[0][lname]" value="" />
</div>
</div>
Each time the button is clicked, name="member[0][lname]" will become name="member[1][lname]" and will continue to increment each time the button is clicked. As stated earlier, the user can do this as many times as they want on the page.
I am using PHP to loop through the multidimensional array:
$array = $_POST['member'] ;
foreach($array as $array_element) {
$fname = $array_element['fname'];
$lname = $array_element['lname'];
}
How can I use PHP to determine how many fileds have been added so I can loop through them?
Any help is greatly appreciated!

You can simply get a count like so:
$count = count($_POST['member']);
You could also then modify your loop to look like this:
// First check to see if member is set and is a valid array
if (!empty($_POST['member']) && is_array($_POST['member'])) {
$count = count($_POST['member']);
for ($i = 0; $i < $count; $i++) {
$fname = $_POST['member'][$i]['fname'];
$lname = $_POST['member'][$i]['lname'];
}
}

Related

Last user input keeps overwriting previous input in PHP array

I tried to word the question as best as I could. I'm trying to create a web app that lists a few animals and then allows the user to add more to the list. That part is working just fine, however, I need the list to keep growing. What's happening right now is every time I put in a new input, the last one is overwritten.
For example, if I add "Tiger Shark" first and then add "Dolphin", "Tiger Shark" is completely replaced by "Dolphin" instead of "Dolphin" listing beneath "Tiger Shark". How do I prevent this from happening and ensure that each user input is listed beneath the previous one?
Edited for clarification, if needed: I'm doing this via an HTML form.
Here's my PHP code:
<?php
$animal = array("Killer Whale", "Great White Shark", "Eel");
if (isset($_POST['add']))
{
$add = array($_POST['animal']);
$animal = array_merge($animal, $add);
}
foreach($animal as $a){
echo "<li>$a</li>";
}
?>
And here is my HTML Form code:
<form method="post" action="Yarbrough_Chapter6Project.php" class="form">
<div class="form__group">
<input type="text" name="animal" class="form__input" placeholder="Favorite Sea Animal">
<label for="animal" class="form__label">Favorite Sea Animal</label>
</div>
<div class="form__group">
<input type="submit" name="add" class="btn btn--blue" value="Add An Animal">
</div>
</form>
You can just add the element to the array using [].
$animal[] = new_element will always add the new_element to the end of the array.
<?php
$animal = array("Killer Whale", "Great White Shark", "Eel");
if (isset($_POST['add']))
{
$add = $_POST['animal'];
$animal [] = $add;
}
foreach($animal as $a){
echo "<li>$a</li>";
}
?>

How best to format radio button array and capture in $_POST

I'm really struggling with an RSVP form I'm trying to set-up and any help would be great!
I have this form so far http://adrianandemma.com/ which I am trying to get to send me a simple email once submitted.
The form has a 'Name' field and a radio button for 'Attending - Yes/No'.
I then have some JS whereby you can clone these fields to RSVP for more than one guest at a time.
The 'Name' fields are passing through fine as an array and coming through by email, as I can just set the name attribute of the input to name="name[]", but I'm having trouble with the radio buttons.
I can't leave the 'name' attribute the same for the cloned radio buttons, because if I do I can only select yes/no for one cloned row, as all the cloned radios have the same name, so I have added a bit of JS to try to amend the name of any cloned radios to 'coming[1], coming[2], etc'.
I can't quite get this to work though, as every time I submit the form the radio button values appear to come through blank.
Can anybody advise the best approach to setting up radio buttons as an array and to carry them through via $_POST and ultimately an email script?
Here's my HTML form:
<?php
if(#$_REQUEST['submit'] == '1') {
include('assets/forms/rsvp.php');
}
?>
<form action="?" method="post">
<?php if(#$errors) :?>
<p class="errors"><?php echo $errors; ?></p>
<?php endif; ?>
<input type="hidden" name="submit" value="1" />
<div class="form-row">
<div class="field-l">
<p>Name</p>
</div>
<div class="field-r">
<p>Attending?</p>
</div>
</div>
<div class="form-row guest">
<div class="field-l">
<input type="text" name="name[]" id="name" value="<?php echo htmlspecialchars(#$_REQUEST['name']); ?>" tabindex="1" />
</div>
<div class="field-r">
<input type="radio" name="coming" id="coming-yes" class="coming-yes" value="Yes"><label for="coming-yes">Yes</label><input type="radio" name="coming" id="coming-no" class="coming-no" value="No"><label for="coming-no">No</label>
</div>
</div>
<a class="addguest" href="#">Add further guest</a>
<div class="form-row">
<button type="submit" id="rsvp-submit" tabindex="2">Submit RSVP</button>
</div>
</form>
Hers My Form Process code:
<?php
$name = $_POST['name'];
$coming = $_POST['coming'];
$errors = "";
if(!#$_POST['name']) { $errors .= "Please enter your name.<br/>\n"; }
if(!#$_POST['coming']) { $errors .= "Please enter yes or no for attending.<br/>\n"; }
if(#$_POST['emailaddress'] != '') { $spam = '1'; }
if (!$errors && #$spam != '1')
{
$to = "xxx#example.com";
$subject = "Wedding RSVP";
$headers = "From: noreply#adrianandemma.com";
$body = "The following RSVP has been sent via the website.\n\n";
for($i=0; $i < count($_POST['name']); $i++) {
$body .= "
Name ".($i+1)." : " . $_POST['name'][$i] . "\n
Coming ".($i+1)." : " . $_POST['coming'][$i] ."\n\n";
}
$body .= "\n\nDate Received: " . date("j F Y, g:i a") . "\n";
mail($to,$subject,$body,$headers);
}
?>
Here's my JS:
$(document).ready(function() {
$('.addguest').on('click', function(e) {
e.preventDefault();
//
// get the current number of ele and increment it
//
var i = $('.guest').length + 1;
$('.guest').first().clone().find("input").attr('id', function(idx, attrVal) {
return attrVal + i; // change the id
});
$('.guest').first().clone().find("input[type=radio]").attr('id', function(idx, attrVal) {
return attrVal + i; // change the id
}).attr('name', function(idx, attrVal) {
return attrVal+'['+i+']'; // change the name
}).val('').end().find('label').attr('for', function(idx, attrVal) {
return attrVal + i; // change the for
}).end().insertBefore(this);
});
});
Here's an example of what I'm receiving by email currently, names come through fine, but radio values for 'Coming Yes/No" are all blank:
The following RSVP has been sent via the website.
Name 1 : John Doe
Coming 1 :
Name 2 : Ann Doe
Coming 2 :
Name 3 : Fred Doe
Coming 3 :
Date Received: 19 April 2017, 1:04 am
Honestly, my best guess is that in the original row, the names of your radio inputs are simply "coming", without the brackets. I think that because there are no brackets on that name, it is clobbering the other ones of the same name that should behave as an array. In other words, PHP is getting two conflicting types for an input of the same name, and taking the string over the array.
Hard to say without testing it directly, and the fact that the input is referenced as an array in your PHP form handler and doesn't throw an error would tend to suggest to me I'm not quite right, but it may be worth a try.
Here's the change to the HTML I would try:
<div class="field-l">
<input type="text" name="name[0]" id="name" value="<?php echo htmlspecialchars(#$_REQUEST['name']); ?>" tabindex="1" />
</div>
<div class="field-r">
<input type="radio" name="coming[0]" id="coming-yes" class="coming-yes" value="Yes">
<label for="coming-yes">Yes</label>
<input type="radio" name="coming[0]" id="coming-no" class="coming-no" value="No">
<label for="coming-no">No</label>
</div>
Notice I specifically marked the first row as row zero, as PHP uses zero-indexed arrays.
This would then require some changes to your javascript. I've found it was easier to create an actual template for your row HTML and use that than to try and clone the first row each time and reset all the inputs and adjust the names. The way this works is you define your template HTML inside a script tag with an ID and a type that is non-standard. The browser ignores it, but JavaScript can access it just like any other element and we can pull the content out with jQuery's html() method.
Here's what I've come up with (including a fix of your indexing):
<!-- A script with a non-standard type is ignored by the browser -->
<!-- We can reference it by ID in our JS though, and pull out the HTML -->
<script id="guest-row-template" type="text/template">
<div class="form-row guest">
<div class="field-l">
<input type="text" name="" id="name" class="name-ipt" />
</div>
<div class="field-r">
<input type="radio" name="" id="" class="coming-yes coming-yes-ipt" value="Yes" />
<label for="" class="coming-yes coming-yes-label">Yes</label>
<input type="radio" name="" id="" class="coming-no coming-no-ipt" value="No" />
<label for="" class="coming-no coming-no-label">No</label>
</div>
</div>
</script>
<script type="text/javascript">
$(document).ready(function() {
$('.addguest').on('click', function(e) {
e.preventDefault();
//Get the number of rows we have already - this is the index of the *next* row
//If we have 1 row, the first row's index is 0 and so our next row's index should be
//1, which is also our length, no need to increment
var i = $('.guest').length;
//Get HTML template content for a single row
var row = $('#guest-row-template').html();
//Update the name attribute of the name input
row.find('.name-ipt').attr('name', 'name[' + i + ']');
//Update the name and id attributes of the yes radio button
row.find('.coming-yes-ipt').attr('name', 'coming[' + i + ']');
row.find('.coming-yes-ipt').attr('id', 'coming-yes-' + i);
//Update the name and id attributes of the no radio button
row.find('.coming-no-ipt').attr('name', 'coming[' + i + ']');
row.find('.coming-no-ipt').attr('id', 'coming-no-' + i);
//Update the for attribute of the yes label
row.find('.coming-yes-label').attr('for', 'coming-yes-' + i);
//Update the for attribute of the no label
row.find('.coming-no-label').attr('for', 'coming-no-' + i);
row.insertBefore(this);
});
});
</script>
Please note this is untested code. Of course I've gone through a few times to make sure I caught all my obvious bugs, but others may persist. Since I can't actively test it, I can't say it's entirely bug free. But, hopefully as pseudo-code it helps you resolve the issue.
EDIT 1
Just to clarify, you don't ordinarily have to manually provide the index values within the brackets of input names for PHP to interpret the input as an array and to automatically index the input in the appropriate order. I specifically set the first inputs to have use [0] because all the inputs after them will also need to specify index values in order for your radio buttons to work (I personally appreciate consistency), and because we need to be absolutely sure that the correct names are matched to the correct RSVP value (just trying to be thorough).

PHP - Insert elemens into an array

I'm working on a formular, but for the moment I just want to insert into an array my elements (I have books and authors).
I can display my books with author (name + surname) with the foreach, but I can't add more elements.
Here is the code with the form.
<H1>Exercice 2</H1>
<form method="POST">
<label for"code" >Number :</label>
<input id="code" name="code" type="number" />
<label for"title">Title :</label>
<input id="title" name="title" type="text" />
<label for"author" >Author :</label>
<input id="author" name="author" type="text" />
<button type="input" type="submit">Ok</button>
$title = $_POST['title'];
$code = $_POST['code'];
$author = $_POST['author'];
$book = array();
$book['code'] = 123;
$book['title'] = "Legendes";
$book['author'] = array("David", "Gemmel");
foreach($book as $value){
$book['key'] = $value;
var_dump($book);
if (is_array($value)) {
foreach($value as $otherValue) {
echo($otherValue);
}
} else {
echo($value);
}
}
I did some searcch, but I don't think it works, it's using the array_push() method with the POST, but I don't know where I can manipulate my form into the array.
If you want some details, I'll be happy to do that =) I'm working on it, if i have some news, you will know =)
Have a nice day =)
1) Assignments are in reverse. Correct way:
$myVar = $myValue
2) You need to set the name attribute in your inputs in order to be sent:
<input id="code" type="number" name="code" />
Then you can access them like:
$_POST['code']
3) To add an element by key in an array, use:
$array['key'] = $value;
Your Exercise 2 have some mistakes :
First, your HTML inputs must have the name attribute to be retrieved by post:
<h1>Exercice 2</h1>
<form method="post">
<label>
<input name="code" type="number" />
</label>
<button type="submit">Ok</button>
</form>
With PHP, you can access to any input value using the name:
$code = $_POST['code'];
Now, I think you want to "add" several books using this HTML form without a storage system. The problem is you can not do this if for every a new request since all the elements you have in your array will be deleted each time you run a new post request. To keep this information you need to use some persistent storage system as a database or others.
Since you seem to want to keep the information for each book together, you need to use a multidimensional array - hence, you'll need to redo the whole thing. Here's a suggestion:
Form:
<h2>Exercice 2</h2>
<form method="post">
<label for"code">Number :</label>
<input id="code" name="code" type="number">
<label for"title">Title :</label>
<input id="title" name="title" type="text">
<label for"author-firstname">Author First Name:</label>
<input id="author-firstname" name="author-firstname" type="text">
<label for "author-lastname">Author Last Name:</label>
<input id="author-lastname" name="author-lastname" type="text">
<input type="submit" name="submit_book" value="Ok">
</form>
Fixed the name-problems, changed the heading (you never, ever use H1 for a form, H1 is strictly used for the site-wide heading/logo/name of site). Also changed the button into a simple input type="submit".
$title = $_POST['title'];
$code = $_POST['code'];
$author = $_POST['author'];
$book = []; // changed this to modern PHP version array assignment
$book[0]['code'] = 123;
$book[0]['title'] = "Legendes";
$book[0]['author-firstname'] = "David";
$book[0]['author-lastname'] = "Gemmel"; // no reason to assign a separate array for first and last name, just use two array-keys
for ($c = 0; $c <= count($book); $c++) { //changed this to a for, counting the amount of entries in the $book array
echo 'Title: '.$book[$c]['title'];
echo 'Author: '.$book[$c]['author-firstname'].' '.$book[$c]['author-lastname'];
} // the content should probably be wrapped in a container of some sort, probably a <li> (and then a <ul>-list declared before the for-loop)
Now. None of this has anything to do with putting stuff INTO the array. That would be something like this (there isn't even a point of assigning the $_POST-variables for the code you posted. But, you can do something like this:
if (isset($_POST['submit_book'])) {
$title = $_POST['title'];
$code = $_POST['code'];
$author-firstname = $_POST['author-firstname'];
$author-lastname = $_POST['author-lastname'];
// however, if all you're doing is putting this into the array, no need to assigne the $_POST to variables, you can just do this:
$temp_array = ['code'=>$_POST['code'],'title'=>$_POST['title'],'author-firstname'=>$_POST['author-firstname'],'author-lastname'=>$_POST['author-lastname']];
$book[] = $temp_array;
}
So, that would replace the assigned variables at the beginning of your code.

initialization of multiple POST input php

The issue here is trying with my limited experience to create a section where a user can dynamically edit data already stored. The approach I am using is to create POSTs input in a variable number and initialize them with the already stored values... here is the code
<html>
<input type="button" id="more_fields" onclick="add_fields();" value="Add another Skill" />
<?php
$cars = ["Volvo", "BMW", "Toyota"];
echo $cars[0];
?>
<div id="data_fileds">
<div>
<div class="content">
<span>Skill: <input type="text" style="Skill:48px;" name="Skill[]" value= "<?php echo $cars[0];?>" />
</div>
</div>
</div>
<script>
function add_fields() {
var objTo = document.getElementById('data_fileds')
var divtest = document.createElement("div");
divtest.innerHTML = '<div class="content"><span>Skill: <input type="text" style="Skill:48px;" name="Skill[]" value="<?php echo $cars[2];?>" />';
objTo.appendChild(divtest)
}
</script>
</html>
I managed in a non-elegant way to initialize the first POST according the first input item... what I am missing is the dynamic allocation of the number of post according the data already stored (in this case the creation of 3 POSTs as per cars array) and the initialization of the POSTs with the car[...i] values...
Anyone can support?
Thanks!!!
EDIT
I will try to be more clear, what I would like to obtain is the creation o three "Skill" input filed initialized with the following values
Skill[0] --> Volvo
Skill[1] --> BMW
Skill[2] --> Toyota
At the moment the program cannot automatically create three "Skill" field but I believe there may be a way forward. So far what I managed to do is to initialize the first field
Skill[0] --> Volvo
and input a initialization value for any trigged extra Skill input. There is no connection though between the array cars containing the initialization values and the number of input filed "Skills"
Hope this explains.
To get an input field for every value stored in the $cars-array you could use a simple loop:
<?php for($i = 0; $i < count($cars); $i++): ?>
<div class="content">
<span>Skill:
<input type="text" style="Skill:48px;" name="Skill[]" value="<?php echo $cars[$i];?>" />
</span>
</div>
<?php endfor; ?>

Dynamically added input fields not getting posted?

The code below consists of invoice-lines that contain some input fields that the user can fill out. The initial number of input lines is 20. Users will often need to add more lines to the invoice by clicking the "Add lines" button. Every click of this button uses Javascript to append more lines to the invoice.
The problem is when the form gets submitted only the first 20 lines seem to get submitted. All the javascript appended invoice lines are ignored and never POSTed.
I have been trying to work out this problem for quite a while now, I was wondering if someone can guide me as to how to go about implementing this correctly?
Many thanks in advance.
Markup / PHP
<?php
for($i=0; $i < 20; $i++){
echo '
<div class="invoice-line">
<div class="prod-id-cell"><input name="rows['.$i.'][id]" type="text" class="prod-id-input">
<div class="smart-suggestions">
<!-- RESULT SUGGESTIONS WILL POPULATE HERE --> </div>
</div>
<div class="prod-name-cell">
<input type="text" name="rows['.$i.'][name]" class="prod-name-input"/> <div class="smart-suggestions">
<!-- RESULT SUGGESTIONS WILL POPULATE HERE -->
</div>
</div>
<div class="price-cell"><input name="rows['.$i.'][price]" class="price-input" type="text" /></div>
<div class="quantity-cell"><input name="rows['.$i.'][quantity]" type="text" class="quantity-input"></div>
<div class="unit-price-cell"><input name="rows['.$i.'][unit-price]" class="unit-price-input" type="text" /></div>
<div class="num-kits-cell"><input name="rows['.$i.'][num-kits]" class="num-kits-input" type="text" /></div>
<div class="amount-cell"><input name="rows['.$i.'][amount]" class="amount-input" type="text" readonly="readonly" /></div>
</div>';
}
?>
Javascript
//**ADD 5 LINES**//
$('.invoice-links div').on("click", ".add-five-trigger", function(){
for(var i=0; i < 5; i++){
var invoiceLine = $(".invoice-line").first().clone( true, true );
$(invoiceLine).insertAfter(".invoice-line:last");
$(".invoice-line:last").find('input').val('').attr('disabled','disabled');
}
});
You forgot to change the name attributes of the cloned inputs. They would overwrite previous fields.
Use this:
var invoiceLine = $(".invoice-line").last();
var newLine = invoiceLine.clone( true, true );
invoiceLine.after(newLine);
newLine.find('input').each(function() {
if (this.type == "text")
this.value = "";
this.name = this.name.replace(/rows\[(\d+)\]/, function(m, num) {
return "rows["+(+num+1)+"]";
});
this.disabled = true;
});
The values are not being posted because you are disabling them. Input elements with disabled attribute don't get posted.
Also, always make sure that elements have unique ids and names. Elements without names don't get posted.
You are not giving new names to the elements you create. You are also disabling them.
$(".invoice-line:last").find('input').val('').attr('disabled','disabled');
Disabled form inputs will never be submitted with the form.

Categories