CodeIgniter Datamapper将一对多保存为1:n

时间:2013-04-25 21:22:28

标签: php codeigniter codeigniter-datamapper

我正在使用codeigniter和datamapper来创建帐单结算应用。

发票has_many Invoice_item

我正在尝试针对发票保存新的Invoice_items。

如果我执行以下操作:

$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);

有可能这样做吗?任何帮助或建议非常感谢,谢谢。

更新

发票模型

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);
  }
}

Invoice_item模型

class Invoice_item extends DataMapper {

  public $has_one = array('invoice');

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

}

1 个答案:

答案 0 :(得分:2)

如果你将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_item行。这个过程并不理想,因为数据库持有发票项目没有相关发票的时刻,建议使用此处的交易。

您可以通过先保存Invoice不包含项目而不是使用发票实例保存项目来切换订单:

$invoice->save();
$invoice_item = new Invoice_item;
// ...
$invoice_item->save($invoice);

您可以通过转储来自$this->db->queries的查询来检查发生了什么。

更新

在您的Invoice模型中,您正在覆盖原始的save()方法,但是您没有将参数传递给parent::save(),所以这样的行:

$invoice->save($invoice_item); 

只会忽略参数(php不会因为需要更多参数而抱怨)。 你可能想写这样的东西:

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_item类的save()方法保存。