ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Yii2 应用结构全景解析:从 MVC 骨架到入口脚本、应用对象与模块化协作

Yii2 应用结构全景解析:从 MVC 骨架到入口脚本、应用对象与模块化协作 Yii2 应用结构全景解析从 MVC 骨架到入口脚本、应用对象与模块化协作【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址: https://gitcode.com/gh_mirrors/yi/yii2Yii 2 应用遵循经典的模型-视图-控制器MVC设计模式组织业务代码同时在其之上定义了入口脚本、应用对象、应用组件、模块、过滤器与部件Widget等六大结构实体共同支撑一次完整请求的处理周期。本篇指南以官方法文版《Vue densemble》docs/guide-fr/structure-overview.md为骨架结合本仓库框架源码framework/目录与英文版结构指南docs/guide/系统讲解 Yii 应用的静态结构与运行生命周期帮助你掌握如何把控制器、模型、视图、模块、过滤器组织成一套可维护、可扩展的应用系统。MVCYii 应用的业务骨架Yii 应用按照 模型-视图-控制器MVC 架构模式组织模型Models代表数据、业务逻辑与校验规则对应 docs/guide/structure-models.md视图Views是模型的输出呈现形式对应 docs/guide/structure-views.md控制器Controllers接收用户输入并将其转换为对模型和视图的命令对应 docs/guide/structure-controllers.md。在典型的 Basic 项目模板中models/、views/、controllers/三个子目录直接对应这三类角色。控制器通过action方法暴露路由入口例如SiteController::actionIndex()读取模型数据后渲染视图并返回响应模型负责数据校验、数据库访问与业务规则视图只做展示逻辑。三者各司其职是理解后面所有结构实体的前提。六大结构实体一次请求周期的完整参与者除 MVC 之外Yii 应用还定义了以下六类实体它们共同构成上图所示的静态结构实体职责参考文档入口脚本Entry Scripts用户直接访问的 PHP 脚本负责启动一次请求处理周期docs/guide-fr/structure-entry-scripts.md应用对象Applications全局可访问的对象管理应用组件并协调它们完成请求docs/guide-fr/structure-applications.md应用组件Application Components注册到应用上的对象为完成请求提供各类服务docs/guide-fr/structure-application-components.md模块Modules自包含的软件包内部拥有完整 MVC可被应用组织为多个模块docs/guide-fr/structure-modules.md过滤器Filters在控制器实际处理每个请求之前和之后被调用的代码docs/guide-fr/structure-filters.md部件Widgets可嵌入视图的对象可包含控制器逻辑并在不同视图中复用docs/guide-fr/structure-widgets.md下面逐一深入剖析每一类实体。入口脚本请求处理周期的起点入口脚本是整个启动流程的第一步一个应用无论是 Web 应用还是控制台应用拥有且仅有一个入口脚本。Web 入口脚本必须存放在 Web 可访问目录下通常命名为index.php控制台入口脚本通常存放在应用根目录下并命名为yii可通过./yii route [arguments] [options]执行。入口脚本主要完成六件事见 docs/guide/structure-entry-scripts.md定义全局常量注册 Composer 自动加载器引入 Yii 类文件本仓库即 framework/Yii.php加载应用配置创建并配置应用实例调用\yii\base\Application::run()处理请求。Basic Web 项目模板的入口脚本完整代码如下?php defined(YII_DEBUG) or define(YII_DEBUG, true); defined(YII_ENV) or define(YII_ENV, dev); // 注册 Composer 自动加载器 require __DIR__ . /../vendor/autoload.php; // 引入 Yii 类文件 require __DIR__ . /../vendor/yiisoft/yii2/Yii.php; // 加载应用配置 $config require __DIR__ . /../config/web.php; // 创建、配置并运行应用 (new yii\web\Application($config))-run();入口脚本还负责定义三个全局常量其默认行为已固化在框架约定中YII_DEBUG是否开启调试模式。开启后保留更多日志、抛出异常时显示详细调用栈默认falseYII_ENV应用运行环境默认prod生产环境可设为dev、test等详见 docs/guide/concept-configurations.mdYII_ENABLE_ERROR_HANDLER是否启用 Yii 提供的错误处理器默认true。常量定义必须放在入口脚本最开头以保证在引入其他 PHP 文件时即刻生效。应用对象全局协调中枢应用对象掌控 Yii 应用系统的整体结构与生命周期。每个 Yii 应用系统只包含一个应用对象它在入口脚本中被创建并通过表达式\Yii::$app全局访问。在源码中yii\base\Application是所有应用类的抽象基类直接继承自模块基类yii\base\Moduleframework/base/Application.php并提供两种具体形态Web 应用yii\web\Application主要处理 Web 请求framework/web/Application.php控制台应用yii\console\Application处理控制台命令请求。从源码可以看出应用对象构造时framework/base/Application.php会依次完成把自身注册为Yii::$app与模块实例、初始化state STATE_BEGIN、调用preInit()预处理、注册错误处理器。而preInit()framework/base/Application.php强制要求配置中必须包含id与basePath否则抛出InvalidConfigException这印证了文档中任何应用至少配置id与basePath两个属性的说法。必须配置的属性id唯一标识应用主要用于程序化区分官方建议仅使用字母数字字符以保证互操作性basePath应用根目录即包含models、views、controllers等受保护源码的目录。可配置为目录路径或路径别名目录必须真实存在最终会经realpath()规范化。设置basePath的同时会预定义别名appframework/base/Application.php后续许多派生路径如app/runtime都基于它构建。常用重要属性aliases以数组形式定义别名键为别名名值为路径等价于调用Yii::setAlias()bootstrap指定在应用启动阶段bootstrapping必须运行的组件列表。支持五种指定方式应用组件 ID、模块 ID、类名、配置数组、匿名函数。若组件类实现了yii\base\BootstrapInterface其bootstrap()方法也会被调用。Basic 模板在开发环境中的典型用法如下if (YII_ENV_DEV) { // 针对 dev 环境的配置调整 $config[bootstrap][] debug; $config[modules][debug] yii\debug\Module; $config[bootstrap][] gii; $config[modules][gii] yii\gii\Module; }注意bootstrap中放入过多组件会拖慢性能因为每次请求都会运行同一批组件务必克制使用。catchAll仅 Web 应用把全部用户请求交给指定控制器动作处理常用于维护模式。配置数组首元素为动作路由其余元素为绑定参数[ catchAll [ offline/notice, param1 value1, param2 value2, ], ]在源码 framework/web/Application.php 中可以看到handleRequest()首先检查catchAll为空则调用$request-resolve()解析路由否则直接使用catchAll[0]作为路由解析失败时抛出NotFoundHttpException即Page not found。components最重要的属性用于注册命名组件应用组件例如[ components [ cache [ class yii\caching\FileCache, ], user [ identityClass app\models\User, enableAutoLogin true, ], ], ]controllerMap把控制器 ID 映射到任意控制器类打破默认命名约定。键为控制器 ID值为类名或配置数组[ controllerMap [ account app\controllers\UserController, article [ class app\controllers\PostController, enableCsrfValidation false, ], ], ]controllerNamespace控制器类默认命名空间默认app\controllers。ID 为post时按约定对应app\controllers\PostControlleradmin/post对应app\controllers\admin\PostController。命名空间与类必须可自动加载否则访问时会出现Page Not Foundlanguage面向终端用户的内容语言默认en推荐使用 IETF 语言标签如en-US影响消息翻译、日期数字格式化等国际化行为sourceLanguage应用代码书写语言默认en-USmodules应用包含的模块键为模块 ID值为模块类名或配置数组name展示给用户的名称无需唯一version应用版本号默认1.0params全局可访问的参数数组用于集中管理常量配置例如thumbnail.size [128, 128]代码中通过\Yii::$app-params[thumbnail.size]读取timeZone设置 PHP 运行时默认时区本质是对date_default_timezone_set()的封装framework/base/Application.php。若 php.ini 与应用配置均未设置框架默认回退到UTC见 preInit。按约定取值的属性以下属性默认值来自通用约定仅在需要打破约定时才配置charset默认UTF-8defaultRoute未指定路由时使用的路由。Web 应用默认site即SiteController及其默认动作控制台应用默认help直接运行yii显示帮助信息layout/layoutPath默认布局main布局目录默认app/views/layoutsruntimePath临时文件日志、缓存目录默认app/runtime必须可写且应对终端用户隐藏可能含敏感信息同时预定义别名runtimeviewPath视图根目录默认app/viewsvendorPathComposer 管理的第三方库目录默认app/vendor同时预定义别名vendor、bower、npmframework/base/Application.phpextensions已安装扩展列表默认读取vendor/yiisoft/extensions.php由 Composer 自动生成维护一般无需手动配置enableCoreCommands仅控制台应用是否启用 Yii 内置核心命令默认true。核心应用组件yii\base\Application::coreComponents()framework/base/Application.php预置了一批带固定 ID 与默认配置的核心组件Web 应用在此基础上追加request、response、session、user、errorHandlerframework/web/Application.php。常用的包括组件 ID类职责assetManageryii\web\AssetManager资源包管理与发布dbyii\db\Connection数据库连接与查询errorHandleryii\web\ErrorHandlerPHP 错误与异常处理formatteryii\i18n\Formatter面向用户的格式化i18nyii\i18n\I18N消息翻译与格式化logyii\log\Dispatcher日志目标管理request/responseyii\web\Request/yii\web\Response请求采集与响应输出session/useryii\web\Session/yii\web\User会话与用户认证仅 WeburlManageryii\web\UrlManagerURL 解析与创建viewyii\web\View视图渲染完整说明见 docs/guide/structure-application-components.md。应用组件按需实例化的服务提供者应用本质上是服务定位器承载一组提供各种服务的应用组件。每个组件有唯一 ID通过\Yii::$app-componentID访问例如\Yii::$app-db获取数据库连接、\Yii::$app-cache获取主缓存。组件在首次被访问时才实例化之后复用同一实例——这意味着一大优势请求期间未被访问的组件不会被创建从而节省资源。注册方式支持类名、配置数组与匿名函数三种[ components [ cache yii\caching\ApcCache, // 类名 db [ // 配置数组 class yii\db\Connection, dsn mysql:hostlocalhost;dbnamedemo, username root, password , ], search function () { // 匿名函数 return new app\components\SolrService; }, ], ]提示应用组件如同全局变量注册过多会降低代码的可测试性与可维护性应谨慎使用。若想让某个组件在每次请求时都被实例化把它加入bootstrap列表即可docs/guide-fr/structure-application-components.md。模块自包含的迷你应用模块是由模型、视图、控制器及其支撑组件构成的自包含软件单元常被视为迷你应用。与应用的差异在于模块不能独立部署必须驻留在应用内部。一个典型模块的目录结构如下forum/ Module.php 模块类文件 controllers/ 控制器类文件 DefaultController.php 默认控制器类文件 models/ 模型类文件 views/ 控制器视图与布局文件 layouts/ 布局视图文件 default/ DefaultController 的视图文件 index.php index 视图文件模块类需继承yii\base\Module并放在模块根目录下docs/guide/structure-modules.md。在应用配置中通过modules属性挂载[ modules [ forum [ class app\modules\forum\Module, // ... 模块的其他配置 ... ], ], ]模块内控制器的路由必须以模块 ID 开头例如forum/post/index表示forum模块中post控制器的index动作只写模块 ID如forum时由模块的defaultRoute默认default决定使用哪个控制器。模块支持无限层级嵌套子模块必须声明在父模块的modules属性中。若某些模块需要每次请求都运行如debug模块将其 ID 加入应用的bootstrap属性即可。一个值得注意的实践模块的 URL 规则应在UrlManager::parseRequest()触发之前即引导阶段注册因为模块在路由解析后才被初始化放在模块init()中无效可用yii\web\GroupUrlRule包装模块规则。自 2.0.13 起模块支持服务定位器树遍历模块内优先使用$module-get(db)而非Yii::$app-get(db)便于模块级组件定制。过滤器动作执行前后的拦截代码过滤器是在控制器动作之前和/或之后运行的代码对象。例如访问控制过滤器在动作前检查用户权限内容压缩过滤器在动作后压缩响应内容。过滤器本质上是行为的一种特例在控制器中重写behaviors()方法声明public function behaviors() { return [ [ class yii\filters\HttpCache, only [index, view], lastModified function ($action, $params) { $q new \yii\db\Query(); return $q-from(user)-max(updated_at); }, ], ]; }默认过滤器作用于控制器全部动作可用only/except限定作用范围在模块或应用级声明过滤器时需使用路由而非动作 ID。多个过滤器按应用 → 模块 → 控制器的顺序执行前置过滤动作执行后按相反顺序执行后置过滤任一层前置过滤返回false会中断后续过滤与动作执行docs/guide/structure-filters.md。Yii 在yii\filters命名空间下本仓库 framework/filters/提供了常用过滤器AccessControl基于规则表的访问控制、yii\filters\auth下的认证方法过滤器HTTP Basic、OAuth2 等、ContentNegotiator响应格式与语言协商、HttpCache客户端 HTTP 缓存、PageCache整页服务端缓存、RateLimiter漏桶算法限流、VerbFilterHTTP 方法校验与Cors跨域资源共享。ContentNegotiator既可作过滤器也可作为引导组件在应用生命周期早期确定响应格式与语言。部件Widgets可复用的视图组件部件是可嵌入视图的对象可包含控制器逻辑并在不同视图间复用docs/guide-fr/structure-widgets.md。本仓库内置部件位于 framework/widgets/例如ActiveForm表单构建、Breadcrumbs面包屑导航、LinkPager分页、Menu菜单、DetailView/ListView数据展示等。部件通常通过? \yii\widgets\ActiveForm::begin() ?这类形式在视图中调用其渲染逻辑封装在类内部从而避免在多个视图间复制粘贴相同的展示代码。应用生命周期与事件请求如何在 Yii 中流转从源码 framework/base/Application.php 的run()方法可以看到一次请求处理的完整流程入口脚本把应用配置加载为数组创建应用实例preInit()配置高优先级属性如basePath→ 注册错误处理器 → 配置应用属性 →init()内部调用bootstrap()运行引导组件调用run()触发EVENT_BEFORE_REQUEST处理请求把请求解析为路由与参数按路由创建模块、控制器与动作对象并执行动作触发EVENT_AFTER_REQUEST发送响应给终端用户入口脚本接收退出状态码并结束处理。框架为这一生命周期定义了六个状态常量STATE_BEGIN到STATE_END见 framework/base/Application.phprun()依次推进状态机并在关键节点触发事件。开发者可在应用配置中用on eventName语法挂接事件处理器也可以在应用实例创建后通过\Yii::$app-on(...)挂接\Yii::$app-on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) { // ... });四个核心事件常量定义见 framework/base/Application.phpEVENT_BEFORE_REQUESTbeforeRequest应用处理请求之前触发此时应用已配置并初始化完毕适合动态调整language等属性以拦截请求处理EVENT_AFTER_REQUESTafterRequest应用完成请求处理但尚未发送响应时触发可做请求后处理或定制响应EVENT_BEFORE_ACTIONbeforeAction每个控制器动作运行之前触发事件参数为yii\base\ActionEvent将isValid置为false可中止动作执行。触发顺序为应用 → 模块 → 控制器任何一层中止后后续事件不再触发EVENT_AFTER_ACTIONafterAction每个动作运行之后触发可通过$event-result读取或修改动作结果触发顺序与beforeAction相反控制器 → 模块 → 应用。小结一次请求在 Yii 2 中的完整协作把以上实体串起来一次典型请求的路径是入口脚本定义常量、加载自动加载器与配置 → 创建应用对象并完成引导实例化bootstrap组件、注册app等别名、启用错误处理器→ 触发beforeRequest→ 经urlManager/request组件解析出路由 → 按路由实例化模块若有与控制器→ 执行过滤器链 → 运行控制器动作动作调用模型取数并渲染视图含部件→ 触发afterRequest→response 组件发送响应。所有环节都由应用对象这个全局协调中枢统一调度这正是 Yii 2快速、安全、专业的架构基础。若要继续深入推荐按以下顺序阅读docs/guide/structure-entry-scripts.md入口脚本→ docs/guide/structure-applications.md应用对象与属性→ docs/guide/structure-application-components.md应用组件→ docs/guide/structure-modules.md模块→ docs/guide/structure-filters.md过滤器→ docs/guide/structure-widgets.md部件底层实现可对照 framework/base/Application.php 与 framework/web/Application.php 逐行研读。【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址: https://gitcode.com/gh_mirrors/yi/yii2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表