3
votes

I'm new to cakephp and trying to write a simple app with it, however I'm stuck with some form validation issues.

I have a model named "Person" which hasMany "PersonSkill" objects. To add a "PersonSkill" to a person, I have set it up to call a url like this:

http://localhost/myapp/person_skills/add/person_id:3

I have been passing through the person_id because I want to display the name of the person we are adding the skills for.

My issue is if the validation fails, the person_id parameter is not persisted to the next request, so the person's name is not displayed.

The add method on the controller looks like this:

function add() {        
    if (!empty($this->data)) {          
        if ($this->PersonSkill->save($this->data)) {
            $this->Session->setFlash('Your person has been saved.');
            $this->redirect(array('action' => 'view', 'id' => $this->PersonSkill->id));
        }       
    } else {
        $this->Person->id = $this->params['named']['person_id'];
        $this->set('person', $this->Person->read());        
    }
}   

In my person_skill add.ctp I set a hidden field which holds the person_id, eg:

echo $form->input('person_id', array('type'=>'hidden','value'=>$person['Person']['id']));

Is there a way to persist the person_id url parameter when form validation fails, or is there a better way to do this that I'm missing completely?

Any advice would be greatly appreciated.

2

2 Answers

6
votes

The FormHelper::create() method allows you to configure the URL in the action attribute of the form tag it creates.

You want to make sure the current URL is used so you are posting to the same URL and if validation fails, the person_id named parameter is still there.

Try something like this:

echo $form->create('PersonSkill', array('url' => $this->params['named']));

CakePHP should merge the named params, i.e. array('person_id' => 3) with the current controller and action and return the same URL as you are on.

By the way, you also want to read the person details and set them available in the view if $this->data is not empty, so I'd lose the else statement in the controller and just have:

function add() {        
    if (!empty($this->data)) {          
        if ($this->PersonSkill->save($this->data)) {
            $this->Session->setFlash('Your person has been saved.');
            $this->redirect(array(
                'action' => 'view',
                'id' => $this->PersonSkill->id
            ));
        }       
    }
    $this->Person->id = $this->params['named']['person_id'];
    $this->set('person', $this->Person->read());        
}   
0
votes

You could manually validate the data, then use your own redirect parameters to preserve the URL params. E.g.,

if( !empty( $this->data ) ) {
 if( $this->PersonSkill->validates() ) {
  if( $this->PersonSkill->save( $this->data ) {
   ...
  }
  else { // invalid data
   $this->redirect( array( 'action' => 'view', 'id' => $this->PersonSkills->id ) );
  }
 }
}

From the manual on validation in the controller at http://book.cakephp.org/view/410/Validating-Data-from-the-Controller