Php CodeIgniter数据映射器保存一对多1:n

Php CodeIgniter数据映射器保存一对多1:n,php,codeigniter,codeigniter-datamapper,Php,Codeigniter,Codeigniter Datamapper,我正在使用codeigniter和datamapper创建一个发票应用程序 一张发票包含多个发票项 我正在尝试根据发票保存新的发票项目 如果我这样做: $invoice = new Invoice(1474); $invoice_item1 = new Invoice_item(); $invoice_item1->description = 'item 1'; $invoice_item2 = new Invoice_item(); $invoice_item2->desc

我正在使用codeigniter和datamapper创建一个发票应用程序

一张发票包含多个发票项

我正在尝试根据发票保存新的发票项目

如果我这样做:

$invoice = new Invoice(1474);    
$invoice_item1 = new Invoice_item();
$invoice_item1->description = 'item 1';
$invoice_item2 = new Invoice_item();
$invoice_item2->description = 'item 2';
$items = array($invoice_item1, $invoice_item2);    
foreach ($items as $item) {
  $item->save($invoice);
}
这很好,但我希望我能做这样的事情:

$invoice = new Invoice(1474);    
$invoice_item1 = new Invoice_item();
$invoice_item1->description = 'item 1';
$invoice_item2 = new Invoice_item();
$invoice_item2->description = 'item 2';
$items = array($invoice_item1, $invoice_item2);
$invoice->save($items);
$invoice->save($invoice_item); 
public function save() {
    // passing arguments the way they came, 
    // it's also more robust against changes in datamapper with func_get_args() + call_user_func()
    call_user_func_array(array('parent', 'save'), func_get_args());

    $this->where('id', $this->id)->update('invoice_no', $this->id);
}
有可能这样做吗?非常感谢任何帮助或建议,谢谢

更新:

发票模型

class Invoice extends DataMapper {

  public $has_many = array('invoice_item');
  public $has_one = array('customer');

  public function __construct($id = NULL) {
    parent::__construct($id);
  }

  public function getTotal() {
    $this->invoice_item->get_iterated();
    $total = 0;
    foreach ($this->invoice_item as $item) {
      $total += $item->price * $item->qty;
    }
    return number_format($total, 2);
  }

  public function getStatus() {
    if (!$this->paid) {
      $status = date_diff(date_create(date('Y-m-d')), date_create($this->invoice_date))->format('%a') . " days";
    } else {
      $status = 'PAID';
    }
    return $status;
  }

  public function save() {
    parent::save(); 
    $this->where('id', $this->id)->update('invoice_no', $this->id);
  }
}
发票项目模型

class Invoice_item extends DataMapper {

  public $has_one = array('invoice');

  public function __construct($id = NULL) {
    parent::__construct($id);
  }

}

如果将magick
save{relationname}
函数与数组一起使用,它应该可以执行您想要的操作,请尝试:

$invoice->save_invoice_item($items);
如果将数组传递给
save()
方法,它会尝试将其中的每一项解释为一个关系,要使“*-many”起作用,您需要在其中包含第二个数组,因此将发票项包装两次也可以:

$invoice->save(array(array($invoice_item1, $invoice_item2));
不幸的是,DM似乎无法处理相关对象尚未首先保存到数据库的情况(猜测正确的顺序并不容易)。所以你必须这样写:

$invoice_item1->save();
$invoice_item2->save();
$invoice->save(array(array($invoice_item1, $invoice_item2)));
保存后,这将使用发票的ID更新发票项目行。当然,这并不理想,因为有时数据库持有的发票项没有相关发票,建议在这里使用事务

您可以先保存不带项目的
发票
,然后使用发票实例保存项目,从而切换订单:

$invoice->save();
$invoice_item = new Invoice_item;
// ...
$invoice_item->save($invoice);
您可以通过从
$this->db->querys
转储查询来检查发生了什么

更新 在您的
Invoice
模型中,您正在覆盖原始的
save()
方法,但是您没有将参数传递给
parent::save()
,因此如下行:

$invoice = new Invoice(1474);    
$invoice_item1 = new Invoice_item();
$invoice_item1->description = 'item 1';
$invoice_item2 = new Invoice_item();
$invoice_item2->description = 'item 2';
$items = array($invoice_item1, $invoice_item2);
$invoice->save($items);
$invoice->save($invoice_item); 
public function save() {
    // passing arguments the way they came, 
    // it's also more robust against changes in datamapper with func_get_args() + call_user_func()
    call_user_func_array(array('parent', 'save'), func_get_args());

    $this->where('id', $this->id)->update('invoice_no', $this->id);
}
将忽略该参数(php不会抱怨需要更多参数)。 你可能想写这样的东西:

$invoice = new Invoice(1474);    
$invoice_item1 = new Invoice_item();
$invoice_item1->description = 'item 1';
$invoice_item2 = new Invoice_item();
$invoice_item2->description = 'item 2';
$items = array($invoice_item1, $invoice_item2);
$invoice->save($items);
$invoice->save($invoice_item); 
public function save() {
    // passing arguments the way they came, 
    // it's also more robust against changes in datamapper with func_get_args() + call_user_func()
    call_user_func_array(array('parent', 'save'), func_get_args());

    $this->where('id', $this->id)->update('invoice_no', $this->id);
}

您最初的示例之所以有效,是因为您使用了
Invoice\u项
class的
save()
方法进行了保存。

非常感谢您的回答。我尝试了你的两个建议,但似乎都没有保存相关的发票项目:(哦,我没有意识到,在保存发票项目的最终发票之前,您没有先保存发票项目。不幸的是,DM在将尚未存在的对象保存为关联对象时,似乎无法使用这些对象。更新了答案。再次感谢您的更新。但似乎仍然无法使用。感谢提示:$this->db->query是的。这真的很有用。我可以看到正在保存的发票项,但既没有$invoice->save\u invoice\u item($items);也没有$invoice->save(数组($invoice\u item1,$invoice\u item2)));更新发票id字段,使其与发票保持无关。在我的测试环境中,这两个字段都起作用。那么,关系中一定存在命名或其他问题。您是否可以发布模型或至少
$有一个
$有多个
部分(如果您使用这些部分,可能是
$表
)?我添加了对似乎正在发生的事情的解释。