Сохранение модели соединения - PullRequest
1 голос
/ 27 декабря 2010

Я уже некоторое время читаю кулинарную книгу и до сих пор не понимаю, как мне это сделать:

Моя первоначальная проблема заключалась в следующем: Связанная модель непроверяется

Из комментария RabidFire:

Если вы хотите подсчитать количество моделей категорий, с которыми связано новое сообщение (при сохранении), то вам необходимосделать это в функции beforeSave, как я уже упоминал.Поскольку вы сейчас настраиваете свои модели, вам не нужно нигде использовать правило множественного числа.Если вы действительно действительно хотите проверить список идентификаторов категорий по какой-то причине, то создайте модель соединения и проверьте category_id с помощью правила множественного числа.

Теперь у меня есть эти модели исейчас проверяю.Проблема в том, что данные не сохраняются в таблице соединений:

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'
        )
    );

Это новая форма:

<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>

Данные, которые я получаю из формы, имеют видследующее:

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
        )

)

ОБНОВЛЕНИЕ: действие контроллера // Действие контроллера

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);
        }
    }
}

ОБНОВЛЕНИЕ № 2: Должен ли я просто сделать это вручную?

Проблема в том, чтоВ таблицах объединения нет сохраненных вещей.Что-то мне не хватает?

удалено обновление # 3

Схема таблицы соединений:

CREATE TABLE IF NOT EXISTS `category_posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
);

Обновление: # 4

Поставлювсе о моем заявлении здесь в надежде сделать то, что я хочу сделать.

// Post Model
class Post extends AppModel {
    var $name = 'Post';
    var $hasMany = array(
        'CategoryPost' => array(
            'className' => 'CategoryPost'
        )
    );
    var $belongsTo = array(
        'Page' => array(
            'className' => 'Page'
        )
    );
    var $actsAs = array('Containable');
    var $virtualFields = array(
        'date_posted' => 'DATE_SUB(Post.created, INTERVAL 7 DAY)'
    );

    var $order = array('Post.modified' => 'desc');
    var $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'body' => array(
            'rule' => 'notEmpty'
        )
    );

    function getFeed() {
        if ($posts = $this->find('all', array('limit' => 20, 'order' => 'Post.created DESC'))) {
            return $posts;
        }
        return FALSE;
    }

    function getRecentPosts() {
        $conditions = array(
            'Post.created < (curdate() + interval 7 day)',
        );
        return $this->find('all', array('limit' => 8, 'conditions' => $conditions));
    }
}


// CategoryPost Model
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'
        )
    );

    var $actsAs = array('Containable');
}

class Page extends AppModel {
    var $name = 'Page';
    var $order = array('Page.modified' => 'desc');

    var $hasOne = array(
        'Post' => array(
            'className' => 'Post'
        ));

    var $hasMany = array(
        'Snippet' => array(
            'className' => 'Snippet'
        ));

    var $validate = array(
        'title' => array(
            'rule' => 'notEmpty'
        ),
        'uris' => array(
            'slugged' => array(
                'rule' => '/^[a-z0-9-_]+$/i',
                'message' => 'This field should only contain characters, numbers, dashes and underscores'
            ),
            'uniqueUrl' => array(
                'rule' => array('uniqueUrl'),
                'message' => 'A page has already acquired this url'
            )
        ),
        'meta_keywords' => array(
            'rule' => 'notEmpty'
        ),
        'meta_description' => array(
            'rule' => 'notEmpty'
        ),
        'layout' => array(
            'rule' => 'notEmpty'
        )
    );
}


// Form
<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>


// Posts#admin_add
function admin_add() {
    $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';


        if ($this->Post->saveAll($this->data, array('validate' => 'first'))) {
            $this->Session->setFlash('Your post has been saved', 'flash_good');
            $this->redirect(array('action' => 'admin_add'));
        }

    }
}


// Table structure
CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `page_id` int(11) NOT NULL,
  `title` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `uri` varchar(127) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `body` text COLLATE utf8_unicode_ci,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=163 ;


CREATE TABLE IF NOT EXISTS `pages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `uris` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `meta_keywords` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `meta_description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `layout` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=164 ;


CREATE TABLE IF NOT EXISTS `category_posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=36 ;

Ответы [ 2 ]

2 голосов
/ 28 декабря 2010

Ваши данные не сохраняются, потому что вы пытаетесь сохранить массив в поле.

[CategoryPost] => Array
    (
        [category_id] => Array
            (
                [0] => 1
                [1] => 2
            )
    )

Форма данных должна выглядеть следующим образом:

[CategoryPost] => Array
    (
        [0] => Array
            (
                [category_id] => 1
            )
        [1] => Array
            (
                [category_id] => 2
            )
    )

Для этого вы можете использовать следующий код:

// Correcting data form of CategoryPost
$categoryPosts = array();
foreach ($this->data['CategoryPost']['category_id'] as $categoryId) {
    $categoryPost = array(
        'category_id' => $categoryId
    );
    array_push($categoryPosts, $categoryPost);
}
$this->data['CategoryPost'] = $categoryPosts;

Этот код может быть помещен в контроллер до вызова saveAll.Если вы обнаружите, что вы используете этот код в нескольких местах, вы можете преобразовать его в модель beforeSave:

function beforeSave() {
    if (isset($this->data['CategoryPost']['category_id']) && is_array($this->data['CategoryPost']['category_id'])) {
        ... // above code
    }
}

Опубликовать схему таблицы соединений (имя таблицы и поля) для возможноголучшая альтернатива.


Хорошо, у меня ушло немного мозгов, но я наконец понял это.Ваш последний комментарий вроде расставил все по местам.Вот простое исправление:

На ваш взгляд:

echo $this->Form->input('CategoryPost.0.category_id', array('multiple' => 'checkbox'));

Это должно привести к тому, что данные будут иметь следующую форму:

[CategoryPost] => Array
    (
        [0] => Array
            (
                [category_id] => Array
                    (
                        [0] => 1
                        [1] => 2
                    )
            )
    )

Вам нужно, чтобы получить его в этой форме из-за отношения hasMany между Post и CategoryPost - , или оно даже не будет подтверждено. После внесения этого измененияbeforeSave функция будет вызвана.СЕЙЧАС внесите необходимые изменения в beforeSave, чтобы он заработал!Отладка $this->data поможет.Я оставляю вам эту часть, потому что у меня есть другая лучшая альтернатива :

1) Сдвиньте правило проверки multiple на Post модель:

class Post extends AppModel { 
    ...
    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'
        )
    );
    ...
}

2) Измените представление соответственно:

echo $this->Form->input('Post.category_id', array('multiple' => 'checkbox'));

3) Сдвиньте beforeSave на Post модель:

function beforeSave() {
    if (isset($this->data['Post']['category_id']) && is_array($this->data['Post']['category_id'])) {
        $categoryPosts = array();
        foreach ($this->data['Post']['category_id'] as $categoryId) {
            $categoryPost = array(
                'category_id' => $categoryId
            );
            array_push($categoryPosts, $categoryPost);
        }
        $this->data['CategoryPost'] = $categoryPosts;
    }
    return true;
}

Это должно держать вещи красивыми и гладкими.Проверьте обе альтернативы и дайте мне знать, если это работает!: D

0 голосов
/ 27 декабря 2010

Я думаю, что элемент для множественного выбора должен иметь имя, подобное этому:

echo $ this-> Form-> input ('Category', массив ('множественный' => 'флажок'));

Для лучших результатов создайте резервную копию вашего файла представления и воссоздайте ее, используя консольный скрипт bake.

...