2016-03-01 95 views
0

我已經開始學習PHP類,接口,擴展以及與這些相關的東西。在會話中使用購物車類

在此之前,我只與函數一起工作,它開始與單獨的函數hundreads相當混亂。

根據我的需求將有多個類爲我的項目:

  1. 車類。這應該是相當通用的,因爲在某些時候,我可能需要將數據保存到數據庫而不是會話。
  2. 計算類。將會有大約15種產品和大約5種不同類型的計算。 (基於金額,基準價格,人均價格等)
  3. 數據庫類。這將用於從我的計算類的數據庫中獲取我的價格。
  4. 從通過HTML表單提交的數據(也用於更新購物車數量並返回實時計算價格)

然而MPDF創建PDF,那只是爲了給在暗示什麼我正在努力實現,所以它可能會讓你更好地理解我應該如何處理事情。

現在的實際問題。這是我的車類:

interface CartInterface { 
    public function addItem($id, $amount, $months); 
    public function updateItem($id, $amount, $months); 
    public function deleteItem($id); 
    public function countItems(); 
    public function getCart(); 
    public function ifIdExists($id);  
} 

class Cart implements CartInterface { 
public $cart = array(); 

public function addItem($id, $amount, $months) { 

    if($this->ifIdExists($id)){ 
     $this->updateItem($id, $amount, $months);         
    } 

    else { 
     $this->cart[$id]['id'] = $id; 
     $this->cart[$id]['amount'] = $amount; 
     $this->cart[$id]['months'] = $months; 
    } 

} 

public function updateItem($id, $amount, $months) { 
     $this->cart[$id]['id'] = $id; 
     $this->cart[$id]['amount'] = $amount; 
     $this->cart[$id]['months'] = $months; 
} 

public function deleteItem($id) { 
    unset($this->cart[$id]);   
} 

public function countItems() { 
    return count($this->cart); 
} 

public function getCart() { 
    return $this->cart; 
} 

public function ifIdExists($id) { 
    $exists = false; 
    if(array_key_exists($id, $this->cart)) { 
     $exists = true; 
    } 
    else { 
     $exists = false; 
    } 
    return $exists; 
} 

public function showCart() { 
    foreach($this->cart as $value) { 
     echo "<br />"; 
     echo 'Id:'. $value['id'] ; 
     echo "<br />"; 
     echo 'Amount:'.$value['amount']; 
     echo "<br />";   
     echo 'Months:'.$value['months']; 
     echo "<br />"; 
    } 
} 
} 

這已經幾乎我的車需要但這裏的功能問題:

  1. 我的HTML表單有輸入欄的每個項目,這決定簇量相應的項目將被訂購。在這種情況下,我需要單獨的addItem()和updateItem()嗎?因爲無論如何,新的值會重寫舊的。

  2. 什麼決定我應該在CartInterface中包含哪些方法?我知道任何使用CartInterface的類都被迫使用這些方法,但是我想強制一個類使用這些方法的原因是什麼?

  3. 最重要的問題是適應這個類來使用會話。正如我們所知道的,購物車沒有會話就沒有多大用處。我怎樣才能使用$ cart-> deleteItem()也從會話中刪除項目?我是否需要創建一個單獨的SessionCart類,它具有與購物車相同的方法但處理會話?

    $cart = new Cart(); 
    $cart->addItem('1', '30', '2'); 
    $cart->addItem('2', '306', '12'); 
    $cart->addItem('6', '306', '12'); 
    $cart->deleteItem('1'); 
    
    // Here i create a session array from the cart but cart's class methods won't work 
    $cart = $cart->getCart(); 
    
    $_SESSION['cart'] = $cart; 
    $cart->deleteItem('1'); // This won't effect the session cart 
    print_r($_SESSION['cart']); 
    

我感謝所有幫助,也請大家指出不好的編碼習慣,所以大家閱讀這篇文章會學到一些東西。

長話短說:我應該用什麼方法才能讓這個Cart類與會話一起工作?

+0

爲什麼'$ cart-> deleteItem('1')'不會影響會話購物車?如果它是任何其他PHP陣列存儲購物車,那麼它會影響它。 – apokryfos

+0

在上述示例中,它不會從會話購物車中銷燬物品。這就是爲什麼我要求幫助,因爲我不知道我應該如何繼續。 :) – Griphon

+0

'$ cart = $ cart-> getCart();'覆蓋您的購物車對象,包含在對象中的數組。這違反了封裝(換句話說,爲什麼在一個類中包裝一個數組,如果你打算之後處理這個數組呢?) – apokryfos

回答

0
  1. 您的添加和項目和更新的實現是相同的。第一次添加項目還是被更換,是否真的與您相關?如果答案是肯定的,那麼你應該保留兩種不同的方法。會有人會告訴你,你違反了DRY規則(不要重複自己),但該規則只適用於語義。寫出相同但不完全相同的東西可以重複。

  2. 接口是一種確保某個合同得到滿足的方法。試想一下,你有一個能夠從你的購物車生成發票的類。另外想象一下,你實現另一個購物車是免費贈品,它可以免費從購物車給你一個隨機物品。該的Invoicer類將是這個樣子:

    class Invoicer { 
    
        /** 
        * @return Invoice 
        */ 
        public function invoiceFromCart(CartInterface $cart) { 
         //in here you know exactly what to expect from the $cart object 
         $cart->getItems(); 
         $cart->countItems(); 
        } 
    ... 
    } 
    

    正如你可以看到,提供的接口是針對將要使用類的代碼非常方便,因爲它並不需要知道具體的實現一個CartInterface正在接收,它只需要知道它的合約來調用它的方法並與它通信。這也使您可以在不必修改大量代碼的情況下交換功能。

    要回答您的評論,理解在OOP中擴展Cart的類Invoicer會非常奇怪。關鍵字「extends」的含義是擴展的類是更抽象類的更專業的版本。想想Car extends VehicleEarth extends Planet

  3. 有幾種方法可以解決這個問題。對我來說最重要的事情就是將會話包裝到自己的抽象中。就像CartStorage。這個類實現一個接口,這樣的:

    interface CartStorage { 
        public function store(CartInterface $cart); 
        public function retrieve(SessionId $sessionId); 
    } 
    

    然後,你需要實現一個SessionCartStorage類店,並允許您從會話中檢索推車。如果稍後想要將購物車存儲在數據庫中或其他位置,則可以實施PostGresCartStorage或CassandraCartStorage,這樣可以將您的購物車存儲在這些存儲系統中,而無需更改太多的代碼。

    要回答您的評論,它將取決於在會話中存儲購物車時所需的粒度方式和級別。如果你逐項存儲,你確實可以有一個像SessionCartStorage->addItem(CartItem $item)這樣的方法。但是這會使得從會話中檢索購物車的方式複雜化,所以我會保持簡單地存儲整個購物車。

希望這會有所幫助。

+0

1.謝謝你。這真的爲我清除了。 2。班級發票人延長班級車是否一樣?在這種情況下,Invoicer將被迫使用Cart的界面,對吧? 3.只是爲了驗證一件事。這需要我寫一個班級,這也是例如。 addItem()方法,但與會話交互?或者我可以像SessionCartStorage-> addItem()一樣使用它,它會使用Cart類中的那個方法? – Griphon

+0

我已閱讀了答案,並感謝您的澄清。有了這些答案,我可以構建一些更好的東西,這有助於我更好地理解OOP。 :) – Griphon

0

正如我以上評論,不要以這種直接的方式暴露你的內部工作。您的購物車在內部使用陣列,但陣列屬於購物車的一部分,並不是整個購物車。只將數組放在會話中意味着你放棄了面向對象的設計。我會建議對初學者進行此修改。

$cart = new Cart(); 
$cart->addItem('1', '30', '2'); 
$cart->addItem('2', '306', '12'); 
$cart->addItem('6', '306', '12'); 

//$cart = $cart->getCart(); //This is not necessary 

$_SESSION['cart'] = $cart; //This will put the object itself in the session. 
$cart->deleteItem('1'); // This should now affect the object 
var_dump($_SESSION['cart']); 

在請求結束時,會話中的所有對象都是使用系列化連載(),所以你不應該擔心PHP是怎麼做的,你只需要知道PHP做的。