跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

计算披萨订单总价:PHP面向对象实现教程

本文详解如何使用php面向对象方式动态计算披萨订单总价,支持尺寸、配料和饼底类型组合计价,并将订单详情与金额安全写入文件,兼顾可维护性与健壮性。 本文详解如何使用 php 面向对象方式动态计算披萨订单总价,支持尺寸、配料和饼底类型组合计价,并将订单详情与金额安全写入文件,兼顾可维护性与健壮性。 在电商类表单处理中,准确、可扩展地计算商品总价是后端逻辑的核心能力之一。本文以披萨订单系统为例,展示如何用 现代PHP(≥8.0)面向对象设计 替代原始的流程式脚本,实现清晰、易测试、易维护的价格计算逻辑。 核心设计思路 我们封装一个 Pizza 类,将业务规则(价格映射、选项校验、金额聚合)与数据操作(文件写入、响应输出)解耦。关键优势包括: PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 ✅ 配置集中化 :尺寸、饼底、配料及其单价统一定义为常量,便于后续调整; ✅ 类型安全与容错 :自动处理空值、非法选项(如未选饼底),默认回退至合理值; ✅ 灵活扩展性 :新增配料或尺寸只需修改常量数组,无需重写计算逻辑; ✅ 职责分离 :calculatePizza() 专注金额计算,saveToFile() 专注持久化,getThankYou() 专注响应渲染。 完整实现代码(pizza.php)
self::PRICE_SIZE[$this->getSize()], 'crust' => self::PRICE_CRUST[$this->getCrust()], 'toppings' => count($this->getChosenToppings()) * self::PRICE_TOPPINGS, ]; return (float) number_format(array_sum($costs), 2); } /** * 将订单信息追加写入 pizza.txt(含格式化分隔) */ public function saveToFile(): self { $file = fopen(self::FILE, 'a') or die('Unable to open pizza.txt for writing!'); fwrite($file, "Size: " . self::SIZES[$this->getSize()] . "\n"); foreach ($this->getChosenToppings() as $idx) { fwrite($file, "Topping: " . self::TOPPINGS[$idx] . "\n"); } fwrite($file, "Crust: " . self::CRUSTS[$this->getCrust()] . "\n"); fwrite($file, "Name: " . ($this->getCustomerName() ?: 'Unknown') . "\n"); fwrite($file, "Price: $" . $this->calculatePizza() . "\n"); fwrite($file, str_repeat('-', 40) . "\n"); fclose($file); return $this; } /** * 生成并输出感谢页面(含客户名与总价) */ public function getThankYou(bool $echo = true): string { $html = <<Pizza ordered, thank you {$this->getCustomerName()}!

Your total is \${$this->calculatePizza()}

HTML; if ($echo) echo $html; return $html; } // --- 属性设置器(支持字符串/数字输入,自动标准化)--- public function setSize(string|int|null $size): self { if (is_string($size) && in_array($size, self::SIZES)) { $this->size = array_search($size, self::SIZES); } elseif (is_int($size) && isset(self::SIZES[$size])) { $this->size = $size; } else { $this->size = 0; // 默认 Large } return $this; } public function setCrust(string|int|null $crust): self { if (is_string($crust) && in_array($crust, self::CRUSTS)) { $this->crust = array_search($crust, self::CRUSTS); } elseif (is_int($crust) && isset(self::CRUSTS[$crust])) { $this->crust = $crust; } else { $this->crust = 0; // 默认 Thin } return $this; } public function addChosenToppings(array $toppings): self { foreach ($toppings as $topping) { if (empty($topping)) continue; if (is_string($topping) && in_array($topping, self::TOPPINGS)) { $this->chosenToppings[] = array_search($topping, self::TOPPINGS); } elseif (is_int($topping) && isset(self::TOPPINGS[$topping])) { $this->chosenToppings[] = $topping; } } return $this; } public function setCustomerName(?string $name): self { $this->customerName = trim($name) ?: 'Unknown'; return $this; } // --- 获取器 --- public function getCustomerName(): ?string { return $this->customerName; } public function getChosenToppings(): array { return $this->chosenToppings; } public function getSize(): int { return $this->size ?? 0; } public function getCrust(): int { return $this->crust ?? 0; } } // === 请求处理入口 === if ($_POST['submit'] ?? false) { $pizza = new Pizza(); $pizza ->setSize($_POST['size'] ?? null) ->setCrust($_POST['crust'] ?? null) ->addChosenToppings([ $_POST['pepperoni'] ?? null, $_POST['mushrooms'] ?? null, ]) ->setCustomerName($_POST['name'] ?? null) ->saveToFile() ->getThankYou(); } else { include 'pizza.html'; // 未提交时显示表单 }
关键注意事项与最佳实践 安全性提醒 :本例未包含XSS防护与SQL注入防御(因无数据库),实际生产环境需对 $_POST 数据进行 htmlspecialchars() 转义后再输出; 文件写入风险 :fopen(..., 'a') 在高并发下可能产生竞态条件,建议改用数据库或添加文件锁(flock()); 表单兼容性 :HTML中