商品模块开发应基于ci4.7.1内置能力,合理设计模型、路由、上传与分页:模型启用软删除和关系方法,路由分离前台seo路径与后台权限保护,上传重命名并按需生成缩略图,分页结合索引优化与id缓存。

直接上手开发商品模块,CodeIgniter4.7.1 已内置足够支持——不用魔改核心、不硬塞第三方包,重点是模型设计合理、路由清晰、服务可测。下面说清关键几步怎么做、为什么这么定、哪些地方一动就崩。
怎么定义商品模型并关联分类和品牌
CI4 的 Model 不再是 CI3 那种纯数据访问层,它天然支持查询构造器、软删除、时间戳自动填充。商品表通常需关联分类(categories)和品牌(brands),但别急着写 join ——先用关系方法声明,后期扩展更稳。
- 在
app/Models/ProductModel.php中继承CodeIgniter\Model,启用$useSoftDeletes = true(下架≠删库) - 用
protected $allowedFields = ['name', 'slug', 'price', 'category_id', 'brand_id', 'status']严格控制批量赋值字段,防 mass-assignment 漏洞 - 定义关系方法:
public function category()返回$this->belongsTo(CategoryModel::class, 'category_id', 'id');同理写brand() - 别在模型里写业务逻辑(比如“计算库存是否充足”),这类逻辑应抽到
app/Services/ProductService.php中——模型只管“查/存/删”,服务才管“能不能卖”
路由怎么配才支持 SEO 友好的商品页和后台管理
CI4.7.1 的路由系统支持命名、分组、中间件绑定,商品前台页要带分类路径(如 /electronics/smartphones/iphone-15),后台则走 /admin/products,两者必须隔离,否则权限和缓存会乱。
- 前台路由写在
app/Config/Routes.php的$routes->group('')下:$routes->get('(:segment)/(:segment)/(:any)', 'Product::view/$1/$2/$3');,然后在Product控制器里解析三段参数并查slug - 后台路由必须加中间件保护:
$routes->group('admin', ['filter' => 'auth'], static function ($routes) { $routes->resource('products'); });——resource()自动生成 CRUD 路由,但记得在app/Controllers/Admin/Products.php中重写create()和update()方法,加入表单验证和上传处理 - 别把前台商品页的
slug直接当 ID 用:数据库查时必须同时校验status = 'active'和slug,防止未发布商品被猜出 URL 访问
商品图怎么上传并生成多尺寸缩略图
CI4.7.1 的 Upload 类已支持多文件、类型白名单、大小限制,但缩略图得自己生成——别依赖 GD 扩展硬编码,用 Image 辅助类配合配置驱动更可控。
- 上传前先配置:
app/Config/Images.php中定义常用尺寸,如'thumb' => ['width' => 300, 'height' => 300, 'maintain_ratio' => true] - 控制器中上传后调用:
$image = \Config\Services::image()->withFile($file->getTempName())->fit(300, 300, 'center')->save(WRITEPATH . 'uploads/thumbs/' . $filename); - 注意路径安全:所有上传文件名必须重生成(如
uniqid() . '_' . $file->getRandomName()),且保存目录不能在public/下直访——用WRITEPATH . 'uploads/',再通过app/Controllers/Uploads.php提供受控访问接口 - 别在上传时同步生成全部尺寸:按需生成(访问时判断缩略图是否存在,不存在再生成),避免首图上传卡顿
怎么让商品列表支持分页+搜索+状态筛选且不拖慢响应
电商首页或后台商品列表常被做成“万能查询页”,但 CI4 的 Pager 默认不缓存查询结果,每次翻页都重跑 SQL —— 数据量一过万,OFFSET 就成性能杀手。
- 用
$model->select('id, name, price, status')->like('name', $keyword)->whereIn('status', $statuses)构建查询,最后才调用paginate(),别先findAll()再分页 - 给高频查询字段(
status、category_id、created_at)建联合索引,例如ALTER TABLE products ADD INDEX idx_status_cat_created (status, category_id, created_at); - 搜索关键词长度低于 2 字符时直接跳过
like,避免全表扫;空关键词不执行查询,返回空数组 - 如果用 Redis 缓存分页结果,别缓存原始数据集,而缓存「ID 列表」+ 「总条数」,再用
whereIn('id', $ids)查详情——这样更新商品信息不影响缓存一致性
商品模块看着简单,实际最易踩坑的是数据一致性(比如库存扣减和订单创建不同步)、上传路径权限、以及分页时的索引失效。这些点不写进代码注释,半年后你自己都得重读三遍才能改对。











