HABTM form validation in CakePHP

前端 未结 7 1370
我在风中等你
我在风中等你 2020-12-03 06:33

I have a Projects table and a Users table which are linked by a HABTM relation. In the \"add\" new Project page I have a multiple checkbox section to select Users for the ne

相关标签:
7条回答
  • 2020-12-03 06:42

    I've just been looking at his problem myself on a project and came across a slightly more elegant solution, as long as you're only dealing with a habtm relationship and you need to ensure that at least one checkbox is selected.

    so for example you're editing a Project and you want it to be associated with at least one user

    Add this to beforeValidate()

    // check habtm model and add to data

      foreach($this->hasAndBelongsToMany as $k=>$v) {
       if(isset($this->data[$k][$k]))
       {
        $this->data[$this->alias][$k] = $this->data[$k][$k];
       }
      }
    

    In the validation rules add the following:

    'User' => array(
       'rule' => array('multiple', array('min' => 1)),
       'message' => 'Please select one or more users'
      )
    
    0 讨论(0)
  • 2020-12-03 06:47

    teknoid's blog has a pretty in depth solution to your issue here. The most Cakey way of doing this would be to add custom validation to your model, as you mention in your comment above. Check out http://teknoid.wordpress.com/2008/10/16/how-to-validate-habtm-data/

    From the article, where Tag HABTM Post (:: Project HABTM Users):

    First, we validate the Tag model, by using the data from the form to ensure that at least one Tag was selected. If so, we save the Post and the relevant Tags.

    0 讨论(0)
  • 2020-12-03 06:49

    2016 update for CakePhp 2.7

    Full answer here : HABTM form validation with CakePHP 2.x


    TL;DR;

    AppModel.php

    public function beforeValidate($options = array()){
       foreach (array_keys($this->hasAndBelongsToMany) as $model){
         if(isset($this->data[$model][$model]))
           $this->data[$this->name][$model] = $this->data[$model][$model];
       }
       return true;
     }
    
     public function afterValidate($options = array()){
       foreach (array_keys($this->hasAndBelongsToMany) as $model){
         unset($this->data[$this->name][$model]);
         if(isset($this->validationErrors[$model]))
           $this->$model->validationErrors[$model] = $this->validationErrors[$model];
       }
       return true;
     }
    

    In the main model of your HABTM :

    public $validate = array(
        'Tag' => array(
            'rule' => array('multiple', array('min' => 1)),
            'required' => true,
            'message' => 'Please select at least one Tag for this Post.'
            )
        );
    
    0 讨论(0)
  • 2020-12-03 07:01

    I stumbled on the same issue, but now - 3 years later - with CakePHP 2.3.

    To be clear; Group has and belongs to User. I've had a form like this:

    // View/Groups/add.ctp
    echo $this->Form->input('name');
    echo $this->Form->input('User');
    

    With the validation rule like in user448164's answer:

    // Model/Group.php
    public $validate = array(
        'User' => array(
            'rule' => array('multiple', array('min' => 1)),
            'message' => 'Please select one or more users'
        )
    );
    

    That didn't work, after Googling for it, I found this question which couldn't still be the best solution. Then I tried several things, and discovered this to work just fine:

    // View/Groups/add.ctp
    echo $this->Form->input('name');
    echo $this->Form->input('Group.User');
    

    Way too easy solution, but had to dig into it to find out it works this way.

    Hopefully it helps somebody one day.

    Update for CakePHP 2.4.x (possibly 2.3.x as well)

    When I wrote this answer, I was using CakePHP 2.3.x. Back then it worked perfectly for both validating and saving the data. Now when applying the same code on a new project, using CakePHP 2.4.x, it didn't work anymore.

    I created a test case, using the following code:

    $data = array(
        'User' => array(
            'Client' => array(8)
        ),
    );
    $this->User->create();
    $this->User->saveAll($data);
    

    My first thought was: Saving all means saving all "root" models, what actually makes sense to me. To save deeper than just the "root" ones, you'll have to add the deep option. So I ended up with the following code:

    $data = array(
        'User' => array(
            'Client' => array(8)
        ),
    );
    $this->User->create();
    $this->User->saveAll($data, array('deep' => true));
    

    Works like a charm! Happy coding. :)

    Update (2014/03/06)

    Struggling with the same problem again, in this case with hasMany instead of habtm. Seems like it behaves the same way. But I found myself looking for this answer again, and got confused.

    I'd like to make clear that it's key to use Group.User instead of User in your input. Else it won't use the User model validation.

    0 讨论(0)
  • 2020-12-03 07:02

    If you are using CakePHP 2.3.x, you may need to add this code to your model in addition to the code that GuidoH provided, otherwise your HABTM model data may not save:

    public function beforeSave($options = array()){
      foreach (array_keys($this->hasAndBelongsToMany) as $model){
        if(isset($this->data[$this->name][$model])){
          $this->data[$model][$model] = $this->data[$this->name][$model];
          unset($this->data[$this->name][$model]);
        }
      }
      return true;
    }
    
    0 讨论(0)
  • 2020-12-03 07:02

    As per my comment on Guido's answer above, I use Guido's answer exactly, however I modify the data with the beforeSave callback before it saves to the database.

    I have this issue on Cake 2.4.5+

    public function beforeSave($options = array()) {
        $temp = $this->data['Group']['User'];
        unset($this->data['Group']['User']);
        $this->data['User']['User'] = $temp;
    
        return true;
    }
    
    0 讨论(0)
提交回复
热议问题