我做了一些修改,希望我能提出更清晰的
我正在开发一个PHP项目,我需要根据各个项目的总计计算发票的总价。
根据我们的要求,我们要创建一个保存类对象的实例变量,然后使用一个方法循环遍历数组并计算总数。
这就是我所拥有的远:
InvoiceItem
上课
class InvoiceItem {
private $itemId;
private $itemQty;
private $itemPrice;
private $itemDescription;
private $total;
public function __get($attr) {
return $this->$attr;
}
public function __set($attr, $val) {
$this->$attr = $val;
}
public function calculateItemTotal() {
// This method will calculate the total by multiplying the quantity times the price.
$this->total = $this->__get("itemQty") * $this->__get("itemPrice");
}
public function display() {
// This method will generate a String that contains a one-line value for this object.
// It should include all the instance variables and the total for this item.
$display_format = "ID: %s, Quantity: %s, Price: %s, Description: %s, Total: %s<br />";
return sprintf($display_format,$this->__get("itemId"),$this->__get("itemQty"),
$this->__get("itemPrice"),$this->__get("itemDescription"), $this->__get("total"));
}
}
这就是我在课程中所做的(到目前为止)我正在尝试进行计算Invoice
class Invoice {
private $items;
private $invoice_total;
public function __construct() {
$this->items = array(new InvoiceItem());
}
// Magic Method Getters/Setters
public function __get($attr) {
return $this->$attr;
}
public function __set($attr, $val) {
$this->$attr = $val;
}
public function calculateInvoice() {
// it's supposed to loop through my array and calculate the invoice total here
}
public function displayInvoice() {
// this is supposed to call the parent 'display()' method to list each InvoiceItem
// call calculateInvoice() and print the $invoice_total
}
}
最后的读数应该是这样的:
ID:1,数量:3,价格:5,描述:Foo,总计:15
ID:2,数量:6,价格:3,描述:酒吧,总计:18
发票总数:33
我知道某些事情不是最有效的(不管怎样),但我试图先学会先执行它,然后再重构。
答案 0 :(得分:0)
整体结构看起来还不错。你为此使用了合成而不是继承,这很好。
您可以进行一些简单的更改,以进一步简化它。
您可以稍微更改Invoice
的构造函数以接收InvoiceItem
个对象的列表。这将使您的Invoice类从实例化之时起生效。
public function __construct(array $invoiceItems) {
$this->loadInvoiceItems($invoiceItems);
}
private function loadInvoiceItems(array $invoiceItems){
$this->items = array_map(function(InvoiceItem $item){
return $item;
}, $invoiceItems);
}
这使您的API看起来像这样,我认为这更清晰,更方便:
$myInvoice = new Invoice([
new InvoiceItem(1, 2, 2, "4"),
new InvoiceItem(2, 1, 3, "3"),
new InvoiceItem(2, 3, 5, "15"),
]);
以相同的价格,您还可以修改InvoiceItem的构造函数。您不需要传递总数,因为您可以从数量和单价中推断出来(除非有特殊规则阻止这种情况发生):
public function __construct($id, $qty, $price, $description = "") {
$this->itemId = $id;
$this->itemQty = $qty;
$this->itemPrice = $price;
$this->itemDescription = $description;
$this->calculateItemTotal();
}
要计算您的displayInvoice方法,您只需要遍历您的项目并累积响应:
public function displayInvoice() {
$displayItems = $this->fetchAllDisplayItems();
$displayItems[] = $this->displayInvoiceTotal();
return implode(PHP_EOL, $displayItems);
}
private function fetchAllDisplayItems(){
return array_map(function(InvoiceItem $item){
return $item->display();
}, $this->items);
}
private function displayInvoiceTotal(){
return "Invoice Total: ". $this->calculateTotalInvoice();
}
private function calculateTotalInvoice(){
return array_sum(array_map(function(InvoiceItem $item){
return $item->getTotal();
}, $this->items));
}
我强烈建议你做的另一件事就是删除getter和setter的魔法。考虑一下您的对象需要处于有效状态并将其传递给构造函数。这应该摆脱大多数的二传手。在吸气剂方面,确定哪些是实际需要的,并摆脱其余的。
答案 1 :(得分:0)
弄清楚我做错了什么:主要是误解如何来实现我的阵列
class Invoice {
private $items = array();
private $invoice_total;
// Magic Method Getters/Setters
public function __get($attr) {
return $this->$attr;
}
public function __set($attr, $val) {
$this->$attr = $val;
}
public function calculateInvoice() {
foreach ($this->__get("items") as $item) {
$this->invoice_total += $item->itemTotal;
}
}
public function displayInvoice() {
foreach ($this->__get("items") as $item) {
$item->calculateItemTotal();
echo $item->display();
}
$this->calculateInvoice();
$total_output = "<label for='invoice_total'>" . "Invoice Total: $%s" . "</label>";
echo "<br />";
echo sprintf($total_output, $this->__get("invoice_total"));
}
}
这个练习的目的是专注于使用硬编码的值,所以这或多或少是我采用和定义InvoiceItem属性并将它们正确存储到数组中的问题,而我最初混淆时正在创建一个数组