后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载导读控制器Controller是 Yii 2 MVC 架构中承上启下的核心组件它接收应用转发过来的请求解析输入数据调度模型完成业务处理再把结果注入视图生成响应。本篇基于 Yii 2 官方文档 docs/guide-fr/structure-controllers.md并结合框架源码framework/base/Controller.php、framework/base/Action.php、framework/web/Controller.php等与测试用例tests/framework/base/ControllerTest.php、tests/framework/web/ControllerTest.php系统讲解控制器的定义、路由机制、创建规则、动作Action的两种形态、参数绑定、控制器生命周期与编码最佳实践。读完你将能够独立编写规范、可复用、符合 Yii 2 约定的控制器代码并理解请求从 URL 到响应的完整执行链路。控制器在 MVC 架构中的角色控制器是 MVC将控制权移交给控制器之后控制器会依次完成以下工作分析进入的请求数据将数据传递给模型把模型的处理结果注入视图最终生成对外输出的响应。从源码结构看Yii 2 的控制器体系由yii\base\Controllerframework/base/Controller.php作为通用基类Web 应用使用的yii\web\Controllerframework/web/Controller.php和 console 应用使用的yii\console\Controller都继承自它。基类内部还定义了EVENT_BEFORE_ACTION与EVENT_AFTER_ACTION两个事件常量framework/base/Controller.php这为后续生命周期一节提到的钩子机制提供了基础。Actions控制器的最小执行单元控制器由**动作Actions**组成动作是终端用户可以直接请求执行的最小单元。一个控制器可以包含一个或多个动作。下面示例定义了一个post控制器包含view和create两个动作namespace app\controllers; use Yii; use app\models\Post; use yii\web\Controller; use yii\web\NotFoundHttpException; class PostController extends Controller { public function actionView($id) { $model Post::findOne($id); if ($model null) { throw new NotFoundHttpException; } return $this-render(view, [ model $model, ]); } public function actionCreate() { $model new Post; if ($model-load(Yii::$app-request-post()) $model-save()) { return $this-redirect([view, id $model-id]); } else { return $this-render(create, [ model $model, ]); } } }在view动作由actionView()方法定义中代码首先根据请求的模型 ID 加载模型如果加载成功就使用名为view的视图将其展示出来否则抛出异常。在create动作由actionCreate()方法定义中逻辑类似先用请求数据填充一个新的模型实例并保存。如果两步都成功就将浏览器重定向到view动作并携带新模型的 ID否则展示create视图让用户补充需要的输入。值得注意的两点编码习惯也可在源码中印证actionCreate()中通过Yii::$app-request-post()获取请求数据体现了控制器访问请求数据的职责保存成功后使用$this-redirect(...)返回一个 response 对象这是 Post/Redirect/GetPRG模式的典型写法能避免用户刷新页面导致表单重复提交。路由Routes终端用户通过所谓的**路由route**来请求动作的执行。一条路由是字符串由以下部分组成模块 IDmodule ID仅当控制器属于某个非应用自身的模块时才存在控制器 ID在同应用或同模块如果控制器属于模块内唯一标识控制器的字符串动作 ID在同一控制器内唯一标识动作的字符串。路由的格式如下控制器ID/动作ID如果控制器属于模块则格式为模块ID/控制器ID/动作ID例如用户请求 URLhttps://hostname/index.php?rsite/index就会执行site控制器中的index动作。关于路由如何被解析为具体动作的细节请参阅路由与 URL 生成一节。从源码看路由解析发生在yii\base\Module::createController()framework/base/Module.php它会先检查controllerMap再检查是否为模块 ID最后才按照控制器命名规则尝试实例化控制器类——这个优先级顺序值得开发者留意它是后文controllerMap能覆盖默认命名约束的根本原因。创建控制器在 [[yii\web\Application|Web 应用]]中控制器必须继承 [[yii\web\Controller]] 或其子类类似地在 [[yii\console\Application|console 应用]]中控制器必须继承 [[yii\console\Controller]] 或其子类。下面代码定义了一个名为site的控制器namespace app\controllers; use yii\web\Controller; class SiteController extends Controller { }控制器 IDController IDs通常一个控制器被设计用于处理某类特定资源的请求因此控制器 ID 往往是表示资源类型的名词。例如你可以用article作为处理文章数据的控制器 ID。默认情况下控制器 ID 只能包含以下字符英文小写字母、数字、下划线、连字符和正斜杠。例如article和post-comment都是合法的控制器 ID而article?、PostComment、admin\post都不合法。控制器 ID 还可以包含子目录前缀。例如admin/article表示 [[yii\base\Application::controllerNamespace|控制器命名空间]]下admin子目录中的article控制器。子目录前缀允许的字符包括英文大小写字母、数字、下划线和正斜杠其中正斜杠用作多级子目录的分隔符例如panels/admin。从源码确认控制器命名空间的默认值为app\controllers定义于 framework/base/Application.php。即默认情况下控制器类应位于app/controllers目录app是应用根目录的别名。控制器类命名规则Controller Class Naming控制器类名可以由控制器 ID 按以下步骤推导出来把 ID 中每个由连字符分隔的单词首字母转为大写。注意如果控制器 ID 包含斜杠该规则只作用于 ID 中最后一个斜杠之后的部分删除连字符并把所有正斜杠替换为反斜杠命名空间分隔符追加后缀Controller在前面加上 [[yii\base\Application::controllerNamespace|控制器命名空间]]。假设控制器命名空间取默认值app\controllers示例如下控制器 ID派生出的控制器类名articleapp\controllers\ArticleControllerpost-commentapp\controllers\PostCommentControlleradmin/post-commentapp\controllers\admin\PostCommentControlleradminPanels/post-commentapp\controllers\adminPanels\PostCommentController控制器类必须是可自动加载的。因此在上面的示例中article控制器类应保存在别名为app/controllers/ArticleController.php的文件中而admin/post-comment控制器则应位于app/controllers/admin/PostCommentController.php。提示最后一个示例admin/post-comment展示了如何把控制器放入控制器命名空间下的子目录中。当你希望将控制器按类别组织、又不想使用模块时这种方式非常有用。控制器映射表Controller Map你可以配置 [[yii\base\Application::controllerMap|controller map控制器映射表]]来绕过上述关于控制器 ID 和类名的约束。这在使用第三方控制器、无法控制其类名时尤为有用。控制器映射表在应用配置中配置例如[ controllerMap [ // 使用类名声明 account 控制器 account app\controllers\UserController, // 使用配置数组声明 article 控制器 article [ class app\controllers\PostController, enableCsrfValidation false, ], ], ]从源码看controllerMap定义于yii\base\Moduleframework/base/Module.php应用同样继承该属性。在createController()中控制器映射表的匹配优先于模块匹配和默认的类名推导framework/base/Module.php。上面配置数组中enableCsrfValidation false这样的属性会被传给Yii::createObject()来初始化控制器实例——这是 Yii 2 配置机制的典型应用。默认控制器Default Controller每个应用都有一个通过 [[yii\base\Application::defaultRoute]] 属性指定的默认控制器。当请求没有指定任何路由时就使用该属性指定的路由。对于 [[yii\web\Application|Web 应用]]其默认值为site源码见 framework/web/Application.php对于 [[yii\console\Application|console 应用]]其默认值为help源码见 framework/console/Application.php。因此如果 URL 是https://hostname/index.php将由site控制器处理请求。你可以通过如下应用配置修改默认控制器[ defaultRoute main, ]补充说明yii\base\Module自身也有一个默认值default的defaultRouteframework/base/Module.phpWeb/console 应用分别将其覆盖为site与help。当路由为空时Module::runAction()/createController()会用defaultRoute填充。创建动作Actions创建动作非常简单在控制器类中定义所谓的动作方法即可。动作方法是以action开头的公有方法其返回值代表要发送给终端用户的响应数据。下面代码定义了index和hello-world两个动作namespace app\controllers; use yii\web\Controller; class SiteController extends Controller { public function actionIndex() { return $this-render(index); } public function actionHelloWorld() { return Hello World; } }动作 IDAction IDs动作通常被设计为对资源做特定操作因此动作 ID 一般是动词如view查看、update更新等。默认情况下动作 ID 只能包含以下字符英文小写字母、数字、下划线和连字符可以用连字符分隔单词。例如view、update2、comment-post都是合法的动作 ID而view?和Update不合法。从源码确认yii\base\Controller::createAction()正是用正则/^(?:[a-z0-9_]-)*[a-z0-9_]$/校验动作 IDframework/base/Controller.php校验失败的动作 ID 直接无法解析为动作。tests/framework/base/ControllerTest.php中的actionIdMethodProvider数据提供器覆盖了大量边界用例如-apple、apple--id、apple\33、apple333]等均非法可以当作动作 ID 合法字符的权威清单来阅读。创建动作有两种方式内联动作inline和独立动作standalone。内联动作定义为控制器中的方法独立动作则是继承 [[yii\base\Action]] 或其子类的类。内联动作创建成本低在没有复用意图时通常是首选独立动作则主要用于在不同控制器间复用或作为扩展分发。内联动作Inline Actions内联动作即上面描述的、以动作方法形式定义的动作。动作方法名由动作 ID 按以下步骤推导把动作 ID 中每个单词首字母转为大写删除连字符加上前缀action。例如index变成actionIndexhello-world变成actionHelloWorld。注意动作方法名是区分大小写的。如果你定义了名为ActionIndex的方法它不会被当作动作方法因此请求index动作会抛出异常。此外动作方法必须是公有的——私有或受保护方法不会定义内联动作。从源码看createAction()在方法匹配成功后还会用反射校验isPublic()且方法名与推导结果完全一致framework/base/Controller.php然后创建yii\base\InlineAction实例framework/base/InlineAction.php它负责通过call_user_func_array()调用控制器方法并传递绑定好的参数framework/base/InlineAction.php。内联动作是最常见的动作形态因为创建成本低。但如果你打算在多处复用同一动作或者想分发这个动作就应该考虑把它定义为独立动作。独立动作Standalone Actions独立动作以继承 [[yii\base\Action]] 或其子类的动作类来定义。例如在 Yii 发行版中就内置了 [[yii\web\ViewAction]] 和 [[yii\web\ErrorAction]]二者都是独立动作。要使用独立动作需要在控制器类中重写 [[yii\base\Controller::actions()]] 方法在*动作映射表action map*中声明它public function actions() { return [ // 使用类名声明 error 动作 error yii\web\ErrorAction, // 使用配置数组声明 view 动作 view [ class yii\web\ViewAction, viewPrefix , ], ]; }如你所见actions()方法应返回一个数组键是动作 ID值是相应的动作类名或配置数组。与内联动作不同独立动作的动作 ID 可以包含任意字符只要它们在actions()方法中被声明过即可。从源码看createAction()会先查动作映射表framework/base/Controller.php命中后用Yii::createObject()创建动作实例。要创建独立动作类需要继承 [[yii\base\Action]] 或其子类并实现一个名为run()的公有方法。run()方法的作用与动作方法类似。例如?php namespace app\components; use yii\base\Action; class HelloWorldAction extends Action { public function run() { return Hello World; } }从源码看yii\base\Action的构造函数接收($id, $controller, $config)framework/base/Action.phprun()方法由runWithParams()调用并且在执行前后分别触发beforeRun()与afterRun()两个可覆写钩子framework/base/Action.php。如果类中没有run()方法runWithParams()会抛出InvalidConfigException。框架内置的两个典型独立动作可以加深理解[[yii\web\ViewAction]]用于展示静态页面其viewPrefix属性默认值为pagesframework/web/ViewAction.php通过 GET 参数指定要渲染的视图名[[yii\web\ErrorAction]]用于展示应用错误需要配合errorHandler组件配置errorAction site/error使用渲染views/site/error.php视图framework/web/ErrorAction.php。动作的返回值Action Results动作方法或独立动作run()方法的返回值代表对应动作的执行结果。返回值可以是一个 response 对象它将被原样发送给终端用户。对于 [[yii\web\Application|Web 应用]]返回值也可以是任意数据这些数据会被赋值给 [[yii\web\Response::data]]随后被转换为表示响应体的字符串对于 [[yii\console\Application|console 应用]]返回值还可以是一个整数表示命令执行的[[yii\console\Response::exitStatus|退出状态]]。从源码看console 应用的handleRequest()会把非 Response 的返回值直接写入$response-exitStatusframework/console/Application.php最终作为进程退出码。上面示例中动作的返回值都是字符串会被当作发送给终端用户的响应体。下面的例子展示动作如何通过返回 response 对象把浏览器重定向到新 URL因为 [[yii\web\Controller::redirect()|redirect()]] 方法返回一个 response 对象public function actionForward() { // 将用户浏览器重定向到 https://example.com return $this-redirect(https://example.com); }从源码看yii\web\Controller还提供了一组返回 response 对象的便捷方法asJson()、asXml()设置Response::$format并返回当前 response 对象framework/web/Controller.php以及goHome()、goBack()、refresh()等重定向快捷方式framework/web/Controller.php。动作参数Action Parameters内联动作的动作方法和独立动作的run()方法都可以接受参数称为动作参数。它们的值来自请求对于 [[yii\web\Application|Web 应用]]每个动作参数的值以参数名作为键从$_GET中获取对于 [[yii\console\Application|console 应用]]它们对应命令行参数。下面示例中view动作内联动作声明了两个参数$id和$versionnamespace app\controllers; use yii\web\Controller; class PostController extends Controller { public function actionView($id, $version null) { // ... } }针对不同请求动作参数将被填充如下请求 URL结果https://hostname/index.php?rpost/viewid123$id获得值123$version保持null因为请求中没有version查询参数https://hostname/index.php?rpost/viewid123version2$id和$version分别获得123和2https://hostname/index.php?rpost/view抛出 [[yii\web\BadRequestHttpException]] 异常因为请求未提供必需的$id参数https://hostname/index.php?rpost/viewid[]123抛出 [[yii\web\BadRequestHttpException]] 异常因为$id意外收到了数组值[123]如果你希望动作参数接受数组需要在方法定义中把参数类型声明为arraypublic function actionView(array $id, $version null) { // ... }现在如果请求是https://hostname/index.php?rpost/viewid[]123$id会获得值[123]如果请求是https://hostname/index.php?rpost/viewid123$id同样会收到数组值因为标量值123会被自动转换成数组。从源码看参数绑定发生在yii\web\Controller::bindActionParams()framework/web/Controller.php其核心逻辑包括用反射读取动作方法/run()方法的参数签名缺失且无默认值的参数会累积到$missing列表最终抛出BadRequestHttpException消息为Missing required parameters: ...带类型声明单类型或联合类型的参数会经过类型过滤array类型会把标量强制转为数组int/float/bool用filter_var()校验framework/web/Controller.php类型不匹配同样抛出BadRequestHttpException非内置类型类类型的参数会走依赖注入绑定从模块、容器中解析服务framework/base/Controller.php。tests/framework/web/ControllerTest.php中有大量针对参数绑定的测试例如验证缺失参数抛BadRequestHttpException、类型不匹配时消息为Invalid data received for parameter foo.、以及array类型参数的自动转换等是理解这些行为的绝佳参考。以上示例主要展示 Web 应用中动作参数的工作方式。对于 console 应用请参阅控制台命令一节获取更多细节。默认动作Default Action每个控制器都有一个通过 [[yii\base\Controller::defaultAction]] 属性指定的默认动作。当路由只包含控制器 ID 时就表示请求该控制器的默认动作。默认情况下默认动作被设置为index源码见 framework/base/Controller.php。如果你想修改默认值只需在控制器类中覆写该属性如下所示namespace app\controllers; use yii\web\Controller; class SiteController extends Controller { public $defaultAction home; public function actionHome() { return $this-render(home); } }控制器的生命周期Controller Lifecycle处理请求时应用会根据请求的路由创建一个控制器。随后控制器经历如下生命周期来满足请求控制器被创建并配置完成后调用 [[yii\base\Controller::init()]] 方法控制器根据请求的动作 ID 创建动作对象如果动作 ID 未指定使用 [[yii\base\Controller::defaultAction|默认动作 ID]]如果动作 ID 在 [[yii\base\Controller::actions()|动作映射表]]中找到创建独立动作如果动作 ID 匹配某个动作方法创建内联动作其他情况抛出 [[yii\base\InvalidRouteException]] 异常控制器依次调用应用的beforeAction()方法、模块如果控制器属于模块的beforeAction()方法、控制器自身的beforeAction()方法如果其中某次调用返回false后续未执行的beforeAction()调用会被跳过动作执行被取消默认情况下每次beforeAction()调用都会触发beforeAction事件你可以为它挂接事件处理器控制器运行动作动作参数会根据请求数据被解析和填充控制器依次调用控制器自身的afterAction()方法、模块的afterAction()方法、应用的afterAction()方法默认情况下每次afterAction()调用都会触发afterAction事件你可以为它挂接事件处理器应用获取动作结果并赋值给 response 对象。以上 6 步与源码实现严格对应可以逐条印证步骤 1yii\base\Controller::init()会把request和response属性解析为应用组件实例framework/base/Controller.php步骤 2createAction()完整实现了映射表 → 内联方法 → null的解析次序framework/base/Controller.php解析失败时runAction()抛出InvalidRouteException步骤 3/5runAction()先按模块从外到内的顺序收集beforeAction()通过的模块链再执行$this-beforeAction($action)返回false则$runAction false并跳过动作执行动作执行后依次调用控制器和模块的afterAction()framework/base/Controller.php步骤 3/5 中的事件beforeAction()/afterAction()的实现就是触发EVENT_BEFORE_ACTION/EVENT_AFTER_ACTION事件并通过ActionEvent控制流程framework/base/Controller.php。基于此行为与过滤器如PageCache、AccessControl才能以声明方式介入动作执行步骤 4runAction()调用$action-runWithParams($params)最终由InlineAction::runWithParams()或Action::runWithParams()完成参数绑定与调用framework/base/InlineAction.php。一个值得注意的细节runAction()会记录当前动作到$this-action执行结束后恢复旧值framework/base/Controller.php因此在动作内部始终可以通过$this-action获取正在执行的动作对象。最佳实践Best Practices在精心设计的应用中控制器通常非常轻薄thin每个动作只包含少量代码。如果你的控制器相当复杂通常意味着你需要重构把部分代码移到其他类中。以下是控制器相关的具体最佳实践。控制器可以访问请求数据可以使用请求数据调用模型方法及其他服务组件的方法可以使用视图来组合响应不应该处理请求数据——这应该由模型层完成应该避免内嵌 HTML 或其他表现层代码——这更适合放在视图中。这条原则与上面PostController示例一脉相承actionView()只做查模型 → 判空 → 渲染视图三件事actionCreate()只做装载请求数据 → 保存 → 重定向/渲染表单所有数据校验、过滤、持久化逻辑都交给Post模型完成。坚持胖模型、瘦控制器Fat Model, Thin Controller配合本文介绍的actions()动作映射表、独立动作复用机制以及beforeAction/afterAction生命周期钩子就能构建出结构清晰、可测试、可维护的 Yii 2 应用。赞分享后端Web框架【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址https://gitcode.com/gh_mirrors/yi/yii2点击查看免费下载相关推荐Yii 2 控制器Controller完全指南路由、动作、生命周期与最佳实践Yii 2 控制器Controller完全指南路由、动作、生命周期与最佳实践 导读 控制器Controller是 Yii 2 中 MVC 架构的核心组后端Web框架Yii 2 控制器Controller完全指南动作、路由、生命周期与最佳实践Yii 2 控制器Controller完全指南动作、路由、生命周期与最佳实践 控制器是 Yii 2 框架 MVC 架构的核心枢纽它接收请求reques后端Web框架Yii 2 组件体系完全指南Component、BaseObject 与对象生命周期实战Yii 2 组件体系完全指南Component、BaseObject 与对象生命周期实战 组件Component是 Yii 2 应用中最核心的构建单元几后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
CUDA向量加法性能剖析:用Nsight Compute读懂kernel快慢 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/23 1:20:19
RabbitMQ 3.11.2 维护版本解析:镜像队列稳定性修复与 MQTT 维护模式行为修正 RabbitMQ 3.11.2 维护版本解析:镜像队列稳定性修复与 MQTT 维护模式行为修正 【免费下载链接】rabbitmq-server Open source RabbitMQ: core server and tier 1 (built-in) plugins 项目地址: https://gitcode.com/gh_mirrors/ra/rabbitmq-server
RabbitMQ 3… · 2026/9/23 1:20:19
日在野球拳保姆级教程:面试被问原理答不上来?3天搞懂核心逻辑 日在野球拳保姆级教程:面试被问原理答不上来?3天搞懂核心逻辑 面试被问底层原理,脑子一片空白?别慌,这份日在野球拳保姆级教程帮你3天补齐短板。很多开发者背了八股文,一到追问就露馅,核心是没搞懂执行链路。今天不聊虚的,直接拆解日在野球拳的内存… · 2026/9/23 1:20:19
三维点云边界提取:算法原理、Open3D实现与调参实战 简介:这份资源围绕三维点云边界提取这一经典问题展开,面向具备一定点云处理基础、希望深入理解边界检测原理并落地实现的开发者与研究人员,可用于三维重建、目标识别、逆向工程等场景中的轮廓提取环节。压缩包共2个文件,包含1份PD… · 2026/9/23 2:18:46
内网穿透实战:用ngrok将本地Tomcat网站映射到公网 简介:面向个人网站搭建初学者的实操教程,重点讲解如何借助 Tomcat 与内网穿透工具 ngrok,将本地运行的网站发布到公网供他人访问。文档先明确需要准备的四项条件——JDK 1.8、Apache Tomcat 7、个人网站源码及 ngrok 账号,再通过原… · 2026/9/23 2:18:46
JavaWeb开发必懂的HTTP协议:从请求报文到实战排查 开头部分直接用Java Web开发者的视角切入,讲清楚HTTP协议在Web开发里到底处于什么位置,再引出这篇博文能帮你解决什么、适合谁读。下面就是正文。1. 先把HTTP协议在JavaWeb里的位置摆正做JavaWeb开发也快十年了,带过的新人少说也有几十个。我… · 2026/9/23 2:18:46
企业微信通讯录同步自建指南:增量更新与冲突解决全解析 在企业微信通讯录同步这件事上,我最开始的想法很简单:每天定时拉一次全量通讯录,写入内部系统,完事。结果第一次上线就被现实按在地上摩擦——公司三千多人的通讯录,每天都有入离职、跨部门调动、岗位调整,… · 2026/9/23 2:18:46
2026最新少女心草莓粉色系头像渲染原理与性能优化实战 2026最新少女心草莓粉色系头像渲染原理与性能优化实战 面试被问原理答不上来,是不是让你当场僵住?别慌,今天用2026最新少女心草莓粉色系头像渲染案例,把底层逻辑和性能优化一次讲透,让你下次稳稳接住追问。 概念速懂… · 2026/9/23 2:18:40
ECE-R10 Rev.6汽车EMC新规落地指南:LED驱动与车载以太网硬核整改 简介:本资源为联合国欧洲经济委员会(UNECE)发布的ECE R10法规最新修订版——Rev.6正式文本(2019年10月15日生效),面向汽车电子工程师、EMC测试人员、整车及零部件认证工程师,解决车辆电磁兼容性… · 2026/9/23 2:18:34
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29