简体   繁体   English

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

[英]CodeIgniter Datamapper save one to many 1:n

I'm using codeigniter and datamapper to create an invoicing app. 我正在使用codeigniter和datamapper来创建一个发票应用程序。

an Invoice has_many Invoice_item 发票has_many Invoice_item

I'm trying to save new Invoice_items against an Invoice. 我正在尝试针对发票保存新的Invoice_items。

If i do the following: 如果我做以下事情:

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

This works fine but I was hoping I could do something like this: 这很好但我希望我可以做这样的事情:

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

Is it possible to do it this way? 有可能这样做吗? Any help or advice much appreciated, thanks. 任何帮助或建议非常感谢,谢谢。

Update: 更新:

Invoice Model 发票模型

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 Model Invoice_item模型

class Invoice_item extends DataMapper {

  public $has_one = array('invoice');

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

} }

If you use the magick save_{relationname} function with an array it should do what you want, try: 如果你使用magick save_{relationname}函数和数组它应该做你想要的,尝试:

$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: 如果将数组传递给save()方法,它将尝试将其中的每个项目解释为关系,并且要使“* -many”工作,您需要在其中包含第二个数组,因此将发票项目包装两次应该执行它也:

$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). 不幸的是,当相关对象没有首先保存到数据库时,DM似乎没有处理这种情况(猜测正确的顺序不会是微不足道的)。 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. 一旦保存,这将使用发票的ID更新invoice_item行。 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而不是使用发票实例保存项目来切换订单:

$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 . 您可以通过从$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()方法,但是您不会将参数传递给parent::save()因此这样的行如下所示:

$invoice->save($invoice_item); 

Will just ignore the parameter (php don't complain for more parameters then required). 只是忽略参数(php不要抱怨更多参数然后需要)。 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. 您的原始示例有效,因为您使用Invoice_item类的save()方法进行save()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM