2015-12-15 43 views
0

我已经使用多维关联数组创建了一个购物车。可以添加新项目,已存在的项目会更新其数量和总金额。必须检查每个物品的美观状况,并将具有独特状况的物品作为新物品添加到购物车中。替换(或添加到)取决于多个条件的多维关联数组

我写了下面的代码,它确实有效,但它看起来过于复杂。有没有更好的方法来完成这件事?

// if there are items in the cart 
if(isset($_SESSION['cart'])) { 
    // loop through the array 
    for($i = 0; $i <= count($_SESSION['cart']); $i++) { 
     // if $name is found in $_SESSION['cart'] array ... 
     if(in_array_r($name, $_SESSION['cart'])) { 
      // if $i == count($_SESSION['cart']) that means a new item needs to be added since $name 
      // was found in the array but no match for $condition was found 
      if($i == count($_SESSION['cart'])) { 
       $_SESSION['cart'][] = array('name' => $name, 'condition' => $condition, 'quantity' => $quantity, 'itemTotal' => $itemTotal); 
       break; 
      } 
      // if a match for $name and $condition is found update the quantity and totals for that item 
      elseif($name == $_SESSION['cart'][$i]['name'] && $condition == $_SESSION['cart'][$i]['condition']) { 
       $_SESSION['cart'][$i]['quantity'] = $_SESSION['cart'][$i]['quantity'] + $quantity; 
       $_SESSION['cart'][$i]['itemTotal'] = $_SESSION['cart'][$i]['itemTotal'] + $itemTotal; 
       break; 
      } 
      // continue through the loop to search for a match 
      else { 
       continue; 
      } 
     } 
     // if $name isn't found in array add new item 
     else { 
      $_SESSION['cart'][] = array('name' => $name, 'condition' => $condition, 'quantity' => $quantity, 'itemTotal' => $itemTotal); 
      break; 
     } 
    } 
    // sort in alphabetical order 
    sort($_SESSION['cart']); 
} 
// if there are no items in the cart 
else { 
    $_SESSION['cart'][] = array('name' => $name, 'condition' => $condition, 'quantity' => $quantity, 'itemTotal' => $itemTotal); 
} 

// recursive in_array function 
function in_array_r($needle, $haystack, $strict = false) { 
foreach ($haystack as $item) { 
    if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) { 
     return true; 
    } 
} 
return false; 

}

+0

什么是条件存储? – Rasclatt

+0

$条件和数组中的'条件'键是指项目的外观条件 – gb2016

+0

条件是一个字符串(重命名为$ _POST变量) – gb2016

回答

1

我建议你应该让你的卡丁车成class,便于编译和执行站点范围。这仅仅是一个简单的例子,我不使用这个或更换你有什么,看看它的任何价值的建议,但它可能给你一些想法:

/classes/class.Cart.php

// Create an easy way to access your cart app 
class Cart 
    { 
     private static $singleton; 
     private static $name; 
     // Allows for same-resource re-use 
     public static function app() 
      { 
       self::$name = (empty(self::$name))? 'cart' : self::$name; 

       if(empty(self::$singleton)) 
        self::$singleton = new ShoppingCart(self::$name); 

       return self::$singleton; 
      } 

     public static function init($name = 'cart') 
      { 
       self::$name = $name; 
      } 
    } 

/classes/class.ShoppingCart.php

class ShoppingCart 
    { 
     public $name; 
     public $condition; 
     public $total; 
     public $items; 

     private $cart; 
     private $cart_info; 
     private $item; 

     const REV_SORT = 'r'; 
     const NAT_SORT = 'n'; 
     // The construct will allow for using mulitple carts if required 
     public function __construct($name = 'cart') 
      { 
       $this->cName  = $name; 
       // This will save the cart data but it only holds the id and qty 
       $this->cart   = (!empty($_SESSION[$this->cName]))? $_SESSION[$this->cName] : array(); 
       // This will save a tandem session that only stores static data in reference to items added to the cart 
       $this->cart_info = (!empty($_SESSION[$this->cName."_info"]))? $_SESSION[$this->cName."_info"] : array(); 
      } 
     // This will retrieve a cart item's total value (qty x price) 
     public function getItemTotal($item = false) 
      { 
       if(empty($_SESSION[$this->cName][$item])) 
        return 0; 
       // Filter all but numbers and decimals 
       $price = (!empty($_SESSION[$this->cName."_info"][$item]['price']))? preg_replace('/[^0-9\.]/',"",$_SESSION[$this->cName.'_info'][$item]['price']) : false; 
       // Check if qty is numeric, if not, just add qty as 1 
       $qty = (!empty($_SESSION[$this->cName][$item]['qty']) && is_numeric($_SESSION[$this->cName][$item]['qty']))? $_SESSION[$this->cName][$item]['qty'] : 1; 
       // Return the final price back. "invalid" means something was not submitted properly 
       return (!empty($price))? ($_SESSION[$this->cName.'_info'][$item]['price'] * $qty) : 'invalid'; 
      } 
     // This will fetch the total cart value 
     public function getCartTotal($format = false) 
      { 
       if(empty($_SESSION[$this->cName.'_info'])) 
        return 0; 
       // Save subtotals to new array 
       foreach($_SESSION[$this->cName.'_info'] as $itm) { 
         $sub[] = $itm['subtotal']; 
        } 
       // Sum the array 
       $final = (!empty($sub))? array_sum($sub) : 0; 
       // If the format is true, send back a currency value 
       if($format) { 
         // This may draw error if on a WINDOWS machine. 
         // May have to use number_format() instead and possibly strpad() 
         setlocale(LC_MONETARY, 'en_US'); 
         return money_format("%#10n",$final); 
        } 
       // $format false will send back just the unformatted value 
       else 
        return $final; 
      } 

     public function getItemList($sort = 'n') 
      { 
       // Check if the session is set 
       if(empty($_SESSION[$this->cName])) 
        return false; 
       // Loop through the items and send back decoded names 
       $arr = array_map(function($v) { return base64_decode($v); },array_keys($_SESSION[$this->cName])); 
       // Check if there is a sort order specified 
       switch($sort) { 
        case('n'): 
         // This may draw error if your PHP version is too low 
         asort($arr,SORT_NATURAL); 
         break; 
        case('r'): 
         arsort($arr); 
         break; 
        default: 
         sort($arr); 
       } 

       return $arr; 
      } 
     // This will return item details if it exists 
     public function getDetails($item = false) 
      { 
       $item = base64_encode($item); 

       if(isset($_SESSION[$this->cName.'_info'][$item])) 
        return (object) $_SESSION[$this->cName.'_info'][$item]; 

       return false; 
      } 
     // This removes the details of a stored item 
     public function removeDetails() 
      { 
       if(isset($_SESSION[$this->cName.'_info'][$this->item])) { 
         unset($_SESSION[$this->cName.'_info'][$this->item]); 
         unset($this->cart_info[$this->item]); 
        } 
      } 
     // This sets the items calculated subtotal price (qty x price) 
     public function saveSubTotal() 
      { 
       return (!empty($_SESSION[$this->cName.'_info'][$this->item]['price']))? $this->getItemTotal($this->item) : 'invalid'; 
      } 
     // This saves the items details. I use the $_GET details, but you can use data pulled from the DB or whatever 
     public function saveDetails($details = array()) 
      { 
       if(isset($_SESSION[$this->cName][$this->item])) { 
         if(!isset($_SESSION[$this->cName.'_info'])) { 
           $this->cart_info = $_SESSION[$this->cName.'_info'] = array(); 
          } 

         $_SESSION[$this->cName.'_info'][$this->item]    = $details; 
         $_SESSION[$this->cName.'_info'][$this->item]['subtotal'] = $this->saveSubTotal(); 

         $this->cart_info[$this->item] = $_SESSION[$this->cName.'_info'][$this->item]; 
        } 
      } 
     // This adds to cart 
     public function addToCart($item = false, $qty = 1) 
      { 
       // It would be better just to use the id from your database, then it's unique and easy 
       // but you are using name, so I am creating a generated id 
       $this->item = base64_encode($item); 
       // Create cart 
       if(!isset($_SESSION[$this->cName])) 
        $this->cart = $_SESSION[$this->cName] = array(); 
       // Add qty 
       if(!isset($_SESSION[$this->cName][$this->item])) 
        $_SESSION[$this->cName][$this->item]['qty'] = $qty; 
       // or Update qty 
       else 
        $_SESSION[$this->cName][$this->item]['qty'] += $qty; 
       // Assign to a local variable 
       $this->cart[$this->item] = $_SESSION[$this->cName][$this->item]; 
       // Return the object to use in method chaining 
       return $this; 
      } 
     // This allows you to remove from the cart either by subtracting qty or by remove totally 
     public function removeFromCart($item = false,$amt = false) 
      { 
       $this->item = base64_encode($item); 
       if(!isset($_SESSION[$this->cName][$this->item])) 
        return; 
       else { 
         if(is_numeric($amt)) { 
           $curr = (int) $_SESSION[$this->cName][$this->item]['qty']; 
           $amt = (int) $amt; 
           if(($curr - $amt) >= 0.01) { 
             $this->cart_info[$this->item]['qty'] = $_SESSION[$this->cName][$this->item]['qty'] = ($amt - $curr); 
             $_SESSION[$this->cName.'_info'][$this->item]['subtotal']       = $this->saveSubTotal(); 
             return; 
            } 
          } 

         unset($_SESSION[$this->cName][$this->item]); 
         unset($this->cart[$this->item]); 
         $this->removeDetails(); 
        } 
      } 
     // Clear the entire cart 
     public function clearCart() 
      { 
       if(isset($_SESSION[$this->cName])) { 
         $this->cart   = array(); 
         $this->cart_info = array(); 
         unset($_SESSION[$this->cName]); 
         unset($_SESSION[$this->cName."_info"]); 
        } 
      } 
     // Set the quantity based on validation of array parameter 
     public function setQty($array = false) 
      { 
       return ((!empty($array['qty']) && is_numeric($array['qty'])) && $array['qty'] !== 0)? $array['qty'] : 1; 
      } 
     // Set name based on parameter 
     public function setName($array = false) 
      { 
       return (!empty($array['name']))? $array['name'] : false; 
      } 
    } 

的index.php

// Include the above classes 
include_once(__DIR__."/classes/class.Cart.php"); 
include_once(__DIR__."/classes/class.ShoppingCart.php"); 

// sets a the cart name, by default it's set to "cart" 
// Cart::init("cart2"); 

// I am using $_GET, you can use $_POST if you want 
// If add or remove 
if(isset($_GET['add']) || isset($_GET['remove'])) { 
     // Set defaults 
     $qty = Cart::app()->setQty($_GET); 
     $name = Cart::app()->setName($_GET); 
     // If the name is empty, just stop 
     if(empty($name)) 
      return false; 
     // If adding, add to cart, save the item's details 
     if(isset($_GET['add'])) 
      Cart::app()->addToCart($name,$qty)->saveDetails($_GET); 
     // Else, you can remove 
     // Leave second parameter blank if you want remove to just 
     // straight remove the item from cart 
     // otherwise it will subtract if the $qty is numeric and not "false" 
     else 
      Cart::app()->removeFromCart($name,$qty); 
    } 
// Clear will remove the cart completely 
// including the details 
elseif(isset($_GET['clear'])) 
    Cart::app()->clearCart(); 

// get data for just the item 1 
print_r(Cart::app()->getDetails("item1")); 
// Get the list ordered naturally 
print_r(Cart::app()->getItemList(ShoppingCart::NAT_SORT)); 
// Get the cart total 
// Using true will format the output (see this method for more info if error occurs) 
echo Cart::app()->getCartTotal(true); 
// Show session 
print_r($_SESSION); 
?> 
<a href="?add=true&name=item1&qty=1&condition=good&price=23.99">ADD ITEM1</a><br /> 
<a href="?add=true&name=item2&qty=1&condition=crap&price=24.50">ADD ITEM2</a><br /> 
<a href="?add=true&name=item3&qty=1&condition=horrible&price=34.50">ADD ITEM3</a><br /> 
<a href="?add=true&name=item4&qty=1&condition=super&price=11.33">ADD ITEM4</a><br /> 
<a href="?remove=true&name=item1">REMOVE ITEM1</a><br /> 
<a href="?remove=true&name=item2">REMOVE ITEM2</a><br /> 
<a href="?remove=true&name=item<?php echo $nm = rand(1,2); ?>&qty=10">REMOVE ITEM<?php echo $nm;?></a><br /> 
<a href="?remove=true&name=item<?php echo $nm = rand(3,4); ?>&qty=10">REMOVE ITEM<?php echo $nm;?></a><br /> 
<a href="?clear=true">Clear</a><br /> 

OUTPUT:

// item1 details 
stdClass Object 
(
    [add] => true 
    [name] => item1 
    [qty] => 1 
    [condition] => good 
    [price] => 23.99 
    [subtotal] => 23.99 
) 

// ordered list 
Array 
(
    [1] => item1 
    [0] => item4 
) 

// Cart total 
$35.32 

// cart session details 
Array 
(
    [cart] => Array 
     (
      [aXRlbTQ=] => Array 
       (
        [qty] => 1 
       ) 

      [aXRlbTE=] => Array 
       (
        [qty] => 1 
       ) 
     ) 

    [cart_info] => Array 
     (
      [aXRlbTQ=] => Array 
       (
        [add] => true 
        [name] => item4 
        [qty] => 1 
        [condition] => super 
        [price] => 11.33 
        [subtotal] => 11.33 
       ) 

      [aXRlbTE=] => Array 
       (
        [add] => true 
        [name] => item1 
        [qty] => 1 
        [condition] => good 
        [price] => 23.99 
        [subtotal] => 23.99 
       ) 
     ) 
) 

我也应该注意到,addToCart()saveDetails()相结合的方法在做大致相同的事情作为你的脚本,我只是他们分成两个部分。