Welcome Guest, Not a member yet? Register   Sign In
How should I write an "edit" view/controller to prepopulate values and perform validation?
#1

[eluser]Unknown[/eluser]
Hi all,

I'm new to CI after developing in flat php since 2000, so the MVC thing is quite alien to me.

I'm writing a small test app in preparation for a database contract i'm starting on for a client next month, so would appreciate any pointers you can give.

I'm trying to write an "Edit" page so that a client's details can be changed when required. This needs to have the same validation as the add page, which uses...

Controller function:
Code:
function add() {
        $rules['name'] = "required";
        $rules['email'] = "required|valid_email";
        $rules['job'] = "required";
        $rules['phone'] = "required|numeric";
        $this->validation->set_rules($rules);
        
        $fields['name']    = 'Username';
        $fields['email']    = 'Email Address';
        $fields['job']    = 'Job';
        $fields['phone']    = 'Phone Number';
        $this->validation->set_fields($fields);
        
        if ($this->validation->run() == FALSE)
        {
            $this->load->view('client_add_view');
        }
        else
        {
            $this->db->insert('clients', $_POST);
            
            redirect('client/');
        }
    }

View:
Code:
<html>
<head>
<title>Add Client</title>
</head>
<body>
<h1>Add Client</h1>

<p>&lt;?=anchor('client/', 'Back to Client List');?&gt;</p>

&lt;?=form_open('client/add');?&gt;

<p>name &lt;input type="text" name="name" value="&lt;?=$this-&gt;validation->name;?&gt;" />&lt;?=$this->validation->name_error; ?&gt;</p>
<p>email &lt;input type="text" name="email" value="&lt;?=$this-&gt;validation->email;?&gt;" />&lt;?=$this->validation->email_error; ?&gt;</p>
<p>job &lt;input type="text" name="job" value="&lt;?=$this-&gt;validation->job;?&gt;" />&lt;?=$this->validation->job_error; ?&gt;</p>
<p>phone &lt;input type="text" name="phone" value="&lt;?=$this-&gt;validation->phone;?&gt;" />&lt;?=$this->validation->phone_error; ?&gt;</p>
<p>&lt;input type="submit" value="Add Client" /&gt;</p>

&lt;/form&gt;

&lt;/body&gt;
&lt;/html&gt;

First of all please let me know if there's a ebtter way to do the above - as I say, i've used PHP for many years, but the MVC concept is something I only started looking at yesterday.

Now the way I understand it, the validation prepopulates the form fields on postback, so how would I go about making the edit page to have the same functionality, same form, everything... just that on initial load it should prepoulate from the database, then on postback should retain the user's changes but flag up any errors. Finally it has to db->update at the end rather than db->insert.


Lastly, are there any example apps which cover a simple "cd catalogue" scenario or similar? I'm just trying to think of a typical database example app.

In a nutshell I need scaffolding with validation. :-)

Many thanks in advance,
Karl
#2

[eluser]echadwickb[/eluser]
I'm pretty new to this whole mvc thing too, so the following code may not be the cleanest, most concise way of accomplishing your goal, but here goes:

Create another function in your controller called "edit" or something similar. Then copy all the add function code into the function. Notice the if/else statement I added to your code. See the comments for more explanation.

Code:
function edit() {
    $rules['name'] = "required";
    $rules['email'] = "required|valid_email";
    $rules['job'] = "required";
    $rules['phone'] = "required|numeric";
    $this->validation->set_rules($rules);

    $fields['name']    = 'Username';
    $fields['email']    = 'Email Address';
    $fields['job']    = 'Job';
    $fields['phone']    = 'Phone Number';
    $this->validation->set_fields($fields);
    
    //Looks for third uri segment for primary key
    //e.g. http://www.site.com/client/edit/4, where 4 is the primary key
    if($this->uri->segment(3,0))
    {
        $pkey = $this->uri->segment(3,0);
        //retrieve corresponding db record.
        $query = $this->db->getwhere('clients', array('id' => $pkey), "1");
        $row = $query->row_array();
        
        //assign record values to view variables to default in view form
        if(count($row) > 0)
        {
            $client_add_view_values['name'] = $row['name'];
            $client_add_view_values['email'] = $row['email'];
            $client_add_view_values['job'] = $row['job'];
            $client_add_view_values['phone'] = $row['phone'];
            $client_add_view_values['id'] = $row['id'];
        }
    }
    //no primary key provided so redirect.
    else
    {
        redirect('client/');
    }
    
    
    if ($this->validation->run() == FALSE)
    {
        //load the $client_add_view_values array into the view to populate the form
        $this->load->view('client_add_view', $client_add_view_values);
    }
    else
    {
        $this->db->where('id', $this->input->post('id'));
        $this->db->update('clients', $_POST);

        redirect('client/');
    }
}

In your view, you need to make a slight modification to the values of all your input tags. Instead of doing
Code:
$this->validation->name
you would want to setup an if/else situation like this
Code:
$this->validation->name ? $this->validation->name : $name;
PHP checks to see if validation variable is set. If not, uses the $name variable you already populated. You'll also need to go back into your add function and initialize all the view variables and load them into the view or else you'll get warnings. Something like this:

Code:
$client_add_view_values['name'] = "";
$client_add_view_values['email'] = "";
$client_add_view_values['job'] = "";
$client_add_view_values['phone'] = "";
$client_add_view_values['id'] = "";

$this->load->view('client_add_view', $client_add_view_values);

Notice in your modified view code below that I added the hidden "id" field so the update function knows which db record to update. All of the input tag values are set to check validation for a value, and if not present, use whatever value you passed to the corresponding field variable.

Code:
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Add Client&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
<h1>Add Client</h1>

<p>&lt;?=anchor('client/', 'Back to Client List');?&gt;</p>

&lt;?=form_open('client/add');?&gt;

<p>name &lt;input type="text" name="name" value="&lt;?=$this-&gt;validation->name ? $this->validation->name : $name;?&gt;" />&lt;?=$this->validation->name_error; ?&gt;</p>
<p>email &lt;input type="text" name="email" value="&lt;?=$this-&gt;validation->email ? $this->validation->email : $email;?&gt;" />&lt;?=$this->validation->email_error; ?&gt;</p>
<p>job &lt;input type="text" name="job" value="&lt;?=$this-&gt;validation->job ? $this->validation->job : $job;?&gt;" />&lt;?=$this->validation->job_error; ?&gt;</p>
<p>phone &lt;input type="text" name="phone" value="&lt;?=$this-&gt;validation->phone ? $this->validation->phone : $phone;?&gt;" />&lt;?=$this->validation->phone_error; ?&gt;</p>
&lt;input type="hidden" name="id" value"&lt;?=$id; ?&gt;" /&gt;
<p>&lt;input type="submit" value="Add Client" /&gt;</p>

&lt;/form&gt;

&lt;/body&gt;
&lt;/html&gt;

None of the above code has been tested, but it should give you an idea of how to accomplish your goal. I also use models to handle db updates and inserts instead of doing them in the controller. Makes the code a little more flexible and cleaner, though it may not be the "best" way of doing things. Good luck.

Chad B.
#3

[eluser]Unknown[/eluser]
Thanks Chad, that all makes perfect sense and does seem a decent way of going about the situation.

I'm not entirely convinced MVC is of particular benefit over a solution such as the PEAR package library. MVC just seems to be putting restrictions ond complications on things where a simple PEAR DataObject Model would get the job done with more flexibility and less feeling of constriction.

What're your opinions as a relative newbie? Do you think MVC is notably "better" than a solution such as PEAR?

I'll be interested to hear your thoughs as i'm not convinced yet!

Cheers
Karl
#4

[eluser]@li[/eluser]
How would you do something like this as a Dataobject in PEAR? Can you demonstrate? Personally I've never tried PEAR because it seems to be huuge in file size, and seems very complicated to set up and bloated/slow in performance. Just my impression of it..
#5

[eluser]wiredesignz[/eluser]
Quote:Do you think MVC is notably “better” than a solution such as PEAR?

The Pear packages and the MVC design pattern are totally different subjects.

Have a read about MVC and decide for yourself:
http://www.phpwact.org/pattern/model_view_controller
#6

[eluser]adamp1[/eluser]
Why not just on first load of a form preload all the values into $this->validation->{$name} that way you don't need to if statmente when ever you want to output it into the form? Makes things alot simpler.
#7

[eluser]echadwickb[/eluser]
adamp1:
Quote:Why not just on first load of a form preload all the values into $this->validation->{$name} that way you don’t need to if statmente when ever you want to output it into the form? Makes things alot simpler.

. . . because I'm not a very experienced programmer. Thanks for the tip. I'll probably go back and make some adjustments to my current programming project.

DigitalVibe:
Quote:What’re your opinions as a relative newbie? Do you think MVC is notably “better” than a solution such as PEAR?

I wish I had enough experience to answer that question intelligently. I'm going to step out on a ledge here and say PEAR vs MVC is apples to oranges. Isn't pear just a repository for commonly written tasks/scripts? And my limited understanding of MVC is that it's just a way of organizing your code and logic in a more manageable/scalable way. I think it would be more accurate to compare codeigniter to PEAR. Either way, I like codeigniter and I like MVC. I'm coding faster and with less errors. Also, (and this is very important) it's now easier for me to add/change features in my web apps.
I do like the idea behind PEAR, but my understanding (from other programmer's opinions) is that PEAR is just a little too heavy for some websites. I think in the long run, that the PHP community will benefit from standardized libraries like PEAR. Of course, I come from the domino/lotusscript world, where the development environment is much more defined and the ui is made out of pleated, stone-washed jeans and permed mullets.
#8

[eluser]bigtony[/eluser]
I'm very new to CI and have been experimenting with how to setup a controller/view combination that allows database additions and amendments. So effectively you have an 'add' mode and an 'edit' mode and just one controller function and one simple view.

This has not been thoroughly tested but seems to work. Any thoughts appreciated if there's a better way.

Controller code:
Code:
function index($id=0) {
    $data['id'] = $id;    // 0 = 'add' mode, otherwise contains database id for 'edit' mode

    $this->load->library('validation');

    // Set validation rules
    $rules['name'] = "trim|required";
    $rules['county'] = "trim|required";
    $rules['email'] = "trim|required|callback__email_validate";
    $this->validation->set_rules($rules);

    // Set validation fields
    $fields['name'] = 'Name';
    $fields['county'] =    'County';
    $fields['email'] = 'Email Address';
    $this->validation->set_fields($fields);

    // If in 'edit' mode but form not yet posted, load from database into validation fields
    if (($id > 0) and (count($this->input->post() == 0))) {
        $this->load->model('person_model');
        $query = $this->person_model->findPersonById($id);
        if ($query->num_rows() == 1) {
            $results = $query->result();
            $this->validation->name = $results[0]->Person_Name;
            $this->validation->county = $results[0]->Person_County;
            $this->validation->email = $results[0]->Person_Email;
        } else {
            $data['id'] = 0;    // Not found so switch to 'add' mode
        }
    }
    
    // Validate
    if ($this->validation->run() == FALSE) {
        $this->load->view('person_manage_view', $data);
    } else {
        // Set db data
        $person = array(
                        'Person_Name' => $this->validation->name,
                        'Person_County' => $this->validation->county,
                        'Person_Email' => $this->validation->email
                        );
                                                
        $this->load->model('person_model');
        if ($id == 0) {
            // Add mode
            $this->person_model->insert($person);
        } else {
            // Edit mode
            $this->person_model->update($id, $person);
        }
        
        redirect('persons');
    }
}
And then in your view just reference the validation field for the value, e.g.:
Code:
&lt;input type="text" name="name" value="&lt;?php echo $this-&gt;validation->name; ?&gt;" />
I haven't tested with selects, checkboxes, etc.




Theme © iAndrew 2016 - Forum software by © MyBB