2010-12-27 7 views
1

Ich habe für eine Weile jetzt und immer noch das Kochbuch zu lesen bekommt nicht, wie ich soll, dies tun:Speicher ein Join Modell

Mein ursprüngliches Problem war: A related Model isn't being validated

Aus RabidFire des commment:

Wenn Sie die Anzahl der Kategorie Modelle zählen möchten, dass eine neue Post ist zugeordnet (beim speichern), können Sie dann Notwendigkeit, dies zu tun in der before funktionieren wie ich erwähnt habe. Da Sie Ihre Modelle derzeit eingerichtet haben, müssen Sie die multiple Regel nirgends verwenden. Wenn Sie wirklich, wirklich wollen gegen eine Liste der Kategorie IDs aus irgendeinem Grund zu validieren, dann erstellen Sie ein Join-Modell, und validieren category_id mit der multiplen Regel dort.

Jetzt habe ich diese Modelle und validiere jetzt. Das Problem ist jetzt, dass die Daten nicht in der Tabelle Join gespeichert werden:

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

Dies ist die neue 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> 

Die Daten, die ich von der Form produzierte sich wie folgt:

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-Aktion // Controller-Aktion

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: Sollte ich das nur manuell tun?

Das Problem ist, dass die Join-Tabellen keine Dinge gespeichert haben. Gibt es etwas, das mir fehlt?

entfernt Update # 3

Join Tabellenschema:

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

Update: # 4

Ich werde alles über meine Anwendung setzen hier in der Hoffnung, sich zu tun, was ich will machen.

// 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 ; 
+0

Können Sie die Controller-Aktion hier hinzufügen? – Nigel

Antwort

0

Ich denke, dass das Element für Multiple-Choice-Namen wie diese haben soll:

echo $ this-> form-> Eingang ('Kategorie', array ('multiple' => 'Option'));

Um bessere Ergebnisse zu erzielen, erstellen Sie eine Sicherungskopie Ihrer Ansichtsdatei und erstellen Sie sie mit dem Konsolen-Bake-Skript neu.

+0

Wenn Sie die Frage lesen, sehen Sie die vorherige Frage, die ich gestellt habe. Dies war das ursprüngliche Setup. Ich habe mein aktuelles Setup geändert, um eine Validierung zu erhalten. –

+0

Wie auch immer, ich habe versucht, die App zu backen, aber es tut nicht die Validierung in den Kategorien. –

2

Ihre Daten werden nicht gespeichert, weil Sie versuchen, ein Array in einem Feld zu speichern.

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

Die Form der Daten sollte wie folgt aussehen:

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

Sie könnten den folgenden Code verwenden, um dies zu tun:

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

Dieser Code kann in der Steuerung gesetzt werden vor Anruf saveAll. Wenn Sie feststellen, dass Sie diesen Code an mehreren Stellen verwenden, können Sie es in das Modell des Refactoring beforeSave:

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

Beitrag das Schema Ihrer Join-Tabelle (Tabellenname und Felder) für eine möglicherweise bessere Alternative.


In Ordnung, es hat mich einige Gehirn-Racking, aber ich habe es endlich herausgefunden. Dein letzter Kommentar hat alles an Ort und Stelle gebracht. Hier ist die einfache Lösung:

Ihrer Ansicht:

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

Dies sollten die Daten verursachen in der folgenden Form sein:

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

Sie Notwendigkeit es haben in dieser Form, weil hasMany Beziehung zwischen Post und CategoryPost - oder es wird nicht einmal validieren. Nachdem Sie diese Änderung vorgenommen haben, wird die beforeSave-Funktion aufgerufen. JETZT die notwendigen Änderungen an beforeSave vornehmen, damit es funktioniert! Debuggen $this->data wird helfen. Ich lasse diesen Teil zu dir, weil ich eine andere haben bessere Alternative:

1) Verschieben Sie die multiple Gültigkeitsregel zum Post Modell:

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) Ändern Sie die Ansicht entsprechend:

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

3) verschieben des beforeSave auf das Post Modell:

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

Dies sollte die Dinge schön und glatt halten. Testen Sie beide Alternativen und lassen Sie mich wissen, ob es funktioniert! : D

+0

Ja, ich habe das schon gemacht und ich denke, das funktioniert. Ich könnte es nur anders codiert haben. Wie auch immer, ich werde schauen, ob es funktioniert. Ich war in Urlaub. –

+0

RabidFire, ich habe Ihren Code verwendet (ich habe diesen Code schon einmal ausprobiert) und es sieht so aus, als wenn er speichert, wird er vor dem Speichern wieder auf das alte Array zurückgesetzt. Ich bin verwirrt. –

+0

Ich habe sogar versucht, ein Sample hartcodieren und es funktioniert nicht: * $ this-> data ['CategoryPost'] [0] ['category_id'] = 1; * –

Verwandte Themen