我使用多维关联数组创建了一个购物车。可以添加新项目,并且已存在的项目的数量和总金额已更新。必须检查每件商品的装饰条件,并将具有独特条件的商品作为新商品添加到购物车中。
我编写了下面的代码,它确实有效,但似乎过于复杂。有没有更好的方法来完成这项工作?
// 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 :(得分: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 />
<强>输出:强>
// 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()
方法与脚本大致相同,我只是将它们分成两部分。