创建PHP结帐系统[关闭]

I'm trying to create a fairly simple PHP checkout system.

The table of information I'm using is:

Product Code        Name            Price
       SW1              Sandwich         £3.11
       CL1               Chocolate        £5.00
       CF1                 Coffee           £11.23


My code is:

class Product {
    public $name;
    public $price;

    public function __construct($name, $price) {
        $this->item = $name;
        $this->price = $price;
  }
} class Checkout {
    protected $shopping_cart;

    public function scan(Product $product) {
        $shopping_cart[] = $product;
    }

    public function total() {
    // Goes through the shopping cart and sums up the price of the contents
        return array_reduce(
            $this->shopping_cart,
            function($total, $item) {
                return $total + $item->price;
            },
            0
        );
    }
}

$pay = new Checkout();
$pay->scan(new Product("Sandwich", 3.11));
$pay->scan(new Product("Chocolate", 5));
$pay->scan(new Product("Coffee", 11.23));
$price = $pay->total();


What I'd like to do is add a pricing rule to some items. For example, I'd like sandwiches to be buy-one-get-one-free and chocolates to have a bulk purchase discount. Not sure if it'd work, but I'm thinking I should add something like this:

$SW1 = new Checkout("Sandwich", 3.11);
$CL1 = new Checkout("Chocolate", 5);
$CF1 = new Checkout("Coffee", 11.23);

if(scan($SW1 % 2 == 0)) {
    $price = $price / 2;
}
elseif(scan($SW1 == 1)) {
}
else {
    $price = $price / 2 + $price;
}

if(scan($CL1 >= 3 && $CL1 % 3 == 0)) {
    $price = $price - .50;
}
else {
// insert logic to make sure purchases that include more than 3 items, though not divisible by 3, are also discounted accordingly.
}


Any help would be appreciated. Also if anyone knows how I could test this code, that'd be great ☺.

I would create a 'Discount' interface that can be applied to the product and/or the checkout. For example:

interface IDiscount {
  public function apply(&$amount);
}

class Discount_HalfOff implements IDiscount {
  public function apply(&$amount) {
    $amount /= 2;
  }
}

class Discount_FixedAmount implements IDiscount {
  private $amount;

  public function __construct($amount) {
    $this->amount = $amount;
  }

  public function apply(&$amount) {
    $amount -= $this->amount;
  }
}

class Product {
  private $discounts = [];

  public function __construct($name, $price) {
    $this->item  = $name;
    $this->price = $price;
  }

  public function addDiscount(IDiscount $discount) {
    $this->discounts[] = $discount;
  }

  public function getPrice() {
    $price = $this->price;
    foreach($this->discounts as $discount)
      $discount->apply($price);
    return $price;        
  }
}

class Checkout {
  private $contents  = [];
  private $discounts = [];

  public function addDiscount(IDiscount $discount) {
    $this->discounts[] = $discount;
  }

  public function scan(Product $product) {
    $this->contents[] = $product;
  }

  public function getCount() {
    return count($this->contents);
  }

  public function getTotal() {
    $ttl = 0;
    foreach($this->contents as $product)
      $ttl += $product->getPrice();

    foreach($this->discounts as $discount)
      $discount->apply($ttl);

    return $ttl;
  }
}

$sandwich = new Product('Sandwich', 3.11);
$sandwich->addDiscount(new Discount_HalfOff());

$checkout = new Checkout();
$checkout->scan($sandwich);

// this logic could be included into the Checkout class directly, depends on your use case.
if ($checkout->getCount() > 3) {
  if ($checkout->getCount() % 3 == 0)
    $checkout->addDiscount(new Discount_FixedAmount(0.50));
  } else {
    // insert logic to make sure purchases that include more than 3 items, though not divisible by 3, are also discounted accordingly.
  }
}

echo $checkout->getTotal() . "
";