2015-09-16 69 views
0

我想爲cakephp3應用程序編寫一個簡單的Tagging-Plugin。所以可以說我們有一個型號書籍和一個型號評論。對於每個模型,都應該可以附加標籤 - 只需添加一個行爲(在插件中):$this->addBehavior('Tag.Taggable')cakephp3:保存相關數據

我在數據庫中創建了兩個表格:tags, tagged_tags

表tagged_tags:

id | tag_id | tagged_id     | 
1 | 1  | 1       | 
2 | 2  | 1       | 

tagged_id是被標記的實體的ID。它所屬的信息是在另一個表中。 表標籤:

id | tag  | model      | 
1 | book | App\Model\Table\BooksTable | 
2 | nobook | App\Model\Table\ReviewsTable| 

顯然,只有第一個標籤屬於一本書。

class TaggableBehavior extends Behavior 
{ 
    // Some more code here 

    public function __construct(Table $table, array $config = []) 
    { 
     parent::__construct($table, $config); 
     $this->_table = $table; 

     $this->_table->belongsToMany('Tag.Tags', [ 
      'joinTable' => 'tagged_tags', 
      'foreignKey' => 'tagged_id', 
      'targetForeignKey' => 'tag_id', 
      'conditions' => [ 
       'Tags.model' => get_class($this->_table); 
      ] 
     ]); 

    } 
} 

檢索數據完美地工作。但是,儲蓄是一個問題:

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Tags.model' in 'where clause'

SQL Query:

SELECT TaggedTags.id AS TaggedTags__id , TaggedTags.tagged_id AS TaggedTags__tagged_id , TaggedTags.tag_id AS TaggedTags__tag_id FROM tagged_tags TaggedTags WHERE (tagged_id = :c0 AND Tags.model = :c1)

我不是那麼舒爾爲什麼這裏的CakePHP執行SELECT查詢,我不真的關心。爲什麼這個查詢導致錯誤很明顯。但我的錯誤在哪裏?它與'conditions' => ['Tags.model' => get_class($this->_table);有關。如果沒有這一點,我可以保存數據(但不能說至極標籤屬於一本書或不)

編輯:一些額外的信息

下面是完整的SQL語句,在調試套件顯示http://freetexthost.com/tc3s46nugi

控制器代碼:

public function add() 
{ 
    $book = $this->Books->newEntity(); 
    if ($this->request->is('post')) { 
     $book = $this->Books->patchEntity($book, $this->request->data); 
     if ($this->Books->save($book)) { 
      $this->Flash->success(__('The book has been saved.')); 
      return $this->redirect(['action' => 'index']); 
     } else { 
      $this->Flash->error(__('The book could not be saved. Please, try again.')); 
     } 
    } 

在行爲我有一些邏輯(複製/粘貼)形成書籤教程

public function beforeSave($event, $entity, $options) 
{ 
    if ($entity->tag_string) { 
     $entity->tags = $this->_buildTags($entity->tag_string); 
    } 
} 

protected function _buildTags($tagString) 
{ 
    $new = array_unique(array_map('trim', explode(',', $tagString))); 
    $out = []; 
    $query = $this->_table->Tags->find() 
     ->where([ 
      'Tags.tag IN' => $new, 
      'Tags.model' => $this->name() 
      ]); 
    // Remove existing tags from the list of new tags. 
    foreach ($query->extract('tag') as $existing) { 
     $index = array_search($existing, $new); 
     if ($index !== false) { 
      unset($new[$index]); 
     } 
    } 
    // Add existing tags. 
    foreach ($query as $tag) { 
     $tag['count'] = $tag['count']+1; 
     $out[] = $tag; 
    } 
    // Add new tags. 
    foreach ($new as $tag) { 
     $out[] = $this->_table->Tags->newEntity(['tag' => $tag, 'model' => $this->name(), 'count' => 0]); 
    } 
    return $out; 
} 
+0

你能提供你的代碼是在控制? – Ray

+0

我已將代碼添加到上面的帖子中。 –

+0

堆棧跟蹤:http://freetexthost.com/3msbh4rabw –

回答

0

如果您創建標籤模型並創建與其他模型的HABTM關係,您將創建易於標記的插件。

這裏有一些簡單的指導。

add.ctp

省略多個選擇標籤領域,而不是把標記文本字段(如tagsinput)。添加一些jquery標籤插件。當添加一個新的標籤(關鍵字)時,它會立即通過jquery post方法存儲在標籤表中。如果關鍵字存在於標籤表中,則不要再存儲它。

行爲

在從標記字段中的beforeSave方法處理值。 如果用逗號分隔值,你可以使用類似這樣(的CakePHP 2):

public function beforeSave($options = array()) 
    { 
     if(!empty($this->data['Article']['tagsinput'])) { 
      $tags = explode(',', $this->data['Article']['tagsinput']); 
      foreach ($tags as $tag) { 
       $tagKey = $this->Tag->find('first',array(
        'recursive' => -1, 
        'fields' => array('id'), 
        'conditions' => array('Tag.name' => $tag) 
        )); 
       $this->data['Tag']['Tag'][] = $tagKey['Tag']['id']; 
      } 
     } 
     return true; 
    } 

這在表中創建articles_tags HABTM關係並存儲該值。

edit.ctp

創建一個逗號分隔值:

<?php 
      $extract_tags = Hash::extract($this->data['Tag'],'{n}.name'); 
      $tags = implode(',', $extract_tags); 
      echo $this->Form->input('tagsinput', 
       array(
        'id' => 'tags', 
        'div'=>true, 
        'label'=>__('Tags'), 
        'class'=>'form-control input-lg', 
        'placeholder'=>__('Add keywords here'), 
        'value' => $tags 
        ) 
       ); 
      ?> 
+0

標記工作原理與我的解決方案。即使逗號分隔標籤樣式。問題是以belongsToMany方法保存數據。 –