【问题标题】:Saving HABTM with extra fields?用额外的字段保存 HABTM?
【发布时间】:2011-04-26 19:46:09
【问题描述】:

我正在尝试保存订单以及订单中的产品。

订单正在保存,但产品未保存。

我有一个orders 表和一个products 表和一个orders_products 表。

在我设置的订单模型$hasAndBelongsToMany = 'Product';

orders_products 表上,我有几个额外的字段:order_idproduct_id 加上pricequantity 以获取销售价格和销售数量。

我正在通过以下方式保存数据:

$this->Order->saveAll($data);

$data 是这样的:

Array
(
    [Order] => Array
        (
            [user_email] => st@kr.com
            [billing_first] => Steve
            ... //more excluded
            [total] => 5000
        )

    [Product] => Array
        (
            [0] => Array
                (
                    [id] => 1
                    [price] => 5000.00
                    [quantity] => 1
                )

        )

)

订单保存到 order 表中,但没有保存到 orders_products 表中。我预计orders_products 表将保存[new_order_id], 1, 5000.00, 1

我确实收到了这条通知:

Notice (8): Undefined index: id [CORE/cake/libs/model/model.php, line 1391]

Model::__saveMulti() - CORE/cake/libs/model/model.php, line 1391
Model::save() - CORE/cake/libs/model/model.php, line 1355
Model::__save() - CORE/cake/libs/model/model.php, line 1778
Model::saveAll() - CORE/cake/libs/model/model.php, line 1673
CartsController::saveOrder() - APP/controllers/carts_controller.php, line 128
CartsController::checkout() - APP/controllers/carts_controller.php, line 172
Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 204
Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 171
[main] - APP/webroot/index.php, line 83

有什么想法吗?

【问题讨论】:

    标签: php mysql cakephp cakephp-1.3


    【解决方案1】:

    HABTM 超卖。很多时候它无法满足需求,例如当您有额外的数据要存储时。最好在模型之间建立 hasMany/belongsTo 关系。

    摘自 CakePHP 书:

    当HABTM变成 复杂吗?

    默认保存时 HasAndBelongsToMany 关系,Cake 将删除连接表上的所有行 在保存新的之前。例如,如果 你有一个有 10 个孩子的俱乐部 联系。然后你更新俱乐部 有 2 个孩子。俱乐部只会 有 2 个孩子,而不是 12 个。

    还要注意,如果你想添加更多 加入的字段(当它是 创建或元信息)这是 可以使用 HABTM 连接表,但是 重要的是要了解您 有一个简单的选择。

    两个模型之间的HasAndBelongsToMany 实际上是三个的简写 通过两个关联的模型 hasMany 和一个 belongsTo 关联。

    在你的情况下,我建议制作一个LineItem 模型并以这种方式加入所有内容:

    • OrderhasMany LineItem
    • LineItem 属于Order, Product

    【讨论】:

    【解决方案2】:

    HATBM 的工作方式非常奇怪。如果您真的需要 HATBM,我建议不要更改模型关联,而是使用有趣的速记方式在连接表中保存额外的数据字段。

    我遇到过很多次,这是最好的解决方案: 实际上,只是为了保存您的附加字段,您可以取消绑定所有 HATBM 关系并 添加一个新的 hasMany 绑定“即时”指向连接模型。 首先,您应该取消绑定现有的 HATBM 关系。

    $this->Order->unbindModel(array('hasAndBelongsToMany' => array('Product')));
    

    然后添加一个新的“on-the-fly” hasMany 绑定:

    $this->Order->bindModel(array('hasMany' => array('OrdersPost')));
    

    那么如果你的数据是:

    $this->data['Order']['id'] = '1';
    $this->data['OrdersPost'][0]['product_id'] = '15';
    $this->data['PostsTag'][0]['price'] = '5000.00';
    $this->data['PostsTag'][0]['quantity'] = '1';
    $this->data['OrdersPost'][1]['product_id'] = '16';
    $this->data['PostsTag'][1]['price'] = '4000.00';
    $this->data['PostsTag'][1]['quantity'] = '2';
    

    如上所述,HATBM 总是在插入新记录之前删除所有现有记录。 所以也许你应该在做之前注意这一点:

    $this->Order->saveAll($this->data);
    

    当您不想更改数据模型但仍需要其他功能时,此方法有效。 希望这可以帮助。 Original Solution and Credits HERE

    【讨论】:

      【解决方案3】:

      我在使用 SaveAll 时经常遇到的另一个问题是它不保存相关记录。在您的示例中,订单已保存,但未保存 OrderProducts(或 OrderItems)。我通常做的是这样的:

      if ($this->Order->save($this->data)) {
          for($i=0; $i<sizeof($this->data['OrderProduct']); $i++){
              $this->data['OrderProduct'][$i]['order_id'] = $this->Order->id;
          }
          $this->Order->OrderProduct->saveAll($this->data['OrderProduct']);
      }
      

      这里发生的是先保存订单,然后将其 ID 复制到每个 OrderProduct。然后保存 OrderProduct 记录。

      【讨论】:

        【解决方案4】:

        在你的orders_products 表中保存额外的数据对我来说似乎不是一个好主意。如果订单有超过 1 个产品怎么办。您是否将每个条目的订单总额存储在orders_products 表中?为什么不将这些信息存储在Order 中?这对我来说更有意义。

        您的错误似乎来自损坏的数据模型。

        【讨论】:

        • 我存储的是产品售价,而不是订单总额。我可以将许多产品绑定到 1 个订单,它会正常工作。我将在订单表中保存每种产品的售价、税金、总额等。如果我只存储总计而不是每件商品的售价,并且客户购买了 3 件商品然后想要退货,我们怎么知道要退还多少?
        • 好的,有道理。采用 Jason 的方法似乎是个好主意。
        【解决方案5】:

        您可以使用以前的解决方案,但是如果还必须更新父表,则必须取消绑定。 在我的示例中,我有一个表 Order 和一个表 Product。对于 Order.id ,我需要为每个产品添加两个额外的字段。看这个例子:

            $this->Order->create(); 
            $this->Order->unBindModel(array('hasAndBelongsToMany'=>array('Product')));
            $f  = $this->Order->save($this->data,false);
        
            /* Save extra columns in HABTM TABLE */
            $this->Order->bindModel(array('hasMany'=>array('OrderProduct')));
            $q = array();
            if (!isset($this->data['Product']))
            {
                $v  = false;
            }
            else
            {
                $v =true;
        
                for($i=0;$i<count($this->data['Product']);$i++)
                {
                    $this->data['OrderProduct'][$i]['order_id']     = $this->Order->getLastInsertID();
                    $this->data['OrderProduct'][$i]['product_id']   = $this->data['Product'][$i];
                    $this->data['OrderProduct'][$i]['quantity']         = $this->data['quantity'][$i];
                    $this->data['OrderProduct'][$i]['state_id']         = $this->data['State'][$i];
                }
            }
        
            $s  = $this->Order->OrderProduct->saveAll($this->data['OrderProduct']);
        

        【讨论】:

          【解决方案6】:

          可能是您的 orders_products 表没有自己的主键。除非您的表格看起来有些东西,否则您将收到此错误 像这样

          CREATE TABLE orders_products (
            id integer,
            order_id integer,
            product_id integer,
            ...
          

          我现在才遇到同样的问题。抱歉这么简单的回答没有 尽快联系您。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-10
            • 1970-01-01
            相关资源
            最近更新 更多