- 后端
- Web框架
【免费下载链接】yii2
Yii 2: The Fast, Secure and Professional PHP Framework
本篇指南以 Yii 2 框架(仓库路径 framework/)的官方入门教程为基础,完整演示如何在 Yii 2 应用中构建一个"接收用户输入 → 校验 → 回显确认"的表单页面:你需要创建一个承载数据的模型类、一个处理提交的操作,以及两个负责渲染的视图。读完本文,你将掌握yii\base\Model的验证规则声明、load()+validate()的提交处理范式、ActiveForm部件的高效表单生成,以及"客户端 JavaScript 校验 + 服务端 PHP 校验"双重保障机制的底层原理,可直接复制代码到自己的应用中实战。
本章在教程中的位置与前置知识
本文对应官方入门教程的"表单使用"章节(乌兹别克语版见 docs/guide-uz/start-forms.md,英文原版见 docs/guide/start-forms.md),完整教程目录可在 docs/guide-uz/README.md 中查看。在开始之前,建议先完成以下前置章节:
- 安装 Yii 并掌握应用启动流程;
- 通过 "你好"示例 了解操作(action)的创建与调用方式;
- 理解 MVC 三要素:操作 structure-controllers.md、视图 structure-views.md、模型 structure-models.md。
本教程的目标页面包含两个输入框(Name 与 Email),用户提交后页面回显其输入内容。为达成这一目标,除了创建一个操作和两个视图之外,还需要创建一个模型。你将学会:
- 创建模型,用属性表示用户通过表单输入的数据;
- 声明验证规则(rules)来校验输入数据;
- 在视图中用
ActiveForm部件构建 HTML 表单。
第一步:创建数据模型 EntryForm
用户提交的数据将由一个EntryForm模型类来表示,文件保存在models/EntryForm.php:
<?php namespace app\models; use yii\base\Model; class EntryForm extends Model { public $name; public $email; public function rules() { return [ [['name', 'email'], 'required'], ['email', 'email'], ]; } }该类的命名遵循 Yii 的类自动加载约定——类名即文件名、以.php结尾,详见类自动加载章节。
模型属性与 rules() 验证规则
EntryForm继承自 yii\base\Model,这是 Yii 为"不与数据库表绑定"的模型类提供的基类(若模型对应数据库表,通常应继承yii\db\ActiveRecord)。类中定义了两个公共成员name和email,用于保存用户输入的数据;同时定义了rules()方法,返回一组数据验证规则:
name与email均为必填项(required规则);email的值必须是语法上合法的电子邮件地址(email规则)。
模型的验证行为:validate()、hasErrors() 与 getErrors()
当EntryForm对象被用户数据填充后,可以调用 Model::validate() 触发验证流程。验证失败时 Model::hasErrors() 返回true,并可通过 Model::getErrors() 查看具体错误信息:
<?php $model = new EntryForm(); $model->name = 'Qiang'; $model->email = 'bad'; if ($model->validate()) { // 数据合法 } else { // 数据不合法 // 使用 $model->getErrors() 获取错误详情 }从源码看,validate()的执行流程(framework/base/Model.php)依次是:清除旧错误 → 触发beforeValidate事件(可在此拦截,返回false则终止验证)→ 依据当前场景(scenario)取出活动属性与活动验证器 → 逐个调用Validator::validateAttributes()→ 触发afterValidate事件 → 最终返回!$this->hasErrors()。这意味着你可以在模型中重写beforeValidate()/afterValidate()做前置检查或后置处理,也可以借助事件机制扩展验证逻辑。
第二步:创建操作 actionEntry
接下来在site控制器中创建一个entry操作来使用这个新模型:
<?php namespace app\controllers; use Yii; use yii\web\Controller; use app\models\EntryForm; class SiteController extends Controller { // ...已有的代码... public function actionEntry() { $model = new EntryForm(); if ($model->load(Yii::$app->request->post()) && $model->validate()) { // $model 中的数据已通过验证 // 在这里对 $model 做一些有意义的事情…… return $this->render('entry-confirm', ['model' => $model]); } else { // 页面首次加载,或数据存在验证错误 return $this->render('entry', ['model' => $model]); } } }load() 与数据填充原理
操作先创建EntryForm实例,然后尝试用$_POST中的数据填充模型(Yii 中通过 yii\web\Request::post() 提供)。若模型被成功填充(即用户已提交 HTML 表单),操作调用 validate() 确认输入值的合法性。
Model::load() 的底层实现体现了 Yii 表单命名空间的约定:它默认通过formName()(即模型类短名,见 framework/base/Model.php)在$_POST中寻找对应子数组,例如$_POST['EntryForm']['name']。这也解释了为什么ActiveForm渲染出的输入框 name 属性形如EntryForm[name]——load()正是按这个约定取数并调用setAttributes()完成批量赋值的。
Yii::$app 与 request 组件
Info: 表达式
Yii::$app代表应用实例,是一个全局可访问的单例,同时也是一个服务定位器,可提供request、response、db等组件。上面的代码正是通过应用实例的request组件访问$_POST数据。
Request::post()内部调用getBodyParams()解析请求体(对普通表单即$_POST,对 JSON 请求体会自动解码),无参数时返回全部 POST 参数数组,传入参数名则返回单个参数值并支持默认值。
渲染分支与 PRG 模式
若一切正常,操作渲染名为entry-confirm的视图,向用户确认数据提交成功;若未提交数据或数据有误,则渲染entry视图,展示 HTML 表单及校验错误信息。
Note: 本例为保持简洁,数据合法时直接渲染确认页。实际项目中,应优先使用 Controller::refresh() 或 Controller::redirect() 做"提交后重定向"(Post/Redirect/Get),以避免表单重复提交问题。
第三步:创建视图
最后创建entry-confirm与entry两个视图文件,它们被entry操作按上述分支渲染。
确认视图 entry-confirm
entry-confirm视图简单地回显用户输入的 name 与 email,保存在views/site/entry-confirm.php:
<?php use yii\helpers\Html; ?> <p>您输入了以下信息:</p> <ul> <li><label>Name</label>: <?= Html::encode($model->name) ?></li> <li><label>Email</label>: <?= Html::encode($model->email) ?></li> </ul>注意这里用 Html::encode() 对输出做 HTML 编码——这是防御 XSS 注入的基本实践,回显用户输入时必须编码。
表单视图 entry 与 ActiveForm 部件
entry视图负责构建 HTML 表单,保存在views/site/entry.php:
<?php use yii\helpers\Html; use yii\widgets\ActiveForm; ?> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'name') ?> <?= $form->field($model, 'email') ?> <div class="form-group"> <?= Html::submitButton('提交', ['class' => 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?>该视图使用了功能强大的部件 yii\widgets\ActiveForm 来构建 HTML 表单。begin()与end()方法分别渲染表单的开启与闭合标签;两个方法之间,通过 ActiveForm::field() 创建输入字段——第一个用于 "name",第二个用于 "email"。字段之后调用 Html::submitButton() 生成提交按钮。
每个field()调用都会返回一个 ActiveField 对象,默认渲染结构为:<label>标签 + 对应类型的<input>输入框 + 校验错误提示容器(help-block),外层再包一层带form-group与field-模型名-属性名类的容器 div。测试用例 tests/framework/widgets/ActiveFormTest.php 中展示了field()渲染 checkbox、radio 等输入类型的完整 HTML 结构,可作参考。
ActiveForm 默认行为参数
从 framework/widgets/ActiveForm.php 的源码可以看到该部件的一系列关键默认值,理解它们有助于你按需定制表单:
| 参数 | 默认值 | 说明 |
|---|---|---|
method | post | 表单提交方式,可改为get |
action | 空(提交到当前 URL) | 表单 action 地址 |
enableClientValidation | true | 是否启用客户端 JS 校验 |
enableAjaxValidation | false | 是否启用 AJAX 校验 |
validateOnSubmit | true | 提交时校验 |
validateOnChange | true | 输入值变化时校验 |
validateOnBlur | true | 输入框失焦时校验 |
errorCssClass | has-error | 校验失败时加到字段容器上的 CSS 类 |
successCssClass | has-success | 校验通过时的 CSS 类 |
validatingCssClass | validating | 校验进行中的 CSS 类 |
试运行:访问页面并观察两种结果
打开浏览器访问以下 URL:
https://hostname/index.php?r=site%2Fentryr=site%2Fentry即路由site/entry(URL 编码形式),由SiteController的actionEntry()处理。你将看到包含两个输入框的表单,每个输入框前都有标签提示应输入什么数据。若直接点击提交而不输入任何内容,或输入的 email 不合法,每个有问题的输入框旁都会显示错误信息:
输入合法的 name 与 email 并点击提交后,会看到一个展示刚才所输数据的新页面:
校验规则在底层如何工作
这里值得展开说明两个校验器在服务端的实现细节(对应上面的错误提示信息):
required规则由 RequiredValidator 实现,其skipOnEmpty默认设为false(见 framework/validators/RequiredValidator.php),保证空值也会触发校验;默认错误消息为{attribute} cannot be blank.(见 L63-L66),正是截图中 "Name cannot be blank." 的由来。测试用例 tests/framework/validators/RequiredValidatorTest.php 验证了null、空数组判为不合法,非空字符串判为合法的行为。email规则由 EmailValidator 实现,默认用正则校验地址格式,并遵循 RFC 5321 的长度限制(local 部分不超过 64 字符、总长度不超过 254 字符,见 L107-L118);allowName、checkDNS、enableIDN等选项默认均为false(见 L50-L66),可按需开启。丰富的边界用例见 tests/framework/validators/EmailValidatorTest.php。
原理揭秘:客户端与服务端双重验证
你可能会好奇这个 HTML 表单在背后究竟如何运作——每个输入框前自动出现标签、输入不正确时无需刷新页面即显示错误信息,看起来近乎"魔法"。
实际上,数据验证首先在客户端通过 JavaScript 完成,其次在服务端通过 PHP 执行。yii\widgets\ActiveForm 足够智能:它会提取你在EntryForm中声明的验证规则,将其转换为可执行的 JavaScript 代码,再用这些 JS 执行客户端校验。即使在浏览器中禁用 JavaScript,校验仍会在服务端进行——正如actionEntry()方法所示。这保证了任何情况下数据的有效性。
Warning: 客户端校验只是提升用户体验的便利手段。无论是否启用客户端校验,服务端校验都是必须的。
从源码看,这一机制的关键路径是 ActiveForm::registerClientScript():它注册yii.activeFormjQuery 插件,并执行jQuery('#表单id').yiiActiveForm(...);而在 ActiveField::getClientOptions() 中,Yii 遍历模型当前场景的活动验证器,调用各验证器的clientValidateAttribute()方法把服务端规则编译成 JS 函数(封装为JsExpression),并连同validateOnChange、validateOnBlur、validationDelay等选项一起传给前端插件。测试 ActiveFormTest::testRegisterClientScript() 验证了注册脚本的行为,并确认设置enableClientScript => false时不会输出任何 JS。
标签生成与自定义
输入框的标签由field()方法基于模型属性名自动生成。例如name属性会生成Name标签。其原理是 Model::getAttributeLabel() 优先读取attributeLabels()中显式声明的标签,否则调用generateAttributeLabel()把驼峰/下划线命名智能转换为可读文案。
你可以在视图中这样自定义标签:
<?= $form->field($model, 'name')->label('您的姓名') ?> <?= $form->field($model, 'email')->label('您的电子邮箱') ?>(在 ActiveField::label() 中可以看到,传入false还可以完全隐藏标签部分。)
Info: Yii 提供了大量此类部件,帮助你快速构建复杂、动态的视图。后面你会学到,编写一个新部件也极其简单。你可以把视图中的许多代码抽取为可复用的部件,从而简化后续视图开发。
小结
通过本教程,你已经完整接触了 MVC 架构模式中的每一个部分:学会了创建模型类来表示用户数据并对其进行验证,也学会了如何从用户那里获取数据、再把数据显示回浏览器。这在实际应用开发中是需要投入大量时间的任务,而 Yii 提供了强大的部件(如ActiveForm)让这项工作变得非常轻松。
在下一个章节中,你将学习与数据库打交道——这是几乎所有应用都需要的能力。相关进阶内容可参阅 数据库基础、查询构建器 与 Active Record;如需把本教程的模型改造为绑定数据表的ActiveRecord模型,请阅读 模型章节。
- 后端
- Web框架
【免费下载链接】yii2
Yii 2: The Fast, Secure and Professional PHP Framework
相关推荐
Yii2 表单处理实战指南:从 EntryForm 模型到 ActiveForm 视图的完整 MVC 流程
Yii2 表单处理实战指南:从 EntryForm 模型到 ActiveForm 视图的完整 MVC 流程 本篇文章基于 Yii2 官方指南的《フォームを扱う(
后端Web框架Yii 2 表单处理实战:从 Model 验证规则到 ActiveForm 视图的完整实现
Yii 2 表单处理实战:从 Model 验证规则到 ActiveForm 视图的完整实现 本篇技术指南以 Yii 2 框架官方入门教程"Working wit
后端Web框架Yii 2 表单处理实战:模型、验证与 ActiveForm 表单构建完整指南
Yii 2 表单处理实战:模型、验证与 ActiveForm 表单构建完整指南 本篇指南基于 Yii 2 官方指南(法语版) start forms.md ht
后端Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考