Saving a Join Model
        Posted  
        
            by 
                Thorpe Obazee
            
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by Thorpe Obazee
        
        
        
        Published on 2010-12-27T06:52:12Z
        Indexed on 
            2010/12/30
            17:54 UTC
        
        
        Read the original article
        Hit count: 319
        
I've been reading the cookbook for a while now and still don't get how I'm supposed to do this:
My original problem was this: A related Model isn't being validated
From RabidFire's commment:
If you want to count the number of Category models that a new Post is associated with (on save), then you need to do this in the beforeSave function as I've mentioned. As you've currently set up your models, you don't need to use the multiple rule anywhere. If you really, really want to validate against a list of Category IDs for some reason, then create a join model, and validate category_id with the multiple rule there.
Now, I have these models and are now validating. The problem now is that data isn't being saved in the Join Table:
class Post extends AppModel {
    var $name = 'Post';
    var $hasMany = array(
        'CategoryPost' => array(
            'className' => 'CategoryPost'
        )
    );
    var $belongsTo = array(
        'Page' => array(
            'className' => 'Page'
        )
    );
class Category extends AppModel {
    var $name = 'Category';
    var $hasMany = array(
        'CategoryPost' => array(
            'className' => 'CategoryPost'
        )
    );
class CategoryPost extends AppModel {
    var $name = 'CategoryPost';
    var $validate = array(
        'category_id' => array(
            'rule'     => array('multiple', array('in' => array(1, 2, 3, 4))),
            'required' => FALSE,
            'message'  => 'Please select one, two or three options'
        )
    );
    var $belongsTo = array(
        'Post' => array(
            'className' => 'Post'
        ),
        'Category' => array(
            'className' => 'Category'
        )
    );
This is the new Form:
<div id="content-wrap">
    <div id="main">
            <h2>Add Post</h2>
            <?php echo $this->Session->flash();?>
            <div>
            <?php
            echo $this->Form->create('Post');
            echo $this->Form->input('Post.title');
            echo $this->Form->input('CategoryPost.category_id', array('multiple' => 'checkbox'));
            echo $this->Form->input('Post.body', array('rows' => '3'));
            echo $this->Form->input('Page.meta_keywords');
            echo $this->Form->input('Page.meta_description');
            echo $this->Form->end('Save Post');
            ?>
            </div>
    <!-- main ends -->
    </div>
The data I am producing from the form is as follows:
Array
(
    [Post] => Array
        (
            [title] => 1234
            [body] => 
1234
        )
    [CategoryPost] => Array
        (
            [category_id] => Array
                (
                    [0] => 1
                    [1] => 2
                )
        )
    [Page] => Array
        (
            [meta_keywords] => 1234
            [meta_description] => 1234
            [title] => 1234
            [layout] => index
        )
)
UPDATE: controller action //Controller action
function admin_add() {
    // pr(Debugger::trace());
    $this->set('categories', $this->Post->CategoryPost->Category->find('list'));
    if ( ! empty($this->data)) {
        $this->data['Page']['title'] = $this->data['Post']['title'];
        $this->data['Page']['layout'] = 'index';
        debug($this->data);
        if ($this->Post->saveAll($this->data)) {
            $this->Session->setFlash('Your post has been saved', 'flash_good');
            $this->redirect($this->here);
        }
    }
}
UPDATE #2: Should I just do this manually?
The problem is that the join tables doesn't have things saved in it. Is there something I'm missing?
UPDATE #3 RabidFire gave me a solution. I already did this before and am quite surprised as so why it didn't work. Thus, me asking here. The reason I think there is something wrong. I don't know where:
Post beforeSave:
function beforeSave()
{
    if (empty($this->id))
    {
        $this->data[$this->name]['uri'] = $this->getUniqueUrl($this->data[$this->name]['title']);
    }
    if (isset($this->data['CategoryPost']['category_id']) && is_array($this->data['CategoryPost']['category_id'])) {
        echo 'test';
        $categoryPosts = array();
        foreach ($this->data['CategoryPost']['category_id'] as $categoryId) {
            $categoryPost = array(
                'category_id' => $categoryId
            );
            array_push($categoryPosts, $categoryPost);
        }
        $this->data['CategoryPost'] = $categoryPosts;
    }
    debug($this->data); // Gives RabidFire's correct array for saving.
    return true;
}
My Post action:
function admin_add() {
    // pr(Debugger::trace());
    $this->set('categories', $this->Post->CategoryPost->Category->find('list'));
    if ( ! empty($this->data)) {
        $this->data['Page']['title'] = $this->data['Post']['title'];
        $this->data['Page']['layout'] = 'index';
        debug($this->data); // First debug is giving the correct array as above.
        if ($this->Post->saveAll($this->data)) {
            debug($this->data); // STILL gives the above array. which shouldn't be because of the beforeSave in the Post Model 
            // $this->Session->setFlash('Your post has been saved', 'flash_good');
            // $this->redirect($this->here);
        }
    }
}
© Stack Overflow or respective owner