CakePHP 3 更新连接表中的数据

Posted

技术标签:

【中文标题】CakePHP 3 更新连接表中的数据【英文标题】:CakePHP 3 updating data in the join table 【发布时间】:2016-12-11 22:35:33 【问题描述】:

我在更新联接表中的现有数据时遇到问题。就这样吧……

我有 2 个模型 SalesOrders 和 Products,它们通过 LineItems 具有 belongsToMany 关联。

products
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int(11) unsigned    | NO   | PRI | NULL    | auto_increment |
| name        | int(11)             | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

sales_orders
+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| id           | int(11) unsigned    | NO   | PRI | NULL    | auto_increment |
| order_number | int(11)             | NO   |     | NULL    |                |
+--------------+---------------------+------+-----+---------+----------------+

line_items
+----------------+---------------------+------+-----+---------+----------------+
| Field          | Type                | Null | Key | Default | Extra          |
+----------------+---------------------+------+-----+---------+----------------+
| id             | int(11) unsigned    | NO   | PRI | NULL    | auto_increment |
| sales_order_id | int(11) unsigned    | NO   |     | NULL    |                |
| product_id     | int(11) unsigned    | NO   |     | NULL    |                |
| qty            | int(11)             | NO   |     | NULL    |                |
+----------------+---------------------+------+-----+---------+----------------+

按预期创建新的销售订单。我可以在添加新销售订单页面上向销售订单添加多个产品和数量。所有正确的数据都添加到连接表中。

我遇到的问题是当我尝试编辑现有销售订单时。例如,我想将某个行项目的数量从 5 更改为 2。我打开要修改的销售订单的编辑页面,更改所需行项目的数量,然后提交表单。表单提交成功,但连接表未更新。这似乎是我无法使用的非常基本的功能。我的所有代码都经过了一些小的修改。

SalesOrdersTable:

$this->belongsToMany('Products', [
    'foreignKey' => 'sales_order_id',
    'targetForeignKey' => 'product_id',
    'through' => 'LineItems',
]);

产品表:

$this->belongsToMany('SalesOrders', [
    'foreignKey' => 'product_id',
    'targetForeignKey' => 'sales_order_id',
    'through' => 'LineItems',
]);

LineItemsTable:

$this->belongsTo('Products', [
    'foreignKey' => 'product_id',
    'joinType' => 'INNER'
]);
$this->belongsTo('SalesOrders', [
    'foreignKey' => 'sales_order_id',
    'joinType' => 'INNER'
]);

SalesOrdersController 编辑:

public function edit($id = null)

    $salesOrder = $this->SalesOrders->get($id, [
        'contain' => ['Products']
    ]);
    if ($this->request->is(['patch', 'post', 'put'])) 
        $salesOrder = $this->SalesOrders->patchEntity($salesOrder, $this->request->data);
        if ($this->SalesOrders->save($salesOrder)) 
            $this->Flash->success(__('The sales order has been saved.'));

            return $this->redirect(['action' => 'index']);
         else 
            $this->Flash->error(__('The sales order could not be saved. Please, try again.'));
        
    
    $products = $this->SalesOrders->Products->find('list', ['limit' => 200]);
    $this->set(compact('salesOrder', 'products'));
    $this->set('_serialize', ['salesOrder']);

SalesOrders 模板编辑.ctp

echo $this->Form->input('order_number');
echo $this->Form->input('products.0.id', [
    'type' => 'select',
    'options' => $products
]);
echo $this->Form->input('products.0._joinData.qty');

在提交表单以将数量从 5 更改为 2 时,SalesOrder 实体如下所示。

object(App\Model\Entity\SalesOrder) 

    'id' => (int) 1,
    'order_number' => 'SO1111',
    'products' => [
        (int) 0 => object(App\Model\Entity\Product) 

            'id' => '1',
            'name' => 'Acme Widget 1',
            '_joinData' => object(App\Model\Entity\LineItem) 

                'id' => (int) 1,
                'product_id' => (int) 1,
                'sales_order_id' => (int) 1,
                'qty' => (int) 2,
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [
                    'qty' => true
                ],
                '[original]' => [
                    'qty' => (int) 5
                ],
                '[virtual]' => [],
                '[errors]' => [],
                '[invalid]' => [],
                '[repository]' => 'LineItems'

            ,
            '[new]' => false,
            '[accessible]' => [
                '*' => true,
                '_joinData' => true
            ],
            '[dirty]' => [
                '_joinData' => true
            ],
            '[original]' => [
                '_joinData' => object(App\Model\Entity\LineItem) 

                    'id' => (int) 1,
                    'product_id' => (int) 1,
                    'sales_order_id' => (int) 1,
                    'qty' => (int) 2,
                    '[new]' => false,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [
                        'qty' => true
                    ],
                    '[original]' => [
                        'qty' => (int) 5
                    ],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[invalid]' => [],
                    '[repository]' => 'LineItems'

                
            ],
            '[virtual]' => [],
            '[errors]' => [],
            '[invalid]' => [],
            '[repository]' => 'Products'

        
    ],
    '[new]' => false,
    '[accessible]' => [
        '*' => true
    ],
    '[dirty]' => [],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[invalid]' => [],
    '[repository]' => 'SalesOrders'


如您所见,SalesOrder 上的脏属性为空。 Products _joinData 已被修改并没有发现。

如果我添加 $salesOrders->dirty('products', true);就在调用 save() 之前,连接表被更新。虽然这可行,并且我可以编写一些逻辑来以这种方式处理更新,但我觉得有更好/正确的方法来做到这一点。

任何帮助表示赞赏,在此先感谢。

【问题讨论】:

【参考方案1】:

原来这是 3.3 中的一个蛋糕错误,直到 3.3.2 版本才解决。一旦我更新了一切都按预期工作。 github.com/cakephp/cakephp/pull/9276

【讨论】:

以上是关于CakePHP 3 更新连接表中的数据的主要内容,如果未能解决你的问题,请参考以下文章

没有任何数据库表的CakePHP模型或控制器

cakephp 2 上的自动完成 Ajax

将数据保存到 2 个表中 cakephp 3

从 CakePHP 4 中的数据库表中选择不同的年份

CakePHP:如何使用内部联接从两个表中检索数据?

Cakephp 3测试:如何从数据库加载记录?