0

我正在使用 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);
  }
}

发票项目模型

class Invoice_item extends DataMapper {

  public $has_one = array('invoice');

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

}

4

1 回答 1

2

If you use the magick save_{relationname} function with an array it should do what you want, try:

$invoice->save_invoice_item($items);

If you pass an array to the save() method it will try to interpret every item of it as a relation and for a "*-many" to work, you need a second array inside it, so wrapping your invoice items twice should do it too:

$invoice->save(array(array($invoice_item1, $invoice_item2));

Unfortunately DM doesn't seem to handle the case when the related objects are not saved already to the database first (guessing the right order would not be trivial). So you would have to write it like:

$invoice_item1->save();
$invoice_item2->save();
$invoice->save(array(array($invoice_item1, $invoice_item2)));

This will update the invoice_item rows with the invoice's ID once that saved. This ofcourse is not ideal since there's a moment in time when the database hold's invoice item's without related invoice, using transactions here would be recommended.

You can switch up the order by first saving the Invoice without items and than saving the items with the invoice instance:

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

You can check what's happening by dumping the queries from $this->db->queries.

Update

In your Invoice model you are overwriting the original save() method, but you don't pass arguments to the parent::save() so the lines like this:

$invoice->save($invoice_item); 

Will just ignore the parameter (php don't complain for more parameters then required). You probably wanted to write something like this:

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

Your original example worked because you saving with the Invoice_item class's save() method.

于 2013-04-26T07:27:56.813 回答