使用额外字段保存HABTM?

时间:2011-04-26 19:46:09

标签: php mysql cakephp cakephp-1.3

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

正在保存订单,但产品不是。

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

在订单模型中,我设置了$hasAndBelongsToMany = 'Product';

orders_products表格上的

我还有一些额外的字段:order_idproduct_idpricequantity来获取销售价格和销售数量。

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

  

$这 - >命令中─>白水($数据);

以下是$ 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
                )

        )

)

订单会保存到订单表中,但不会将任何内容保存到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

有什么想法吗?

6 个答案:

答案 0 :(得分:9)

HABTM过度销售。很多时候它无法满足需求,例如当您有额外的数据存储时。你最好在模型之间做一个hasMany / belongsTo关系。

取自CakePHP书:

  

HABTM成为时该怎么办   复杂吗

     

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

     

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

     

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

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

  • Order hasMany LineItem
  • LineItem belongsTo OrderProduct

答案 1 :(得分: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

答案 2 :(得分:1)

我使用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记录。

答案 3 :(得分:0)

orders_products表格中保存其他数据对我来说似乎不太好。如果订单包含多个产品,该怎么办?您是否在orders_products表格中存储了每个条目的订单总金额?为什么不将这些信息存储在Order中?这对我来说更有意义。

您的错误似乎来自破碎的数据模型。

答案 4 :(得分:0)

您可以使用上一个解决方案,但如果还要更新父表,则必须解除绑定。 在我的示例中,我有一个表 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']);

答案 5 :(得分:0)

可能是您的orders_products表没有自己的主键。除非你的表看起来像什么,否则你会收到此错误 像这样

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

我刚刚遇到同样的问题。对不起这么简单的答案没有 很快就能找到你。