Yii2 框架是一个非常庞大但是并不臃肿的 php 框架。

使用 Yii2 框架,可以极大的提升开发效率。

秉持着要知其然也要知其所以然的思想,花了一周的时间,看了 linuor 的 《深入理解Yii2.0》

根据我的理解梳理了一下 Yii2 框架的整体结构。

此后简称框架。

1. Yii 框架基础

此框架的三个基础概念:

  • 属性
  • 事件
  • 行为

毕竟三生万物。

1.1 属性

一看到这个词可能很迷惑,那么什么是属性呢。

比如说,你现在正在玩一款角色扮演的游戏,角色双手分别有一把 十方大剑 ,一个 十方盾牌

那么从面向对象的角度而言,你的角色类需要有 左手武器右手武器 两个成员变量。

并且角色类可以从 左手武器右手武器 中获得 力量属性。

这么一说属性这一概念,就很容易理解了。

1.2 事件

还是以角色扮演游戏为例(这里要对不起不玩游戏的朋友了,原谅我匮乏的想象力,或者你有好的比喻也可以跟我说),游戏里面都有任务系统,而任务会分为主线任务和支线任务,在做主线任务是通常会触发一系列的支线任务。这些支线任务的触发就可以认为是一系列的事件。

1.3 行为

框架的行为也可以使用角色扮演游戏来举例,你在 无尽荒原 捡到了一本魔法书,学会了禁咒魔法,召唤神龙

于是你把程序一改,给你的类加一个召唤魔法的方法,这是不可能的。我们必须让你的类拥有一个动态添加方法的功能,于是所有拿到魔法书的人或者限定职业的人,都能学会这个禁咒,这就是 行为 的作用,动态给类增加方法。

以上,有了这三个 框架 实现的武器,我们才能更快速和灵活的搭建上层的程序。

2. 设计模式

2.1 依赖注入

框架采用了现在世面上面最常见的一种模式, MVC 模式,具体细节不再阐述,现在网上关于 MVC 的介绍可以说是烂大街了。

MVC 只是一种大框架上的设计模式,其核心思想是分层,最终目的是解耦。框架在 MVC 的基础上,应用了很多经典的设计模式以及后来发展的设计模式。

其中最重要的就是:

  • 依赖注入
  • 服务定位器。

那么什么是依赖注入呢

先来一段没有依赖注入的代码:

  1. <?php
  2. // 这段代码将 db1 中的t1表的数据备份到 db2 库的 t2 中。
  3. // 所使用的变量都在逻辑过程中申请。
  4. class Archive {
  5. public function doArchive() {
  6. $dataDB = new DB1();
  7. $data = $dataDB->query("select * from t1");
  8. $backDB = new DB2();
  9. foreach ($data as $key => $value) {
  10. $backDB->query("insert into t2 values ". implode(',', $value));
  11. }
  12. die("备份完成");
  13. }
  14. }

那么如果再来一个需求,让你把 db3 的数据备份到 db4 中,逻辑相同,那么你该怎么办呢?

有道友就说了,那还不简单, copy & paste,搞定。

于是,你多了一个方法或者一个类。

一直到你的方法和类增加到 10 个以上时,你都不会有什么感觉。

直到产品说现在需求变了,让你把所有的备份库都改成 db3,那么,你就要把手头的工作都停下来,然后将代码中的备份库全改成 db3。

而且,如果你使用的是静态语言,那么,你就要把代码再重新编译一遍。关于静态语言的编译时长:为什么c编译需要这么长时间

那么就有了下面这种:

  1. class ArchiveNew {
  2. private $originDb;
  3. private $backDb;
  4. public function doArchive() {
  5. $dataDB = new $this->originDb();
  6. $data = $dataDB->query("select * from t1");
  7. $backDB = new $this->backDb();
  8. foreach ($data as $key => $value) {
  9. $backDB->query("insert into t2 values ". implode(',', $value));
  10. }
  11. die("备份完成");
  12. }
  13. /**
  14. * @param mixed $originDb
  15. */
  16. public function setOriginDb($originDb)
  17. {
  18. $this->originDb = $originDb;
  19. }
  20. /**
  21. * @param mixed $backDb
  22. */
  23. public function setBackDb($backDb)
  24. {
  25. $this->backDb = $backDb;
  26. }
  27. }

这个方法,把所有的需要用到的数据库都放到了外面来进行管理,那么我们称这几个数据库为依赖,称在外部设置数据库的行为为依赖注入。

这只是一种很原始的使用方式,你可以继续延伸,将外部依赖放到统一的地方去管理,那么就有了注入容器(di Container)

2.2 服务定位器

服务定位器像是一个注册中心,向服务定位器中注册一个 a 服务,可以使用 a 这个名字从服务定位器中取出这个服务。

  1. $locator = new ServiceLocator;
  2. $locator->set('a');
  3. $locator->get('a');

服务定位器是基于依赖注入的,在获取服务时,其实会在容器中先注册一个服务。

3. 请求与响应

这一节其实主要讲的就是请求。

请求的内容会比较多,还涉及到网络协议等知识,这里不再展开。

列举一下重要的几点:

  1. 路由美化 (将原始的路由修改成比较美观的地址,见导图 请求部分)
  2. url 解析(将美化过的路由解析成原始请求)
  3. 请求管理 (包括请求头部,请求体,解析器等等)

4. 数据库

虽然这张图有些搞笑,但是无疑说明了 数据库(MySQL)对于 PHP 的重要性。

4.1 类型转换

框架为了兼容各种数据库,对数据类型做了多层封装,并且做了一系列的转换规则:

4.2 事务

框架支持事务嵌套,但是嵌套的事务必须成对出现(注意!!!)。

看到事务这一节的时候,正巧同事出了一个 bug ,在脚本的循环中,出错之后没有 commit 或者 rollback ,导致,接下来的生成的事务都成了这个事务的子事务。而框架的嵌套事务,实际上是使用代码模拟的,如果父事务没有提交,那么子事务永远不会提交。

4.3 事件

  1. const EVENT_INIT = 'init'; // 初始化对象时触发
  2. const EVENT_AFTER_FIND = 'afterFind'; // 执行查询结束时触发
  3. const EVENT_BEFORE_INSERT = 'beforeInsert'; // 插入结束时触发
  4. const EVENT_AFTER_INSERT = 'afterInsert'; // 插入之前触发
  5. const EVENT_BEFORE_UPDATE = 'beforeUpdate'; // 更新记录前触发
  6. const EVENT_AFTER_UPDATE = 'afterUpdate'; // 更新记录后触发
  7. const EVENT_BEFORE_DELETE = 'beforeDelete'; // 删除记录前触发
  8. const EVENT_AFTER_DELETE = 'afterDelete'; // 删除记录后触发

这些事件和其他事件没有什么分别,都是在特定的时候会执行,就不一一阐述了。

4.4 乐观锁和悲观锁

框架自带了乐观锁的实现,如果有类似需求,可以在重载 yii\db\ActiveRecord::optimisticLock() 方法,返回数据库中的版本号字段即可。在更新与删除时,框架会做相应的操作,来保证,更新的数据是自己拿到的数据,而不是被别人给修改过了。

因为悲观锁不适用于 web 应用,所以框架并没有实现悲观锁。

5. 总结

Yii2 框架的整体架构要比 Yii1 版本提升了一个逼格。并且得益于 namespace 特性,框架的目录结构清晰了很多。

对于不想了解框架底层实现的程序员,可以仅仅了解基本使用,就可以上手写业务代码,而不会影响你的开发效率。

只有当你遇见一个很蛋疼的框架内部报错或者 bug 的时候,你才会想到,我去,这怎么这么蛋疼,怎么框架还会有 bug ,但是很多时候是环境、配置或者特定的代码导致的。如果不了解框架的内部逻辑,这个报错或者 bug 会耽误你很长时间。

Yii2 框架整体结构的更多相关文章

  1. Yii2框架实现计数器功能

    思路: 因为yii2框架没有像tp框架那样的setinc这样的累加函数,所以只能在每次累加之前查出当前的这个字段的值,然后写算法累加入库 例如:

  2. 关于yii2框架活动记录activeRecord添加默认字段的问题

    平时使用sql的时候可以如下添加默认字段flag: "select a.*,0 as flag from user_info a", 对于yii2框架则需要这样: $query = ...

  3. Yii2框架RESTful API教程(二) - 格式化响应,授权认证和速率限制

    之前写过一篇Yii2框架RESTful API教程(一) - 快速入门,今天接着来探究一下Yii2 RESTful的格式化响应,授权认证和速率限制三个部分 一.目录结构 先列出需要改动的文件.目录如下 ...

  4. Yii2框架RESTful API教程(一) - 快速入门

    前不久做一个项目,是用Yii2框架写一套RESTful风格的API,就去查了下<Yii 2.0 权威指南 >,发现上面写得比较简略.所以就在这里写一篇教程贴,希望帮助刚接触Yii2框架RE ...

  5. [PHP]Yii2框架的坑

    [PHP]Yii2框架的坑.md-/Users/zjh/Documents/我的文章/[PHP]Yii2框架的坑 html{font-family: sans-serif;-ms-text-size- ...

  6. Yii2框架与MongoDB拓展、Redis拓展的安装流程

    @author 周煦辰 2016-03-21 这段时间新上了一个项目,使用的是Yii2框架.这里记录一下Yii2框架.Yii2-Mongo拓展.Yii2-Redis拓展等的安装流程.因为使用的系统是W ...

  7. yii2框架安装

    注意:先把php.ini里面的php_openssl.dll扩展打开 1.下载yii2框架的文件包yii-advanced-app-2.0.7 2.打开路径为advanced下面的init.bat   ...

  8. nginx完美支持yii2框架

    nginx完美支持yii2框架 server {listen 80;server_name www.peita.net peita.net;# default_server;access_log /d ...

  9. YII2框架动态创建表模型

    YII2框架动态创建表模型 在YII2中,每个表对应一个model类 在开发过程中,我们在填写一个大型表单的时候,表单里有N个select下拉列表,每个下拉select来自于不同的表: 如果要在程序里 ...

随机推荐

  1. 【2018寒假集训 Day2】【动态规划】钱币兑换(exchange)(自己翻译的2333)

    钱币兑换(exchange) 问题描述: Dave偶然获得了未来几天的美元(dollars)与马克(marks)之间的兑换率.例如Dave开始有100marks,请编写个程序帮助Dave找出最好的买卖 ...

  2. 【搞定面试官】谈谈你对JDK中Executor的理解?

    ## 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1.5 提供了自己的多线程框架 ...

  3. [ASP.NET Core 3框架揭秘] 配置[1]:读取配置数据[上篇]

    提到"配置"二字,我想绝大部分.NET开发人员脑海中会立即浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化 ...

  4. Git实战指南----跟着haibiscuit学Git(第一篇)

    笔名:  haibiscuit 博客园: https://www.cnblogs.com/haibiscuit/ Git地址: https://github.com/haibiscuit?tab=re ...

  5. 20190908write from memory

    JavaScript_Chapter1 文档名:first.js document.write("你好,今天天气凉爽"); 文档名:js_demo1.js /*1.定义js的变量语 ...

  6. 【JavaEE】之SSM-Maven依赖积累

    本帖中收集JavaEE SSM框架使用的Maven版本库中的依赖.本帖持续更新...... 日志输出: <dependency> <groupId>commons-loggin ...

  7. 为什么 main 方法是 public static void ?

    Main方法是我们学习Java编程语言时知道的第一个方法,你是否曾经想过为什么main方法是public.static.void的.当然,很多人首先学的是C和C++,但是在Java中main方法与前者 ...

  8. AutoCad 二次开发 jig操作之标注跟随线移动

    AutoCad 二次开发 jig操作之标注跟随线移动 在autocad当中,我认为的jig操作的意思就是即时绘图的意思,它能够实时的显示出当前的操作,以便我们直观的感受到当前的绘图操作是什么样子会有什 ...

  9. num += num 与 num = num+ num

    a = 100def test(num): num += num print(num) test(a)print(a) 200100 这里 num += num 与 num = num+ num 不能 ...

  10. react-native技术调研:react-native是什么?

    如有疏漏错误,还望指正.转载不忘加上>>原链接<<哦~ react-native是什么? react-native原理 从字面意思上来看,react-native由单词reac ...