Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CakePHP belongsToMany jointable

I'm making a blog and I want to be able to assign multiple categories or tags for an article and an article can have multiple categories.

This is what I have in my database: articles, categories and the join table articles_categories.

PROJECT:

enter image description here

JOIN TABLE:

enter image description here

in my Table/ArticlesTable.php:

 public function initialize(array $config)
 {
     $this->addBehavior('Timestamp');
     $this->belongsToMany('Categories', [
         'alias' => 'Categories',
         'foreignKey' => 'article_id',
         'targetForeignKey' => 'category_id',
         'joinTable' => 'articles_categories'
     ]);
 }

in my Table/CategoriesTable.php:

 public function initialize(array $config)
 {
     $this->table('categories');
     $this->displayField('name');
     $this->primaryKey('id');
     $this->addBehavior('Timestamp');

     $this->belongsToMany('Articles', [
         'alias' => 'Articles',
         'foreignKey' => 'category_id',
         'targetForeignKey' => 'article_id',
         'joinTable' => 'articles_categories'
     ]);
 }

When a user adds an article, it needs to add the article and then the ids in the join table here's my ArticlesController/add method:

 public function add()
 {
     $article = $this->Articles->newEntity();

     if ($this->request->is('post'))
     {
         $article = $this->Articles->patchEntity($article, $this->request->data);
         $article->user_id = $this->Auth->user('id');

         if ($result = $this->Articles->save($article))
         {
             $this->Flash->success(__('Your article has been saved.'));
             return $this->redirect(['action' => 'index']);
         }
         $this->Flash->error(__('Unable to add your article.'));
     }
     $this->set(['article'=>$article,'buttontext'=>'Add Article']);
     $categories = $this->Articles->Categories->find('list');
    $this->set(compact('categories'));
 }

add.ctp view:

echo $this->Form->create($article, ['class' => 'form-group']); echo
$this->Form->input('articlecategory',['options' =>
$categories,'id'=>'magicselect','multiple'=>true,'class'=>'form-control']);
echo $this->Form->input('title',
['class'=>'form-control',
    'maxlength'=>'50']); echo $this->Form->input('body',
['rows' => '8',
    'class'=>'form-control',
    'style'=>'margin-bottom:10px;resize: none',
    'maxlength'=>'5000']); echo $this->Form->button(__($buttontext), ['class'=>'btn btn-success']);
echo $this->Form->end();

and what I get after submitting the form debug($this->request->data):

[
    'articles_categories' => [
        (int) 0 => '1'
    ],
    'title' => 'test article',
    'body' => 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.'
]

My problem is that I'm not sure if my associations are correct. How do I automatically insert the data in the join table?

like image 544
user3813360 Avatar asked May 28 '26 16:05

user3813360


1 Answers

The property name

That is not the correct format for a belongsToMany association, see

  • http://book.cakephp.org/3.0/en/orm/associations.html#belongstomany-associations
  • http://book.cakephp.org/3.0/en/views/helpers/form.html#associated-form-inputs

The property name should by default be the underscored, plural name of the association, so in this case categories.

The magic _ids key

Since you want to link your article to already existing categories, you should additionally use the magic _ids key to pass the IDs of the selected categories, the marshaller will then take care of the rest, that is pick and insert the appropriate Category entities based on the given IDs, see

http://book.cakephp.org/3.0/en/orm/saving-data.html#converting-belongstomany-data

All you need to do is to append it to the field/propertyname, like categories._ids, ie your form input should be defined like this:

$this->Form->input('categories._ids', [
    'options' => $categories,
    'id' => 'magicselect',
    'multiple' => true,
    'class' => 'form-control'
]);

Note that it's not necessary to explicitly pass the options, if you follow the conventions, ie use the underscored plural of the association name, then the form helper will be able to automagically pick up the variable just like it does for other input fields.

like image 128
ndm Avatar answered Jun 02 '26 00:06

ndm