Welcome Guest, Not a member yet? Register   Sign In
validating an "edit" form
#1

[eluser]eilrahc[/eluser]
Okay. I hope this makes sense but it's getting terribly late so excuse me if I'm as clear as mud. Smile This has to be a frequently-encountered problem but the noobie in me hasn't been able to uncover anything particularly insightful.

So I ran through the user guide for the Validation class and it makes perfect sense, but only for forms that don't come pre-filled from the server. I'm building a standard CRUD-style app and I'm trying to build a form and a validating controller for editing a pre-filled form, such as one you might encounter when updating a record in the database.

Here's what I did:

1. I copied to code verbatim from the Validation section of the User Guide.

2. I added a $data array to the controller containing pre-filled values for the form (of course these would come from a database in a real app) and passed it into the view.

3. In the view, I hacked together the following ugly thing because I need the form to show the pre-filled data when the view is first displayed. But if the form was submitted and failed validation, it needs to instead display $this->validation->fieldname.

Make sense? Here's what I've come up with:

Code:
<input type="text" size="50" name="username" value="<?php
  echo (array_key_exists('submit', $_POST) ? $this->validation->username : $username);
?>" />

This is only one field of course, but the way I see it, I have to repeat this for every single field in the form. It works but it's damned ugly and I can't figure out any reasonable way to make it into a function that I can simply call from the view. Since you guys do this kind of stuff for a living, perhaps you can tell me if I'm making this more contrived than necessary.

In case it'll matter, here's the applicable controller code:

Code:
$data = array(
    'username' => 'foobar',
    'password' => 'bazbrak',
    'passconf' => 'bazbrak',
    'email' => '[email protected]'
);

if ($this->validation->run() == FALSE) {
    $this->load->view('myform', $data);
} else {
    $this->load->view('formsuccess');
}
#2

[eluser]xwero[/eluser]
Instead of using the validation->fieldname i created a input helper and one of it's functions is
Code:
function post($name,$default='')
{
    return (isset($_POST[$name]))?$_POST[$name]:$default;
}
This makes your snippet
Code:
<input type="text" size="50" name="username" value="<?php echo post('username',$username); ?>" />

As a sidenote : validation->fieldname, input->post('fieldname') and $_POST['fieldname'] have the same value after validation.
#3

[eluser]eilrahc[/eluser]
Thanks for the quick reply xwero. I'll definitely look into that. A few more noob-like questions: what's the use of validation->fieldname then? Isn't it considered "not safe" to use $_POST like this? Couldn't you use input->post() instead? (I was lead to believe that input->post() always spat out "sanitized" strings.)
#4

[eluser]xwero[/eluser]
[quote author="eilrahc" date="1218632735"] what's the use of validation->fieldname then? [/quote]
It does a form_prep to sanitize the string for display
[quote author="eilrahc" date="1218632735"]Isn't it considered "not safe" to use $_POST like this?[/quote]
Not safe means in this case, the string could possibly break the html, that is why the validation->fieldname uses a form_prep. But if you build your forms with form helper functions then the value gets form_prepped twice. So i rather like to decide when to form_prep a value.
[quote author="eilrahc" date="1218632735"]Couldn't you use input->post() instead? (I was lead to believe that input->post() always spat out "sanitized" strings.)[/quote]
If you enable xss_filtering then you are right about input->post returning sanitized strings. You can't use input->post because you can't define a default. But that is some good thinking by the EL developers. The default only is necessary in the views so a helper function is the best place for the solution.
#5

[eluser]jleequeen[/eluser]
@xwero

I understand your solution above and why that nifty helper streamline things a bit. I have a question though when it comes to prefilled data. If you have a value in a form field, say 100 that you've prefilled from a database. And you've got some custom validation callback that checks to make sure that the value equals 100. If you type 99 in the field and click submit, the validation is run and triggers an error because it doesn't equal 100. But when the form is refreshed, the prefilled value is put back in along with the error. I would expect the 99 to now be in the field, because that's what you last typed in and the reason the validation is triggered in the first place. Any ideas on why that would happen, or be that way?
#6

[eluser]jleequeen[/eluser]
The code I used is similar to this

Code:
<input type="text" name="fax" value="<?php echo ($this->validation->fax) ? ($this->validation->fax) : ($row->fax);?>" />

so basically, when the form is first loaded, I want the $row->fax variable populated in the field. But once the validation has been run, I'd like whatever is in the post/field to be what shows up, not revert back to the default value. Is this because i'm using the $this->validation->fax...instead of something like your nifty helper that directly uses the $_POST variable?
#7

[eluser]ontguy[/eluser]
This is how I've done it.

in the controller
Code:
//if the form has not been submitted
if (empty($_POST))
{
  $this->validation->username = 'default value';
}

if ($this->validation->run() === FALSE)
{

in the view
Code:
&lt;input type="text" name="username" id="username" value="&lt;?=$this-&gt;validation->username; ?&gt;" /><br />
#8

[eluser]eilrahc[/eluser]
xwero, thanks for the clarification. I studied the docs (and some of the CI source) hard tonight, but just so I'm 100% sure: if I put "xss_clean", "htmlspecialchars", and so on near the front of my validation rules, I should still be reasonably safe from malicious input using your helper function, correct?

Thanks again for your guidance and advice on this.
#9

[eluser]xwero[/eluser]
jleequeen the validation library has his quirks that's why i tried to find my own solution. Ontguys solution moves your view code to the controller which is IMO half a measure because you have to add the fields to your code.

The second reason why i use the helper function is because i am of the opinion the view files should have no ties with the framework. So i only have functions and variables that display the content. The view file shouldn't know where the content comes from.
#10

[eluser]jleequeen[/eluser]
@xwero

I've implemented your helper solution and it works like a charm. Thanks for that nifty solution. I just have one more issue that I can't seem to figure out with regards to validating across multiple fields. For example, I have 3 fields of which you only need to fill out one of them. So I can't use a required rule on each one of them individually. But I also can't use a call back function, because If you come into the form the first time and each field is left blank, there is nothing in one of the fields to trip the callback function. Is there a way around this?




Theme © iAndrew 2016 - Forum software by © MyBB