AI大模型这么牛了,为什么它在 Yii2 项目里容易写出屎山代码越写越烂

yii2 php Yii2 · best · 于 10天前 发布 · 65 次阅读

PHP vibecoding

大模型与PHP

不是 PHP 天生更难,而是大模型在 PHP 项目里更容易踩这几类坑:

  1. 训练分布偏了
    大模型见过更多现代 JS / Python / TS 示例,PHP 高质量训练样本里混着大量历史包袱代码:全局函数、弱类型、老框架写法、半 OOP 半过程式、各种“能跑就行”的项目。结果就是模型学到的 PHP 风格不稳定。

  2. PHP 生态割裂更严重
    同样是 PHP,原生 PHP、Laravel、Symfony、Yii2、Hyperf、WordPress、老 CMS 项目,写法差异非常大。模型很容易把不同生态的习惯串台。比如在 Yii2 项目里写出 Laravel 式思路,或者忽略框架约定。

  3. 代码库里“隐式约定”太多
    PHP 老项目尤其依赖约定、魔术方法、容器、配置数组、动态属性、ActiveRecord、行为扩展。人类接手项目会先读目录结构、基类、组件注册、表结构和历史代码;模型如果上下文不够,就只能猜。猜得越多,质量越差。

  4. 动态语言让“看起来对”变多了
    PHP 很多错误不是语法级马上暴露,而是运行到某个分支、某个环境、某个请求参数才炸。模型容易生成“表面合理”的代码,但缺少真正贴合业务的约束。

  5. 很多 PHP 项目本身就不够规范
    如果项目缺少类型声明、静态分析、测试、统一组件封装,模型几乎没有护栏。它只能模仿现有代码,而现有代码如果本身杂乱,输出只会更杂乱。

  6. 模型通常不理解“项目级正确性”
    它擅长补一个函数,不擅长自动领会:

    • 这个字段是不是数据库真实存在
    • 这个表单该不该走 ActiveForm
    • 这个查询有没有 N+1
    • 这个控制器是不是应该复用已有 service / repository / widget
    • 这个改动会不会破坏已有页面和权限逻辑

所以你感受到的“PHP 写得差”,本质上常常是“它对具体 PHP 项目的上下文理解不够”。

更准确地说,大模型写 PHP 在这几种情况下最差:

  • 老项目
  • Yii2 / ThinkPHP / WordPress 这类约定重、历史长的项目
  • 没有类型和测试
  • 你只给一句需求,不给现有代码和约束
  • 需要遵守团队封装和 UI 组件规范

反过来,它在这些情况下能明显变好:

  • 先让它读相关文件再改
  • 明确指定框架和版本
  • 明确“只能复用现有组件,不准自造轮子”
  • 提供模型、控制器、视图、迁移、表结构、相似页面
  • 跑静态分析和测试把错误回灌给它继续修

不是“大模型不会写 PHP”,而是“PHP 项目太依赖具体上下文和历史约定,而大模型默认最缺的就是这个”。

大模型与YII2

Yii2 正好踩中了大模型最不稳的几个点:老框架强约定弱显式魔术多业务代码历史包袱重

最核心的原因有这几类。

  1. Yii2 有大量“代码里没写全,但运行时成立”的东西
    大模型最怕这种。

比如:

  • ActiveRecord 的属性来自数据库字段,不在类里显式声明
  • rules()scenarios() 决定哪些字段可赋值、可验证
  • behaviors() 会偷偷加时间戳、操作者、格式转换
  • relations 是字符串和约定驱动,不是强类型关系
  • Yii::$app->xxx 里的组件来自配置,不在当前文件里

模型看到一个类时,往往拿不到完整运行态信息,于是只能猜。
PHP 本来就弱类型,Yii2 又把很多信息放在框架机制和配置里,模型就更容易“看着像对,其实不对”。

  1. Yii2 项目非常依赖“约定写法”,但这些约定又不是语言级约束
    例如:
    • 控制器里该不该直接写查询
    • 查询条件放 SearchModel 还是 Model
    • 表单该走 load() + validate() + save(),还是自定义 DTO / service
    • 列表页该用 ActiveDataProvider
    • 视图层该用 widget、partial、layout,还是直接拼 HTML
    • admin 端和 web 端可能还用不同 UI 组件库

这些在 Laravel 里很多时候社区主流更集中,Yii2 项目差异反而更大。
模型一旦没先读你项目里的“相似实现”,就会混出一套半 Yii2 半别的框架的东西。

  1. Yii2 的 ActiveRecord 很容易让模型写出“能跑但很烂”的代码
    这是 Yii2 最常见的问题区。

常见翻车方式:

  • 在循环里懒加载关联,造成 N+1
  • 把业务逻辑全塞进控制器
  • 把查询条件硬编码在多个地方
  • 忽略事务
  • 批量写入时还在一条条 save()
  • 误用 joinWith()with()asArray(),结果性能或结果集出错
  • 没处理 safe 字段和批量赋值风险

Yii2 的 AR 上手太简单,所以模型很容易走“最省事”的路径;但“最省事”通常不是项目里该有的写法。

  1. Yii2 到处是字符串、数组、别名、魔术调用,静态可见性差
    比如:
    • 路由是字符串
    • 验证器常是数组配置
    • 组件配置是数组
    • 事件、行为、场景很多是字符串键
    • 别名 @app@common@backend 决定路径解析
    • 视图变量靠 render() 传数组
    • GridView / ActiveForm / Select2 一堆配置数组嵌套

这些东西对人类开发者不陌生,但对模型不友好。
因为模型更擅长补“显式 API 调用”,不擅长在一堆数组和约定字符串里推断真实语义。

  1. Yii2 项目经常带有很深的历史层
    这点尤其致命。

很多 Yii2 项目会同时存在:

  • 旧式 fat controller
  • 旧表结构
  • 自定义基类 BaseActiveRecord / BaseController
  • 公共 helper
  • 自定义 widget
  • 扩展包二次封装
  • 前后台分离不彻底
  • 模块、RBAC、菜单、资产包一套历史逻辑

模型如果不先读基类和现有模块,很容易:

  • 重复造轮子
  • 绕开已有封装
  • 破坏权限判断
  • 写出不符合现有 UI 体系的页面
  • 忽略团队已经统一好的组件用法
  1. Yii2 里“正确”往往不是语法正确,而是流程正确
    比如新增一个表单页,真正的正确性可能包括:
    • Model 规则是否完整
    • 场景是否对
    • 控制器是否做了权限判断
    • 视图是否用统一表单组件
    • 提交后跳转和 flash 是否一致
    • 列表页筛选是否同步 SearchModel
    • 是否影响现有 GridView 过滤
    • 是否需要事务、日志、审计、队列
    • 是否符合现有菜单和路由规范

这些都不是补一段代码就能自动对的。
Yii2 业务开发更像“接入现有系统流程”,不是“单点写个函数”。模型天然就不擅长这种项目级接入。

  1. Yii2 的高质量公开样本没有你想的那么多
    网上当然有 Yii2 代码,但问题是:
    • 很多示例很老
    • 很多教程只讲基础 CRUD
    • 大量真实项目代码并不公开
    • 公开代码质量参差不齐
    • 你项目里还可能用了很多自定义封装和扩展

所以模型学到的 Yii2,经常停留在“Gii 生成 CRUD + 基础 ActiveRecord”层面。
一旦进入真实企业项目,就明显不够用。

一句话说透:

Yii2 的问题不是难写,而是“真实正确性”高度依赖项目内约定、配置和历史代码;这些恰好都是大模型默认最看不清的地方。

所以它在 Yii2 里最容易写烂的典型表现是:

  • 像 Yii2,但不符合你项目约定
  • 能提交,但权限、验证、场景不完整
  • 页面能出,但没复用现有组件
  • 查询能跑,但性能差
  • 改动局部能工作,但破坏系统一致性

本文由 best 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。

共收到 0 条回复
没有找到数据。
添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册