不是 PHP 天生更难,而是大模型在 PHP 项目里更容易踩这几类坑:
训练分布偏了
大模型见过更多现代 JS / Python / TS 示例,PHP 高质量训练样本里混着大量历史包袱代码:全局函数、弱类型、老框架写法、半 OOP 半过程式、各种“能跑就行”的项目。结果就是模型学到的 PHP 风格不稳定。
PHP 生态割裂更严重
同样是 PHP,原生 PHP、Laravel、Symfony、Yii2、Hyperf、WordPress、老 CMS 项目,写法差异非常大。模型很容易把不同生态的习惯串台。比如在 Yii2 项目里写出 Laravel 式思路,或者忽略框架约定。
代码库里“隐式约定”太多
PHP 老项目尤其依赖约定、魔术方法、容器、配置数组、动态属性、ActiveRecord、行为扩展。人类接手项目会先读目录结构、基类、组件注册、表结构和历史代码;模型如果上下文不够,就只能猜。猜得越多,质量越差。
动态语言让“看起来对”变多了
PHP 很多错误不是语法级马上暴露,而是运行到某个分支、某个环境、某个请求参数才炸。模型容易生成“表面合理”的代码,但缺少真正贴合业务的约束。
很多 PHP 项目本身就不够规范
如果项目缺少类型声明、静态分析、测试、统一组件封装,模型几乎没有护栏。它只能模仿现有代码,而现有代码如果本身杂乱,输出只会更杂乱。
模型通常不理解“项目级正确性”
它擅长补一个函数,不擅长自动领会:
ActiveForm所以你感受到的“PHP 写得差”,本质上常常是“它对具体 PHP 项目的上下文理解不够”。
更准确地说,大模型写 PHP 在这几种情况下最差:
反过来,它在这些情况下能明显变好:
不是“大模型不会写 PHP”,而是“PHP 项目太依赖具体上下文和历史约定,而大模型默认最缺的就是这个”。
Yii2 正好踩中了大模型最不稳的几个点:老框架、强约定、弱显式、魔术多、业务代码历史包袱重。
最核心的原因有这几类。
比如:
ActiveRecord 的属性来自数据库字段,不在类里显式声明rules()、scenarios() 决定哪些字段可赋值、可验证behaviors() 会偷偷加时间戳、操作者、格式转换relations 是字符串和约定驱动,不是强类型关系Yii::$app->xxx 里的组件来自配置,不在当前文件里模型看到一个类时,往往拿不到完整运行态信息,于是只能猜。
PHP 本来就弱类型,Yii2 又把很多信息放在框架机制和配置里,模型就更容易“看着像对,其实不对”。
SearchModel 还是 Modelload() + validate() + save(),还是自定义 DTO / serviceActiveDataProvider这些在 Laravel 里很多时候社区主流更集中,Yii2 项目差异反而更大。
模型一旦没先读你项目里的“相似实现”,就会混出一套半 Yii2 半别的框架的东西。
常见翻车方式:
save()joinWith()、with()、asArray(),结果性能或结果集出错safe 字段和批量赋值风险Yii2 的 AR 上手太简单,所以模型很容易走“最省事”的路径;但“最省事”通常不是项目里该有的写法。
@app、@common、@backend 决定路径解析render() 传数组这些东西对人类开发者不陌生,但对模型不友好。
因为模型更擅长补“显式 API 调用”,不擅长在一堆数组和约定字符串里推断真实语义。
很多 Yii2 项目会同时存在:
BaseActiveRecord / BaseController模型如果不先读基类和现有模块,很容易:
这些都不是补一段代码就能自动对的。
Yii2 业务开发更像“接入现有系统流程”,不是“单点写个函数”。模型天然就不擅长这种项目级接入。
所以模型学到的 Yii2,经常停留在“Gii 生成 CRUD + 基础 ActiveRecord”层面。
一旦进入真实企业项目,就明显不够用。
一句话说透:
Yii2 的问题不是难写,而是“真实正确性”高度依赖项目内约定、配置和历史代码;这些恰好都是大模型默认最看不清的地方。
所以它在 Yii2 里最容易写烂的典型表现是:
本文由 best 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。