Reputation: 1670
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);
}
}
Upvotes: 0
Views: 814
Reputation: 20753
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
.
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.
Upvotes: 2