简体   繁体   中英

CodeIgniter Datamapper save one to many 1:n

I'm using codeigniter and datamapper to create an invoicing app.

an Invoice has_many Invoice_item

I'm trying to save new Invoice_items against an Invoice.

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

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:

$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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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