HasMany - save association data


#1

Hello, I need help.
I have a two tables business_departments and companies with association type hasMany.
I need to modify companies list consisting in the department. Code was generated via bake, after that I modified it.

Controller
$businessDepartment = $this->BusinessDepartments->get($id, [
    'contain' => ['Companies']
]);
$companies = $this->BusinessDepartments->Companies->find('list')->where([
    'Companies.active' => true, 
    'Companies.type IS NOT' => 'service', 
    'OR' => [
        'business_department_id IS NULL',
        'business_department_id' => $id
    ]
])->distinct('Companies.id');
if ($this->request->is(['patch', 'post', 'put'])) {
    debug($this->request->getData());
    $businessDepartment = $this->BusinessDepartments->patchEntity($businessDepartment, $this->request->getData(), ['associated' => ['Companies']]);
    debug($businessDepartment);
    if ($this->BusinessDepartments->save($businessDepartment)) {
        $this->Flash->success(__('The business department has been saved.'));

        return $this->redirect(['action' => 'index']);
    }
    $this->Flash->error(__('The business department could not be saved. Please, try again.'));
}
$this->set(compact('businessDepartment', 'companies'));
Entity
protected $_accessible = [
    'name' => true,
    'companies' => true
];
Table
$this->hasMany('Companies', [
    'foreignKey' => 'business_department_id',
    // Tried it
    /*'dependent' => true,
    'cascadeCallbacks' => true,
    'saveStrategy' => 'replace'*/
]);
template
echo $this->Form->control('companies._ids', ['options' => $companies, 'multiple' => true, 'class' => 'multiple-find']);

First save with added companies is success, but when I tried to modify companies list (And if try to save without changes) I get error.
Can I save via *._ids or I need to make a custom code for it?
Thank you. I hope for quick answer.


#2

_ids should work, assuming CakePHP 3.x. We’ll need more details of what you’re trying and what error you’re getting to help resolve it.


#3

Version CakepPHP 3.5.10

Below debug($this->request->getData())

[
    'name' => 'Office',
    'companies' => [
        '_ids' => [
            (int) 0 => '21',
            (int) 1 => '29'
        ]
    ]
]

But after patchEntity, instead of searching for companies and changing the bussines_department_id fields in them, patchEnity tries to create new companies and displays an error. Below is a fragment of screenshot. debug($businessDepartment) and screenshot page


#4

Can you help me? I can make custom code, but if this accessible in cakephp 3, I would like to know about it.


#5

So, you have some departments, say A, B and C. And each department has some companies, say department A has companies M and N, B has S and T and C has X, Y and Z. And you’re trying to move company M from department A to department B?


#6

No. There are several departments and several companies. I need to add and remove companies from the editing department (not move them). When you first edit, I select the necessary companies and their business_department_id changes, with subsequent saving of the entity, an error occurs.


#7

So, companies can belong to multiple departments?


#8

No, Companies can belong to one department, department can has many companies. So I need to change business_department_id into companies table from business department editing. Usually I change foreignKey from entity in wich it located. As I wrote before, I can make custome code, but if _ids is working, I would like a use it. Have a nice day.


#9

Sorry, how is this different from the A/B/C scenario I posted earlier?


#10

you have validation errors in your company related data, thats why you cant save it, if you want to just use _ids as save try clearing companies field in your $businessDepartment i.e.

   $businessDepartment->unsetProperty('companies');

before patchEntity


#11

Thank you, it’s working :+1:. But why first save is success? :thinking:


#12

first save is success because

$businessDepartment = $this->BusinessDepartments->get($id, [
    'contain' => ['Companies']
]);

gives you empty ->companies and there are no validation errors in there : )