Not able to Edit with Associations

I have an Fbpage Table, Keywords Table, and Fbpagekeywords Table. fbpages can be connected to multiple keywords, and keywords can be connected to multiple fbpages, I store the connection id in the Fbpagekeywords table. I can already add an Fbpage with multiple keywords, and I can add keywords with multiple fbpages. My problem is when editing, when I click submit, it doesn’t update the already saved data, it adds another batch of rows instead.

This is my Fbpage/edit.php

<h1>Edit FB Page</h1>

<?php

  echo $this->Form->create($fbpage);
  echo $this->Form->control('page_title', ['label' => 'Facebook Page Title']);
  echo $this->Form->control('page_url',  ['label' => 'Facebook Page URL']);
  echo $this->Form->control('pageid',  ['label' => 'Facebook Page ID']);
  echo '<label for="fb_caption">Facebook Access Token</label>' . $this->Form->textarea('fb_access_token', ['rows' => '15', 'cols' => '5']);
  echo '<label class="article-fb-caption">Assign keywords to Facebook Page:</label>';
  echo '<div class="article-fb-selection">';
?>

<?php
  foreach($keywords as $index => $keyword) :
    $checked = false;
    foreach($fbpage->fbpagekeywords as $page_keyword_item) {
      if($page_keyword_item['keyword_id'] === $keyword['id']) {
        $checked = true;
        // echo $page_keyword_item->keyword;
      } 
    }
  // pr($fbpage)
  // echo $keyword->keyword;
?>

<?php

  echo '<span class="fb-keyword-option">' 
        . $this->Form->checkbox( 'fbpagekeywords.'.$index.'.keyword_id',
          ['value' => $keyword['id'],
           'hiddenField' => false,
           'checked' => $checked
          ]) 
        . $keyword->keyword . '</span>';
  
  endforeach;

  echo "</div>";

  echo '<span class="create-btn">' . $this->Form->button(__('Update')) . '</span>';
  echo $this->Form->end();

?>

This is my FBpage edit controller

public function edit($id) {
    $this->loadModel('Fbpagekeywords');
    $this->loadModel('Keywords');
    $keywords = $this->Keywords->find('all')->order(['keyword' => 'ASC']);
    $fbpage_keywords = $this->Fbpagekeywords->find('all');

    $associated = ['Fbpagekeywords'];
    $Fbpages = $this->getTableLocator()->get('Fbpages');
    $fbpage = $Fbpages->get($id, ['contain' => $associated]);

    if ($this->request->is(['post', 'put'])) {

      $this->Fbpages->patchEntity($fbpage, $this->request->getData(), ['associated' => 'Fbpagekeywords']);
      if ($this->Fbpages->save($fbpage)) {
          $this->Flash->success(__('Facebook Page has been updated.'));
          return $this->redirect(['action' => 'index']);
      }
      $this->Flash->error(__('Unable to update the Facebook Page.'));
    }

    $this->set(compact('fbpage', 'keywords'));
  }

this is the result when i ran

debug($this->Fbpages->patchEntity($fbpage, $this->request->getData(), ['associated' => 'Fbpagekeywords']));
APP/Controller\FbpagesController.php (line 95)
object(App\Model\Entity\Fbpage) id:0 {
'id' => (int) 18
'page_title' => 'test empty keywords'
'page_url' => 'test empty keywords'
'pageid' => 'awdawd'
'fb_access_token' => 'awdawd'
'created' => object(Cake\I18n\FrozenTime) id:1 { }
'modified' => object(Cake\I18n\FrozenTime) id:2 { }
'fbpagekeywords' => [
(int) 0 => object(App\Model\Entity\Fbpagekeyword) id:3 {
'keyword_id' => (int) 40
'[new]' => true
'[accessible]' => [ ]
'[dirty]' => [ ]
'[original]' => [ ]
'[virtual]' => [ ]
'[hasErrors]' => false
'[errors]' => [ ]
'[invalid]' => [ ]
'[repository]' => 'Fbpagekeywords'
},
(int) 1 => object(App\Model\Entity\Fbpagekeyword) id:4 {
'keyword_id' => (int) 42
'[new]' => true
'[accessible]' => [ ]
'[dirty]' => [ ]
'[original]' => [ ]
'[virtual]' => [ ]
'[hasErrors]' => false
'[errors]' => [ ]
'[invalid]' => [ ]
'[repository]' => 'Fbpagekeywords'
},
(int) 2 => object(App\Model\Entity\Fbpagekeyword) id:5 {
'keyword_id' => (int) 35
'[new]' => true
'[accessible]' => [ ]
'[dirty]' => [ ]
'[original]' => [ ]
'[virtual]' => [ ]
'[hasErrors]' => false
'[errors]' => [ ]
'[invalid]' => [ ]
'[repository]' => 'Fbpagekeywords'
},
(int) 3 => object(App\Model\Entity\Fbpagekeyword) id:6 {
'keyword_id' => (int) 53
'[new]' => true
'[accessible]' => [ ]
'[dirty]' => [ ]
'[original]' => [ ]
'[virtual]' => [ ]
'[hasErrors]' => false
'[errors]' => [ ]
'[invalid]' => [ ]
'[repository]' => 'Fbpagekeywords'
},
]
'[new]' => false
'[accessible]' => [ ]
'[dirty]' => [ ]
'[original]' => [ ]
'[virtual]' => [ ]
'[hasErrors]' => false
'[errors]' => [ ]
'[invalid]' => [ ]
'[repository]' => 'Fbpages'
}

we’re spending way too much time trying to solve it and we really need some help. thank you

So, when you edit, you want the new list of keywords to completely replace the old list? Check out the saveStrategy setting on your association between those two tables, you want replace instead of append.

Hi, thank you very much for your reply! I was about to call it a day and I’m glad I checked this thread. I will be checking it now and will be back. Once again, thank you for your reply!

Hi Zuluru,

I’ve updated the saveStrategy in the tables and it seems to be working now as we’d like. But we have another problem though, this is still the same problem but it’s regarding with Articles and FBpages. You see we’re currently trying to match articles to which fb pages should they be shared using keywords. So we have this table called Fbpageposts that holds article_id, keyword_id, and page_id. When we run our keyword match making function, those articles with a keyword that corresponds to which fbpage are saved in this table along with the keyword_ids. so the initial data is something like this:

article_id | keyword_id | fbpage_id

  1        |          1             |         1
  2        |          2             |         2
  1        |          3             |         1

if I edit article_id 1, and assign it to an fbpage_id 4 then edit and save, it’s not able to retain the keyword_id of the previous data. is there a way where I can still replace but retain the data of a column?

So, Fbpageposts is your join table. Does it have a plain “id” field in addition to these other three fields? Any other fields in there that are going to throw in further wrinkles?

Hello Zuluru, Fbpagepost table indeed has its own id field. No more other fields/columns in this table.

Then you would probably want to include either the id or the keyword_id field in your form as a hidden value when you’re editing. In the former case, you might not need to use replace save strategy, as you’ll be editing an existing join record, but it’s potentially problematic in terms of things like the accessible setting or general security (if you don’t 100% trust all your users).

Hello, Zuluru. Thank you very much for your input. We’ve thought of this too, but we’ve decided to create another table that will hold the article_id and fbpage_id. The fbpageposts table will just hold the article_id, keyword_id, and fbpage_id and will be used whenever we have an article matched to a keyword and fbpage. This way, we can truly separate when we had to edit the article to which fbpage it is going to be shared to.

That does sound like probably a better, more representative data structure.

1 Like