password_hash()和password_verify()必须成对使用,数据库中价格用decimal(10,2)、库存用int unsigned、邮箱加unique约束,所有用户输入须预处理绑定,迁移文件应包含timestamps()和softdeletes(),购物车推荐redis以支持并发与多端同步。

password_hash() 和 password_verify() 必须成对使用,否则登录永远失败——这是初学者在实现用户模块时踩得最多、最隐蔽的坑。
从数据库建表开始就该注意字段类型
商品价格不能用 INT 或 FLOAT,必须用 DECIMAL(10,2)。MySQL 中 FLOAT 存储 99.99 可能变成 99.98999999999999,下单结算时金额对不上,用户投诉第一线就是这里。stock 字段建议设为 INT UNSIGNED,避免库存出现负数却没报错;email 字段加 UNIQUE 约束,省去后续查重逻辑。
不要手写 SQL 拼接用户输入
常见错误是这样写:
$sql = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'";
这等于把 SQL 注入大门敞开。正确做法是用预处理语句:
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");<br>$stmt->execute([$_POST['email']]);<br>$user = $stmt->fetch();
- 哪怕只做本地练习,也必须养成用
prepare()+execute()的习惯 - 不依赖框架时,
PDO比mysqli更易统一处理错误和事务 - 所有用户输入——包括分页
$_GET['page']、搜索关键词$_GET['q']——都得走参数绑定
Laravel 迁移文件里别漏掉 timestamps() 和 softDeletes()
新建商品表迁移时,如果只写 $table->string('name'),后面加订单时间、更新日志、软删除支持就得重写迁移或手动改表。正确模板应包含:
public function up(MigrationBuilder $migration)<br>{<br> $migration->create('products', function (Blueprint $table) {<br> $table->id();<br> $table->string('name');<br> $table->decimal('price', 10, 2);<br> $table->integer('stock')->default(0);<br> $table->timestamps();<br> $table->softDeletes();<br> });<br>}
少了 timestamps(),你就得自己维护 created_at 和 updated_at;没加 softDeletes(),删商品时真删库,恢复成本高、审计无迹可查。
购物车数据存在 Session 还是 Redis?看场景
本地开发或小流量测试,用 PHP 原生 $_SESSION 最快上手;但一旦要支持并发下单、多设备同步、或准备对接小程序,Session 就扛不住了。
- Session 默认基于文件存储,高并发下 I/O 锁争抢严重,用户加购变慢甚至丢失
- Redis 支持原子操作(如
INCR库存校验),配合 Lua 脚本能防止超卖 - ThinkPHP 用户可直接用
cache('cart_'.$uid);Laravel 开箱支持Cache::store('redis')->put(...)
真正容易被忽略的点是:Session 过期时间默认 24 分钟,用户逛半小时商城回来,购物车空了还找不到原因——得主动调 ini_set('session.gc_maxlifetime', 86400) 或换 Redis 管理生命周期。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











