Как правильно сохранить данные в BelongsToMany Ассоциации? - PullRequest
0 голосов
/ 26 апреля 2019

Мое приложение управляет заказами на ремонт для мастерской по электронным продуктам. когда я пытаюсь сохранить несколько одинаковых предметов (с одинаковым идентификатором), торт сохраняет только последнюю запись, игнорируя предыдущие. (В моем примере последний товар)

Я пытался настроить "saveStrategy" в модели, пытаясь с "append", но у меня не было результатов. Когда я вхожу в разные продукты (с разными идентификаторами), он без проблем сохраняет их.

Таблица:

Билеты

| id | client_id | reference |

Продукты

| id | code | description |

Products_Tickets

| id | ticket_id | product_id | qty | serial_number | notes |

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

[
    'client_id' => '1',
    'reference' => 'Client reference',
    'products' => [
        (int) 0 => [
            'id' => '1',
            '_joinData' => [
                'qty' => '1',
                'serial_number' => '123',
                'notes' => 'Not working'
            ]
        ],
        (int) 1 => [
            'id' => '1',
            '_joinData' => [
                'qty' => '1',
                'serial_number' => '345',
                'notes' => 'Not Working too'
            ]
        ],
        (int) 2 => [
            'id' => '1',
            '_joinData' => [
                'qty' => '1',
                'serial_number' => '567',
                'notes' => 'Note number 3'
            ]
        ],
        (int) 3 => [
            'id' => '1',
            '_joinData' => [
                'qty' => '1',
                'serial_number' => '978',
                'notes' => 'Another note'
            ]
        ]
    ]
]

Предполагается сохранить все данные, а не только последнее значение.

Как мне решить эту проблему?

1 Ответ

1 голос
/ 30 апреля 2019

Если я правильно понимаю ваше экономическое обоснование, вы создаете заявку для клиента и в той же транзакции добавляете в заявку 4 продукта.Итак, вы добавляете билет с 4-мя ассоциированными product_tickets (пунктами в билете).

В модели ProductsTable.php

    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('products');
        $this->setDisplayField('id');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp');

        $this->hasMany('ProductTickets', [
            'foreignKey' => 'product_id'
        ]);
    }

В модели TicketsTable.php

    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('tickets');
        $this->setDisplayField('id');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp');

        $this->hasMany('ProductTickets', [
            'foreignKey' => 'ticket_id'
        ]);
    }

В модели ProductTicketsTable.php

    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('product_tickets');
        $this->setDisplayField('id');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp');

        $this->belongsTo('Tickets', [
            'foreignKey' => 'ticket_id',
            'joinType' => 'INNER'
        ]);
        $this->belongsTo('Products', [
            'foreignKey' => 'product_id',
            'joinType' => 'INNER'
        ]);
    }

Тогда вы можете использовать только контроллер Tickets и сохранять его с соответствующими ProductTickets (позициями в билете).

Итак, в src\Template\Tickets\add.php, вы можете настроить форму следующим образом:

    <?= $this->Form->create($ticket) ?>
    <fieldset>
        <legend><?= __('Add Ticket') ?></legend>
        <?php
            echo $this->Form->control('client');
            echo $this->Form->control('reference');
        ?>
    </fieldset>
    <fieldset>
        <legend><?= __('Add Product_Tickets (Ticket items)') ?></legend>
       <table>
            <thead>
                <tr>
                    <th><?= __('Product') ?></th>
                    <th><?= __('Qty') ?></th>
                    <th><?= __('Serial Number') ?></th>
                    <th><?= __('Notes') ?></th>
                </tr>
            </thead>

            <tbody>
                <tr>
                <td>
                <?php echo $this->Form->control("product_tickets.0.product_id", []) ?>
                </td>   
                <td>
                <?php echo $this->Form->control("product_tickets.0.qty", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.0.serial_number", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.0.notes", []) ?>
                </td>
                </tr>
                <tr>
                <td>
                <?php echo $this->Form->control("product_tickets.1.product_id", []) ?>
                </td>   
                <td>
                <?php echo $this->Form->control("product_tickets.1.qty", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.1.serial_number", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.1.notes", []) ?>
                </td>
                </tr>
                <tr>
                <td>
                <?php echo $this->Form->control("product_tickets.2.product_id", []) ?>
                </td>   
                <td>
                <?php echo $this->Form->control("product_tickets.2.qty", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.2.serial_number", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.2.notes", []) ?>
                </td>
                </tr>
                <tr>
                <td>
                <?php echo $this->Form->control("product_tickets.3.product_id", []) ?>
                </td>   
                <td>
                <?php echo $this->Form->control("product_tickets.3.qty", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.3.serial_number", []) ?>
                </td>
                <td>
                <?php echo $this->Form->control("product_tickets.3.notes", []) ?>
                </td>
                </tr>


            </tbody>
            <tfoot>

            </tfoot>
        </table>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>

* ( Обратите внимание, есть другие / лучшие способы создания форм с несколькими связанными записями.)

В контроллере Tickets в методе add:

    public function add()
    {
        $ticket = $this->Tickets->newEntity();     
        if ($this->request->is('post')) {
            $data = $this->request->getData();
            $ticket = $this->Tickets->newEntity($data, [
                'associated' => ['ProductTickets']
            ]); 
            $ticket = $this->Tickets->patchEntity($ticket, $this->request->getData(),['associated' => 'ProductTickets'
              ]);
            if ($this->Tickets->save($ticket)) {
                $this->Flash->success(__('The ticket has been saved.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The ticket could not be saved. Please, try again.'));
        }
        $products = $this->Tickets->ProductTickets->Products->find('list');
        $this->set(compact('ticket', 'products'));
    }

Это работает для меня и должно сохранить любую комбинацию product_ids, связанную с ticket_id.Например, данные этого запроса сохраняются, как и ожидалось:

debug($this->request->getData());
[
    'client' => '1',
    'reference' => 'reference 1',
    'product_tickets' => [
        (int) 0 => [
            'product_id' => '1',
            'qty' => '12',
            'serial_number' => 'abc1234',
            'notes' => 'note1'
        ],
        (int) 1 => [
            'product_id' => '2',
            'qty' => '5',
            'serial_number' => '4321cba',
            'notes' => 'note2'
        ],
        (int) 2 => [
            'product_id' => '1',
            'qty' => '6',
            'serial_number' => 'a4b3c21',
            'notes' => 'note3'
        ],
        (int) 3 => [
            'product_id' => '3',
            'qty' => '21',
            'serial_number' => '4c3b2a1',
            'notes' => 'note4'
        ]
    ]
]

Согласно инструкции, Сохранение имеет много ассоциаций

Важное примечание, если какой-либо из 4 продуктов, которые вы планируетесохранить на тикете NULL, тогда вам нужно удалить этот продукт из данных запроса.Вы можете сделать это с помощью метода beforeMarshal в модели ProductTicketsTable.

Надеюсь, это то, что вы имели в виду и полезно.

Cheers,

D.

...