视图中只应进行纯展示逻辑的条件判断,如布尔字段显示图标、时间格式化、元素显隐;禁止在视图中处理业务逻辑(如deal_type分组)、数据库查询、n+1调用或空值sql判断,否则违反mvc、难调试且性能差。

视图里写条件判断本身不难,但容易写出违反 MVC 原则、难以调试、性能差的代码——真正该纠结的不是“怎么写”,而是“该不该在这里写”。
为什么不该在 View 里做 deal_type 分组这类逻辑
比如你看到 deal_type 是 0 或 1,想在视图里用 if ($item->deal_type == 0) 分开渲染优惠券和活动表格。这看似省事,实则埋了三个坑:
- 控制器传来的数据是扁平数组,视图被迫承担分类职责,后续加个“已过期”筛选就得改两处(控制器 + 所有相关视图)
- 如果每个
$item都要调用get_likes()这类方法,会触发 N+1 查询——视图层根本没法批量预加载 -
view_cell()或局部视图虽能拆分,但无法解决数据结构混乱问题;它只是把脏活从一个文件挪到另一个文件
where('field', null) 在 View 里查空值会失效
如果你在视图里拼 SQL 条件(比如用 $this->db),或试图用 PHP 判断数据库字段是否为空,常见错误是:
- 写
if (!$item->name)—— 会把''、0、null全当“空”,但数据库里0可能是合法状态值(如status = 0表示禁用) - 写
if ($item->name === null)—— 看似严谨,但 CodeIgniter 查询结果中 NULL 字段常被转成空字符串,实际永远进不了这个分支 - 更隐蔽的是:视图里没权限访问
$this->db,强行调用会报Call to a member function on null
真需要条件渲染时,只做 presentation 层判断
视图里允许且推荐的条件判断,仅限于纯展示逻辑,例如:
- 根据布尔字段显示开关图标:
<?php echo $item->is_active ? '✅' : '❌'; ?> - 格式化时间:用
date('Y-m-d', strtotime($item->created_at)),但别在里面查数据库或调用模型方法 - 控制元素显隐:
<div class="alert <?php echo $error ? 'show' : 'hide'; ?>">...</div>,前提是$error已由控制器计算好并传入 - 避免嵌套三层以上 if/else;超过两层就该考虑抽成
view_cell('status_badge', ['status' => $item->status])
替代方案:用 view_cell() 封装可复用的展示逻辑
view_cell() 是 CodeIgniter 提供的、唯一被鼓励在视图里调用的“带逻辑的组件”。它要求:
- 对应类(如
App\Libraries\StatusBadge)不能有构造函数参数 - 方法必须返回字符串,不能直接 echo 或输出 HTML
- 所有数据依赖必须通过参数传入,禁止在内部访问
$this->db或$this->session - 示例:
<?php echo view_cell('StatusBadge::render', ['status' => $item->status]); ?>,而StatusBadge::render()内部只做 switch 判断和字符串拼接
最易被忽略的一点:view_cell 的类名和方法名必须严格匹配命名空间与大小写,且不能带 callback_ 前缀——那是表单验证专用的,混用会导致静默失败。











