I have created a form in contact form 7 and using repeater fields addon. I have two fields.
<input type="text" name="serienummer1__1" value="" class="wpcf7-form-control wpcf7-text form-control serielnumber" data-orig_name="serienummer1">
<input type="text" name="productcode1__1" value="" class="wpcf7-form-control wpcf7-text form-control productcode" data-orig_name="postcode1">
It is working fine i am able to get the values in my php file like this..
$serNo = $_GET['serienummer1__1'];
$prodCode = $_GET['productcode1__1'];
The issue is when user clone these fields the repeater plugin changed the name values of inputs then it become like this..
<input type="text" name="serienummer1__2" value="" class="wpcf7-form-control wpcf7-text form-control serielnumber" data-orig_name="serienummer1">
<input type="text" name="productcode1__2" value="" class="wpcf7-form-control wpcf7-text form-control productcode" data-orig_name="postcode1">
Here comes the problem.. I can get these values by writing harcoded this in php.
$serNo = $_GET['serienummer1__2'];
$prodCode = $_GET['productcode1__2'];
But this is not handy then i also have to write number of times because user can duplicate this section number of times there is no limit..
My question is how can get these values dynamically in php?
I tried to loop and get the values with this:
for($i=1; $i<=10; ++$i) {
if(isset($_GET['serienummer1__'.$i])) {
$serNo = $_GET['serienummer1__'.$i];
}
}
But this give 1 instead of value.
I am not sure i explained my problem correctly.
Can anyone help me with this?
Thanks in advance.
I'm not familiar with Contact Form 7 or its' additional plugins, so if there's a way to send Repeater Fields as an array instead (like #pavel mentioned), that would be ideal. If not, you'll need to grab your information and handle it yourself.
There's a dozen ways to do this, the first one I could think of would involve using array_walk() to walk through your $_GET values and assign them to separate arrays.
Since $_GET is insecure and open to user input, you'll want to check the parameters and values before doing anything with them though.
Assuming your form is posted, and you have a URL like:
https://example.com/?serienummer1__1=a-SN11&productcode1__1=a-PC11&serienummer1__2=b-SN12&…
You will end up with a $_GET array that looks like
$_GET = array(
'serienummer1__1' => 'a-SN11',
'productcode1__1' => 'a-PC11',
'serienummer1__2' => 'b-SN12',
'productcode1__2' => 'b-PC12',
'serienummer1__3' => 'c-SN13',
'productcode1__3' => 'c-PC13',
);
Now, Like I mentioned, $_GET is susceptible to user input, and you don't want users adding their own stuff to it, so you'll want to check the format of it. An easy way is to use preg_match() and check the format:
$regex = '/(productcode1|serienummer1)__\d*/';
Now, before you do anything you'll want some variables to store the validated results in:
$serNo = $prodCode = array();
With everything set up, we can proceed to walk through the array, pass those two empty arrays in by reference, and add the values to them if it passes the formatting test.
// Walk through the $_GET array and assign values
array_walk( $_GET, function($value, $key) use ($regex, &$serNo, &$prodCode){
// Does this key match our format?
if( preg_match( $regex, $key ) ){
// Yes, which array does it go in?
if( strpos($key, 'serienummer1__') !== false ){
$serNo[] = $value;
} else if( strpos($key, 'productcode1__') !== false ){
$prodCode[] = $value;
}
}
});
Now that you've validated the keys, and added the values to the appropriate arrays, you can do what you want with those.
#var_dump( $serNo ); // Contains: array(3){ 'a-SN111', 'b-SN12', 'c-SN13' }
#var_dump( $prodCode ); // Contains: array(3){ 'a-PC111', 'b-PC12', 'c-PC13' }
You can access the individual variables by index now:
echo 'Second Product Code is '. $prodCode[1]; // output: "Second Product Code is b-PC12"
This should be scalable enough to handle whatever number of repreater fields you through at it within reason and max-length of the browser's URI.
It's may be a bit overcomplicated, but in my opinion using $_GET warrants the extra security (you may even want to validate/sanitize the $value of each one). At the very least, this should be enough to get you going. Depending on what you're doing, you can loop through the two arrays at the end to output the data or build an email, or whatever you need:
for( $i = 0, $n = count($serNo); $i < $n; $i++ ){
printf( "Item #%d: [Series: %s] [Product: %s]", $i, $serNo[$i], $prodCode[$i] );
}
You can see the code compiled together as an example here.
Related
I have a form that is built dynamically:
foreach($xml->config->popup as $popup_item){
<input class="fm-req" id="fm-popup_name[]" name="fm-popup_name[]" type="text" value="" />
<textarea class="fm-req" rows="4" cols="50" id="fm-popup_desc[]" name="fm-popup_desc[]" /></textarea>
<input class="fm-req" id="fm-popup_image[]" name="fm-popup_image[]" type="file" />
}
I haven't worked with arrays in form names before but i seen on another post on stack overflow you could do this and it seems like this is a much better way than i had planned, which was to add $i to the end of the name and increment each loop so i would have ended up with:
fm-popup_name1
fm-popup_name2
fm-popup_name3 etc etc
I could then do a loop count when building the form, pass the count as a hidden field and then use a for loop where x <= count and do my insert that way. But in the interest of improving the code and keeping it more compact and easy to understand, i think its worth doing this way but i cant figure out a good way to do it:
foreach($_POST['fm-popup_name'] as $index => $value) {
// get the value of name
}
foreach($_POST['fm-popup_desc'] as $index => $value) {
// get the value of name
}
foreach($_POST['fm-popup_image'] as $index => $value) {
// get the value of name
}
With that i can access all the data i need but i don't want to make 3 separate inserts for 1 record.
How can i take the information above and something like:
foreach($_POST['fm-popup_name,fm-popup_desc,fm-popup_image'] as $index => $value) {
INSERT INTO mytable(
popup_name,
popup_desc,
popup_image
)
VALUES(
'$popup_name',
'$popup_desc'
'$popup_image'
)";
}
Any ideas? Hopefully code is ok, i filtered out all the other crap that is irrelevant so hopefully all the id's etc match but im just looking for a rough example and i can convert back to my code.
You can use something the following, but there is a risk (can you spot it?) :
$entries = count($_POST['fm-popup_name']);
for($i = 0; $i < entries; ++$i) {
$name = $_POST['fm-popup_name'];
$desc = $_POST['fm-popup_desc'];
// other processing
}
If you haven't spotted it, the risk is that not all array elements may be populated, so you may not get a proper mapping for each row, unless you enforce it on the front end and validate this before processing your loop.
Can you send an array with various values in html? I would like to send different array values with various different submit buttons all within one <form> element.
Here is what I am doing currently. It works so I'm not having a problem, but I couldn't find any documentation for anything similar and I am really curious if theres another way.
Button with my *psuedo*array
<input type="submit" name="form_action" value="action:new_business,id:0">
Decode function:
$action = explode(',', $_POST['form_action']);
$new = array();
foreach ($action as $v) {
$t = explode(':',$v);
$new[$t[0]] = $t[1];
}
print_r($new);
And the results:
Array ( [action] => new_business [id] => 0 )
Of course, this works, so I'm really just curious whether there's a built in solution already.
The desired simplicity:
<input type="submit" name="array" value="array('0'=>'foo','1'=>'bar')">
print_r($_POST['array]);
Array ( [0] => foo [1] => bar )
Edit: I know how to send arrays with html, but that was not my question. If I use hidden inputs, they get sent regardless of which submit button I click, there will be multiple submit buttons contained in one <form> element, and I need to know which was clicked and what action it is going to be used for. Sorry if that was unclear but I don't think I deserve downvotes either way...
Try this:
<input type="hidden" name="form_action[action]" value="new_business" />
<input type="hidden" name="form_action[id]" value="0" />
Inputs with names of the form name[key] will be condensed into an array. This also applies to name[], which will become elements of an indexed array.
I know the question is old. I still like to answer this, as I am implementing currently something similar.
You can indeed write your statement and turn it into a valid context. By implementing:
if(isset($_POST['array'])){
eval('$my = '.$_POST['array'].';');
print_r($my);
}
you concatenate your POST to a valid php expression in string format and evaluate it. This however is very dangerous because it allows execution of any code inside without any verification. You MUST NOT use this in a public environment because anyone can easily modify the string being send by the button.
The best solution in terms of safety and efficiency is really to send a csv format:
<input type="submit" name="array" value="array('0','foo','1','bar')">
in php do:
$my_assoc = array();
if(isset($_POST['action'])){
$my = explode(",",filter_input(INPUT_POST, 'action' , FILTER_SANITIZE_STRING));
for($i = 0, $num = count($my); $i < $num; $i+=2){
$my_assoc[$my[$i]] = $my[$i+1];
}
print_r($my_assoc);
}
The explode function is linear in complexity and has no large impact. By filtering the csv string, you can also make sure to have no unwanted characters in it (never trust incoming data). You can then either keep the indexed array ($my) and treat every two values as (psydo) key-value pair or turn it into an associative array ($my_assoc).
I'm not exactly sure how the logic would work on this. My brain is fried and i cant think clearly.
I am handling some POST data, and one of the fields in this array is a quantity string. I can read this string and determine if there are more than 1 widgets that need handled.
if($quantity <= 1){ //$_POST[widget1] }
Now say there are 4 widgets. The quantity field would reflect this number, but how would i loop through them and assign them to a new array themselves?
$_POST[widget1], $_POST[widget2], $_POST[widget3], $_POST[widget4]
How do i take that quantity number, and use it to grab that many and those specific named items from the post array, using some kind of wild card or prefix or something? I dont know if this is a for, or while, or what kind of operation. How do I loop through $_POST['widget*X*'], where X is my quantity number?
The end result is im looking to have an array structured like this:
$widgets[data1]
$widgets[data2]
$widgets[data3]
$widgets[data4]
Using a for loop, you can access the $_POST keys with a variable, as in $_POST["widget$i"]
$widgets = array();
for ($i=1; $i<=$quantity; $i++) {
// Append onto an array
$widgets[] = $_POST["widget$i"];
}
However, a better long-term solution would be to change the HTML form such that it passes an array back to PHP in the first place by adding [] to the form input's name attribute:
<input type='text' name='widgets[]' id='widget1' value='widget1' />
<input type='text' name='widgets[]' id='widget2' value='widget2' />
<input type='text' name='widgets[]' id='widget3' value='widget3' />
Accessed in PHP via $_POST['widgets'], already an array!
var_dump($_POST['widgets']);
Iterate over the number of items, at least over one (as you describe it):
$widgets = array();
foreach (range(1, max(1, $quantity)) as $item)
{
$name = sprintf('widget%d', $item);
$data = sprintf('data%d', $item);
$widget = $_POST[$name];
// do whatever you need to do with that $widget.
$widgets[$data] = $widget;
}
I have a form that uses inputs to create and array. The inputs are not all required but at least one is.
<form method="post" action="process.php">
<input type="text" name="MAC[]" maxlength="12" />
<input type="text" name="MAC[]" maxlength="12" />
<input type="text" name="MAC[]" maxlength="12" />
<input type="text" name="MAC[]" maxlength="12" />
<input class="submitbg" type="submit" value="Register" name="submit"/>
</form>
Now on process.php I want to loop through the array remove two types of special characters : ; then make all upper case, and verify there are only 12 characters and then serialize the arrray.
$my_array = $_POST['MAC'];
foreach ($my_array as $val){
$val = strtoupper($val);
$val = str_replace(";","",$val);
$val = str_replace(":","",$val);
$val = trim($val);
if (strlen($val) != 12)){
$valid = false;
$error = "Your MAC address is not 12 characters long";
}
}
$mac_addresses = serialize($my_array);
// if valid is not false do something with the cleaned up array.
The questions:
Will my foreach loop save the updated values back into the array?
How to check to make sure there is at least one array value?
I am just not sure if my foreach loop updates and resaves the values each time
If you want to save the values you should change your loop so that it looks something like this:
foreach ($my_array as $idx => $val) {
...
$my_array[$idx] = $val;
}
Of course you could also save the proper value to a separate clean array which you will then use further on in your application.
I also have to check to make sure there is at least one entry.
In theory you do not have to check whether the array contains elements to use the array in a foreach. The thing you need to check though is whether the variable contains an array. Suppose the MAC[] field wasn't submitted to the server you would first get a warning (it might also be an error nowadays) because you are looking up some non-existent index in the array. Secondly you would get an error on your foreach as it works on arrays (or anything that is Traversable). You could fix this with the following check:
if (!empty($_POST['MAC'])) {
$my_array = $_POST['MAC'];
if (!is_array($my_array)) {
// throw some error.
}
}
Of course you would want to do this validation of your input in a more structured way by providing a validation framework which you can provide validation rules and some input and the validation framework will then handle the validation and most importantly the error messages for you.
Actually could also change the last if-statement to read:
if (!is_array($my_array) && !($my_array instanceof Traversable))
That is if you want to be sure $my_array contains something you can traverse over with foreach. The nasty bit is that the built-in array() isn't Traversable, nasty although understandable.
What's the question?
you can do str_replace(array(';',':'),'',$val);
It's usually better to trim before doing other processing on the same variable due to the overhead involved in processing data you will eventually cut
Consider using break on errors, if you halt execution on one error.
You're not really doing any updates to $my_array.
Consider doing:
foreach($my_array as &$val)
You pass by reference so all updates to $val happen to the actual array. Or:
foreach($my_array as $key=>$val){
$my_array[$key]=trim($my_array[$key]);
You can also try to create a new array for your sanitized data and then over-write your old array. It all depends on needs.
I'm also not understanding your question /problem.
But, looking at your code, you might get the feeling that in the end nothing has happened to your POSTed vars.
You're right! :-)
Your cleaned up array at the end of the script is exactly the original array.
You might want to achieve something like this: The clean array will contain cleaned values, if they consist of 12 characters.
$my_array = $_POST['MAC'];
$my_clean_array = $_POST['MAC'];
foreach ($my_array as $val) {
$val = strtoupper($val);
$val = str_replace(";","",$val);
$val = str_replace(":","",$val);
$val = trim($val);
if (strlen($val) != 12)) {
$valid = false;
$error = "Your MAC address is not 12 characters long";
}
else {
$my_clean_array[] = $val;
}
}
$mac_addresses = serialize($my_clean_array);
To check to see if you have at least one you should be able to use if(count($my_array) > 1)
I have a PHP page that queries a DB to populate a form for the user to modify the data and submit.
The query returns a number of rows which contain 3 items:
ImageID
ImageName
ImageDescription
The PHP page titles each box in the form with a generic name and appends the ImageID to it. Ie:
ImageID_03
ImageName_34
ImageDescription_22
As it's unknown which images are going to have been retrieved from the DB then I can't know in advance what the name of the form entries will be.
The form deals with a large number of entries at the same time.
My backend PHP form processor that gets the data just sees it as one big array:
[imageid_2] => 2
[imagename_2] => _MG_0214
[imageid_10] => 10
[imagename_10] => _MG_0419
[imageid_39] => 39
[imagename_39] => _MG_0420
[imageid_22] => 22
[imagename_22] => Curly Fern
[imagedescription_2] => Wibble
[imagedescription_10] => Wobble
[imagedescription_39] => Fred
[imagedescription_22] => Sally
I've tried to do an array walk on it to split it into 3 arrays which set places but am stuck:
// define empty arrays
$imageidarray = array();
$imagenamearray = array();
$imagedescriptionarray = array();
// our function to call when we walk through the posted items array
function assignvars($entry, $key)
{
if (preg_match("/imageid/i", $key)) {
array_push($imageidarray, $entry);
} elseif (preg_match("/imagename/i", $key)) {
// echo " ImageName: $entry";
} elseif (preg_match("/imagedescription/i", $key)) {
// echo " ImageDescription: $entry";
}
}
array_walk($_POST, 'assignvars');
This fails with the error:
array_push(): First argument should be an array in...
Am I approaching this wrong?
Would it be possible to change the way the items are named on the form?
Current:
ImageID_03
ImageName_34
ImageDescription_22
Changed To:
ImageID[03]
ImageName[34]
ImageDescription[22]
This way it should come through the $_POST as three separate arrays meaning you can skip all that extra processing.
I hate to edit many rows at once. It's usability fault
If I go for it, I'd make it with such a form:
<form method="POST">
<input type="text" name="name[1]">
<input type="text" name="desc[1]">
<input type="text" name="name[2]">
<input type="text" name="desc[2]">
...etc
</form>
So, I'd have 2 arrays, $_POST['name'] and $_POST['desc'] where id used as a key
In your case I wouldn't use array_walk as it's just a syntax sugar, and make it with foreach to have full contorol over data processing.
I think you need
global $imageidarray;
to access a global array inside a function.
Something like this would work as well, assuming your three form fields are always submitted together:
$ids = preg_grep('/^imageid_(\d+)$/', array_keys($_POST)); // $ids now contains only the imageid_* keys
foreach($ids as $id) {
$id = substr($ids, 8); // now contains the numeric id of the field
echo $id, ": ", $_POST["imageid_$id"], "\n";
}
Not as efficient as using the array notation in the form names, but allows you to trivially extract just the ID numbers from one of the field names and then use it to access the other matching fields as well.