Advice expanding a dynamic form validation in php - php

I have a form which (on a previous page) users can select how many items they want to include. Once the second page is submitted, it is run through a validation script which takes the requirement, the field name, and a message to return if an error occurs in the validation.
if($numFieldSelectedearlier > 0) {
for($z=1; $z<=$numFieldSelectedearlier; $z++) {
$rules[] = "required,name,Name for item {$z} is required.";
}
}
In my html form, the field looks like the following:
<form name="someForm" action="" method="post">
<?php if ($numFieldSelectedearlier > 0) {
for($y=1; $y <= $numFieldSelectedearlier; $y++) { ?>
<input type="text" name="name[]" id="name<?php echo $y; ?>" />
<?php }
} ?>
....
The problem I have is, the script is currently build to handle single elements (one field named "name", etc). The php validator takes all POST elements and breaks them out as fields to do the validation and I'm struggling to figure out how to either modify the validation script itself (which I'm somewhat hesitant to do given it would change the overall structure of the validator to check if the element name was itself an array then loop through) or if I am perhaps not thinking about a simpler way to handle the actual $rules creation piece.
Note: it may seem the only thing I care about is the a field is required but I want to essentially pass the arrayed item through the same validation options as any other field (required, numbers only, email, etc) so I don't want to duplicate code for what in theory already exists.
Thank you for any assistance you can provide.

Since you're doing a loop already on both sides, why not just use names like name1, name2, etc. and link your rules to those fields?
On the HTML side, you would change the name:
<input type="text" name="name<?php echo $y; ?>" ... />
And on the rules creation side, you would bind to those field names:
if($numFieldSelectedearlier > 0) {
for($z=1; $z<=$numFieldSelectedearlier; $z++) {
$rules[] = "required,name{$z},Name for item {$z} is required.";
}
}

Related

CakePHP: Form helper with saveMany() to edit multiple rows at once

In my view (/View/Tests/admin_edit.ctp) I want to edit multiple rows (from a different model) by pointing the form to the QsetsController and the "admin_order" action then use the saveMany($this->request->data) to update all changes.
/View/Tests/admin_edit.ctp:
echo $this->Form->create( 'Qset', array('action'=>'order', 'admin'=>1));
$n = 1;
foreach ($qsets as $qset) : ?>
<h3>Question set <?php echo $n; $n++;?></h3>
<?php echo $this->Form->input('Qset.'.$n.'.order'); ?>
<?php echo $this->Form->input('Qset.'.$n.'.id', array('type'=>'hidden') ); ?>
...
$n++;
endforeach;
echo $this->Form->end('save');
/Controller/QsetsController.php
public function admin_order() {
$data = $this->request->data; //maybe just $this->data ?
$this->Qset->saveAll($data);
$this->Session->setFlash( "Order saved.");
$this->redirect( Controller::referer() );
}
Currently, my data does not get saved (although there are no errors).
Also, only the first input echoed by the foreach loop appears with a correct order field value. Each subsequent one has no value at all.
Update:
I changed $n = 1 to $n = 0 and now the first AND second input appear with their correct order values.
update2:
The markup for the form starts like this:
<form action="/admin/qsets/order" id="QsetOrderForm" method="post" accept-charset="utf-8">
The markup for the input fields which appear correct:
<div class="input number"><label for="Qset2Order">Order</label>
<input name="data[Qset][2][order]" type="number" value="3" id="Qset2Order">
</div>
The markup that results for the empty input fields:
<div class="input number"><label for="Qset3Order">Order</label>
<input name="data[Qset][3][order]" type="number" id="Qset3Order">
</div>
Update3:
I solved the problem with the inputs not displaying correctly! Notice I was incrementing $n before echoing the the inputs, so this was creating duplicates at the end of the loop. I moved $n++ to after the inputs and now they appear correctly. Phew. Now I just need to get them to save.
Useful references:
Cake book chapter on saveMany()/saveAll()
Similar question
You reference the manual but probably haven't read it well enough :)
Quoting from the section for saveMany():
Note that we are passing numerical indices instead of usual $data
containing the Article key. When saving multiple records of same model
the records arrays should be just numerically indexed without the
model key.
So instead of $data pass $data['Qset'] to saveAll()/saveMany().
Also Controller::referer() is not a static method use $this->referer()

Need type="text" input fields to display previously-POST'd entries if errors occur

I've probably not explained what I"m trying to do in the title very well, so here goes:
I've got a HTML entry form, in a .php file. That entry form when submitted files a POST operation. That POST operation has code to check field input, similar to this:
<?php
...
if ($_POST["submitted"] == 1) {
//"submitted" is a hidden field with value '1' in the form
$isvalid = 1; // Inits to 1, changes to 0 if something fails checks.
$field1 = $_POST["field1"];
$field2 = $_POST["field2"];
...
/*
Checks for validation on each field go here,
but are not relevant to this question here.
*/
}
if ($isvalid == 1) {
// Send email
} else { ?>
<!-- Print form, and error msg. -->
...
<input name="field1" type="text" id="field1" size="32" class="stylingclass">
...
So the above is example code, but here's the real question: How can I get any of the text input fields in my form, when submitted and an error occurred, to automatically contain the previous values that were entered, so that the user can correct the entries accordingly, based on whatever constraints I've set?
You can set the value parameter using a basic ternary operator:
<input name="field1" type="text" id="field1" value="<?php echo isset($_POST["field1"]) ? $_POST["field1"] : ''; ?>" size="32" class="stylingclass">
Note that the ternary operator is used here to prevent an error if there is no index of the specified field in the $_POST array
Just add value="<?=$_POST['field1']?>" (assuming PHP 5.4, use <?php echo $_POST['field1'] ?> otherwise)

PHP avoiding a long POST

This is more of a technique question rather than maybe code. I am having a php form with many fields (items to select). Naturally some of the items might be selected and some not. How do I know which ones are selected when i post the data from page 1 to page 2? I thought of testing each one if empty or not, but there are just too many fields and it doesn't feel at all efficient to use or code.
Thanks,
UPDATE EDIT:
I've tried the following and maybe it will get me somewhere before I carry on testing the repliers solutions...
<html>
<body>
<form name="test" id="name" action="testprocess.php" method="POST">
<input type="text" name="choices[shirt]">
<input type="text" name="choices[pants]">
<input type="text" name="choices[tie]">
<input type="text" name="choices[socks]">
<input type="submit" value="submit data" />
</form>
</body>
</html>
and then second page:
<?php
$names = $_POST['choices'];
echo "Names are: <br>";
print_r($names);
?>
This gives out the following:
Names are: Array ( [shirt] => sdjalskdjlk [pants] => lkjlkjlk [tie]
=> jlk [socks] => lkjlkjl )
Now what I am going to try to do is iterate over the array, and since the values in my case are numbers, I will just check which of the fields are > 0 given the default is 0. I hope this works...if not then I will let you know :)
I think what you're looking for is this:
<form action="submit.php" method="POST">
<input type="checkbox" name="checkboxes[]" value="this" /> This
<input type="checkbox" name="checkboxes[]" value="might" /> might
<input type="checkbox" name="checkboxes[]" value="work" /> work
<input type="submit" />
</form>
And then in submit.php, you simply write:
<?php
foreach($_POST['checkboxes'] as $value) {
echo "{$value} was checked!";
}
?>
The square brackets in the name of the checkbox elements tell PHP to put all elements with this name into the same array, in this case $_POST['checkboxes'], though you could call the checkboxes anything you like, of course.
You should post your code so we would better understand what you want to do.
But from what I understood you are making a form with check boxes. If you want to see if the check boxes are selected, you can go like this:
if(!$_POST['checkbox1'] && !$_POST['checkbox2'] && !$_POST['checkbox3'])
This looks if all the three check boxes are empty.
Just an idea:
Create a hidden input field within your form with no value. Whenever any of the forms fields is filled/selected, you add the name attribute of that field in this hidden field (Field names are saved with a comma separator).
On doing a POST, you can read this variable and only those fields present in this have been selected/filled in the form.
Hope this helps.
Try this.....
<?php
function checkvalue($val) {
if($val != "") return true;
else return false;
}
if(isset($_POST['submit'])) {
$values = array_filter(($_POST), "checkvalue");
$set_values = array_keys($values);
}
?>
In this manner you can get all the values that has been set in an array..
I'm not exactly sure to understand your intention. I assume that you have multiple form fields you'd like to part into different Web pages (e.g. a typical survey form).
If this is the case use sessions to store the different data of your forms until the "final submit button" (e.g. on the last page) has been pressed.
How do I know which ones are selected when i post the data from page 1 to page 2?
is a different question from how to avoid a large POST to PHP.
Assuming this is a table of data...
Just update everything regardless (if you've got the primary / unique keys set correctly)
Use Ajax to update individual rows as they are changed at the front end
Use Javascript to set a flag within each row when the data in that row is modified
Or store a representation of the existing data for each row as a hidden field for the row, on submission e.g.
print "<form....><table>\n";
foreach ($row as $id=>$r) {
print "<tr><td><input type='hidden' name='prev[$id]' value='"
. md5(serialize($r)) . "'>...
}
...at the receiving end...
foreach ($_POST['prev'] as $id=>$prev) {
$sent_back=array( /* the field values in the row */ );
if (md5(serialize($sent_back)) != $prev) {
// data has changed
update_record($id, $sent_back);
}
}

Extract value from select/option tag in php?

I am not exactly how to do it and how to word the question, so i shall try my best (PS: i'm new to web dev, so please be clear in your answers if you could).
So, I have got a drop down menu with the list names, which are taken from my database. In that database i have a table with names column (the ones that are rendered to the dropdown box) and relevant information to those names. Now, I want that relevant information to appear below in a tag when a user choose one of those names. I also cannot use the form.submit() method because my submit button is already taken for something else.
Here is the code to that bit:
<form name="name_choice" method="post" action="index.php">
<select name="names" onchange="form.some_method()">
<option value="NULL" selected="selected">--Select name--</option>
<?php
for ( $i = 0; $i < $numrows; $i++ ) { //for all the columns, iterate and print out
$id_names = mysql_result($result, $i);
echo "<option value='".$id_names."'>".$id_names."</option>";
}
?>
</select>
</form>
So the bit above works fine, but the "some_method()" is my problem, i don't know what to trigger to display the text in the div below the drop down box (code is below for it):
<div class="information"> <!--if the name is chosen ONLY!-->
<?php
if($_POST['names'] == "NULL") {
echo '<p>Please select an option from the select box.</p>'; //this bit is for testing
}
else {
echo '<p>You have selected: <strong>', $_POST['names'], '</strong>.</p>';
//and then how to echo the relevant information?:(
}
?>
</div><!--end of possible info-->
onchange is a JavaScript event. PHP can't do realtime processing of form data, as it sits on the server and the form is on the client. You can sort of do it by using AJAX and passing the form data as the user types, but that would be a lot more work than is needed. Take a look at JavaScript form validation posts to get yourself headed on the correct path.

How to pass data from form without a form field? (PHP)

I have a form for editing a users name and email.
So when it updates the name and email, it needs the username to identify which row it should update.
So i wanted to know if there is any element which is passed with the form but without showing the value or being editable in the input tag.
So i get the username from one script.
The edit user script gets the name and email from the database with the specified username.
Then it passes that new name and email with the username to another script which updates it.
I believe you are looking for
<input type='hidden' name='username' value='theusername' />
hidden - can only be seen in the source of your HTML document
name - where it will be in the $_REQUEST/$_POST/$_GET ($_POST or $_GET depending on how you are submitting your form) variable on submit
value - the username you want this form to relate to
PRO TIP: Have a way to tell who is trying to update users so you don't have unauthorized people updating your user information. It would be very easy for someone to change the username in the form and try to update someone else.
You can use input type hidden
<input type="hidden" name = "username" value="<?php echo $username ?>">
use an:
<input type="hidden" />
HIDDEN is a TYPE attribute value to the INPUT element for FORMs. It indicates a form field that does not appear visibly in the document and that the user does not interact with. It can be used to transmit state information about the client or server. Hidden fields often store a default value (e.g.via php), or have their value changed by a JavaScript.
more here
Use a hidden input tag:
<input type='hidden' name='username' value='theusername' />
As all the others stated you need a hidden input. It WILL be editable though, never trust it as you never trust any other data coming from outside.
But I'd like to add that it would be nicer not to use the username for identifying a row, add an ID column as a primary key instead to your database (possibly auto incremented), and use that in your form.
Something like
<input type="hidden" name="userid" value="<?=$userid?>" />
Arun, you can use GET to pass variables from one page to another page. Simply construct URLs as edituser.php?username=arun and so on. This is the only possible way to pass on variables or data, of course apart from cookies, to other pages w/out using form tags.
Second method is to use JavaScript to create a hidden form field and update it with username.
Third one is to simply add hidden input tags. But this and latter will require form tags.
A word of caution, filter user inputs, be JS, GET or hidden fields.
You can use a hidden form field:
<input type="hidden" name="originalUsername" value="something" />
This won't render on the form in the browser and will likely be ignored and unnoticed by the user.
However, be aware that this is editable. Do not rely on this as a security measure. When the form is submitted, make sure that the user submitting the form (using whatever authentication and authorization mechanisms you have in place) is authorized to make this change before persisting it to the database. Any form field being submitted can be edited.
Use this if you want to use it safely:
<input type='hidden' name='username' value='<?php echo encode("Please Encode Me!","This is a key"); ?>' />
wich will result into:
<input type='hidden' name='username' value='p3e4e4241674d2r4m4i5o464a4f2p3k5c2' />
and in the modification script you will have to use:
<?php $username = decode("p3e4e4241674d2r4m4i5o464a4f2p3k5c2","This is a key"); ?>
Below you have the PHP functions for the ENCODE/DECODE:
<?php
function encode($string,$key) {
$key = sha1($key);
$strLen = strlen($string);
$keyLen = strlen($key);
for ($i = 0; $i < $strLen; $i++) {
$ordStr = ord(substr($string,$i,1));
if ($j == $keyLen) { $j = 0; }
$ordKey = ord(substr($key,$j,1));
$j++;
$hash .= strrev(base_convert(dechex($ordStr + $ordKey),16,36));
}
return $hash;
}
function decode($string,$key) {
$key = sha1($key);
$strLen = strlen($string);
$keyLen = strlen($key);
for ($i = 0; $i < $strLen; $i+=2) {
$ordStr = hexdec(base_convert(strrev(substr($string,$i,2)),36,16));
if ($j == $keyLen) { $j = 0; }
$ordKey = ord(substr($key,$j,1));
$j++;
$hash .= chr($ordStr - $ordKey);
}
return $hash;
}
?>

Categories