множественный выбор для ассоциации hasMany в CakePHP 3

У меня есть две таблицы seller_businesses и seller_business_categories. и их ассоциация следующая

SellerBusinessesTable.php

    $this->hasMany('SellerBusinessCategories', [
        'foreignKey' => 'seller_business_id'
    ]);

SellerBusinessCategories.php

$this->belongsTo('SellerBusinesses', [
    'foreignKey' => 'seller_business_id',
    'joinType' => 'INNER'
]);

Я использую одну форму для сохранения данных в обеих таблицах

<?= $this->Form->create($sellerBusiness, ['type' => 'file']) ?>
<?= $this->Form->input('company_name') ?>
<?= $this->Form->input('proof', ['type' => 'file']) ?>
<?= $this->Form->input('seller_business_categories._category_ids', ['multiple' => true, 'options' => $categories]) ?>
<?= $this->Form->button('submit', ['type' => 'submit']) ?>
<?= $this->Form->end() ?>

И действие контроллера

$sellerBusiness = $this->SellerBusinesses->newEntity();
if ($this->request->is('post')) {
  $sellerBusiness->seller_id = $this->Auth->user('id');
  $sellerBusiness = $this->SellerBusinesses->patchEntity($sellerBusiness, $this->request->data, [
   'associated' => [
      'SellerBusinessCategories'
   ]
 ]);
 debug($sellerBusiness);
 if ($save_s_b = $this->SellerBusinesses->save($sellerBusiness)) {
    debug($save_s_b);
    $this->Flash->success(__('The seller business has been saved.'));

    return $this->redirect(['controller' => 'SellerBusinesses', 'action' => 'view', $save_s_b->id]);
  } else {
    $this->Flash->error(__('The seller business could not be saved. Please, try again.'));
  }
}

Но это не сохранение записи в таблицу seller_business_categories.

Из документа здесь

// Multiple select element for belongsToMany
echo $this->Form->input('tags._ids', [
    'type' => 'select',
    'multiple' => true,
    'options' => $tagList,
]);

Но это не работает. Есть ли другой способ для hasMany

debug($this->request->data); дает

'seller_business_categories' => [
        '_category_ids' => [
            (int) 0 => '1',
            (int) 1 => '2'
        ]
    ],

и debug($sellerBusiness); после patchEntity

object(App\Model\Entity\SellerBusiness) {

    'seller_id' => (int) 16,
    'company_name' => 'My company',
    'seller_business_categories' => [
        (int) 0 => object(App\Model\Entity\SellerBusinessCategory) {

            (int) 0 => '1',
            (int) 1 => '2',
            '[new]' => true,
            '[accessible]' => [
                '*' => true
            ],
            '[dirty]' => [
                (int) 0 => true,
                (int) 1 => true
            ],
            '[original]' => [],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'SellerBusinessCategories'

        }
    ],
    '[new]' => true,
    '[accessible]' => [
        '*' => true,
    ],
    '[dirty]' => [
        'seller_id' => true,
        'company_name' => true,
        'seller_business_categories' => true,
    ],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'SellerBusinesses'

}

и ошибка

Error: SQLSTATE[HY000]: 
General error: 1364 Field 'category_id' doesn't have a default value in seller_business_categories table

person Gaurav    schedule 24.08.2016    source источник
comment
вы должны настроить ассоциацию «многие ко многим», если хотите использовать формы с множественным выбором,   -  person Salines    schedule 25.08.2016
comment
как переопределить hasMany ? Нужно ли удалять hasMany перед установкой many-to-many?   -  person Gaurav    schedule 25.08.2016
comment
один продавец может иметь несколько предприятий, и несколько предприятий принадлежат одному продавцу. Вот почему существует отношение hasMany. Нет ли другого способа сделать это?   -  person Gaurav    schedule 25.08.2016
comment
Как я уже сказал, если вы хотите, чтобы пользователь выбирал больше значений из реляционных таблиц, вам нужно создать связь «многие ко многим». Есть еще один способ сохранить несколько значений в качестве метаданных, но не рекомендую его.   -  person Salines    schedule 25.08.2016


Ответы (1)


SellerBusinessesTable

$this->belongsToMany('Categories');

Таблица категорий

$this->belongsToMany('SellerBusinesses', [
    'foreignKey' => 'category_id',
    'targetForeignKey' => 'seller_business_id',
    'joinTable' => 'categories_seller_businesses'
]);

// Сводные таблицы должны быть отсортированы по алфавиту

bin/cake bake migration CreateCategoriesSellerBusinesses seller_business_id:integer category_id:integer created modified

CategoriesSellerBusinessesTable

$this->belongsTo('SellerBusinesses', [
    'foreignKey' => 'seller_business_id',
    'joinType' => 'INNER'
]);

$this->belongsTo('Categories', [
    'foreignKey' => 'category_id',
    'joinType' => 'INNER'
]);

Добавить.ctp

<?= $this->Form->create($sellerBusiness, ['type' => 'file']) ?>
    ...
    <?= $this->Form->input('categories', ['type' => 'select', 'options' => $categories, 'multiple' => 'select', 'label' => __('Categories')]) ?>
    ...
<?= $this->Form->end() ?>

Контролер бизнеса продавца

public function add()
{
    $sellerBusiness = $this->SellerBusinesses->newEntity();

    if ($this->request->is('post')) {

        $sellerBusiness = $this->SellerBusinesses->patchEntity($sellerBusiness, $this->request->data);

        $sellerBusiness->seller_id = $this->Auth->user('id');

        if(isset($this->request->data['categories'])) 
        {
            $sellerBusiness -> categories = $this->SellerBusinesses->Categories->find()->where(['id IN' => $this->request->data['categories']])->all()->toArray();
        } 

        if ($this->SellerBusinesses->save($sellerBusiness)) {

            $this->Flash->success(__('The sellerBusiness has been saved.'));

            return $this->redirect(['action' => 'index']);

        } else {

            $this->Flash->error(__('The seller could not be saved. Please, try again.'));

        }
    }

    $categories = $this -> SellerBusinesses-> Categories-> find('treeList');  

    $this->set(compact('sellerBusiness', 'categories'));
    $this->set('_serialize', ['sellerBusiness']);
person Jacek B Budzynski    schedule 25.08.2016