使用特定数组值计算总计

时间:2016-02-28 19:53:23

标签: php loops oop

我做了一些修改,希望我能提出更清晰的

我正在开发一个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

我知道某些事情不是最有效的(不管怎样),但我试图先学会先执行它,然后再重构。

2 个答案:

答案 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属性并将它们正确存储到数组中的问题,而我最初混淆正在创建一个数组