用发展的眼光追技术
- 2020 年 3 月 4 日
- 筆記
本文从 PHP 语言的 YII2 框架说起,简单谈一些技术的演变和发展脉络。
YII2 这个框架是 PHP 语言生态下的一款 Web 应用框架。有过 PHP 开发经验的开发者都不会陌生,或多多少都听说过,熟悉,至少接触过。
回到始点 PHP 官方定位
“PHP is a popular general-purpose scripting language that is especially suited to web development
PHP 官方的定义是基于轻型的 Web 应用,最典型的应用是 MVC。
YII2 初来乍到
在 2013 年,2014 年 YII2 刚刚发布的年份,YII2 被大家追逐的原因大概是面向对象数据,包加载的扩展属性,自带 Gii 自动化生成工具,清爽的 View 界面和工具包,API 序列化模型这几个。
我们返回头再整体回顾下 YII2 框架,你会发现在 YII2 官方的默认模版中,View 层还是占有很大的比重。
最近几年,前端技术演进迅猛,Web 开发都在使用前后端分离,分离大部分内容是数据的业务控制和界面的显示。
View 逐渐被前端框架,如 Vue 取代,YII2 也暴露出来它的劣势。
在 YII2 社区中安装 YII2 版本的讨论中,经常有一个 View asset 扩展安装的难题,核心就是前端页面元素与后端服务的耦合的问题,以及版本依赖的冲突。
参考文档 composer 管理 js css 等依赖文件[1]
相关命令
composer global require "fxp/composer-asset-plugin:*"
使用 YII2 构建 API
简单概括
“现在我们使用 YII2,就是在使用它构建 API 的能力。
看一看 YII2 官方文档[2] 列出来的 YII2 关键组成,基本上很多已经退出常见的使用场景。
找到了一个介绍 YII2 微框架,为服务接口而设计的 使用 Yii 作为微框架[3],

YII2微框架.png
YII2 去掉预置的模版,去掉 View 功能,剩下的核心也就是这个了。
PHP 可扩展性
关于 YII2 这款框架,有两个概念值得说明一下
“组件和模块
.YII2 的扩展性主要体现在组件(comments)的设计上
'components' => [ 'request' => [ 'cookieValidationKey' => 'dmpisthebest', 'parsers' => [ 'application/json' => 'yiiwebJsonParser', ] ], 'cache' => [ 'class' => 'yiicachingFileCache', ], 'errorHandler' => [ 'errorAction' => 'site/error', ], 'user' => [ 'identityClass' => '', 'enableAutoLogin' => false, ], ]
YII2 种常见的组件 包括 user,seesion redis mongodb,log 等
感觉组件更适合做 infrastructure 的构建,而 module 则适合做业务的分离解耦
配置 YII2 带来的耦合性
我们简单分析 YII2 的主配置文件,很容易了解到 YII2 是通过模块(module),组件(components)来启动和项目功能的。 必须的模块和组件自动加载,其它组件和模块可以按需加载。虽然组件和模块为扩展性提供了便利,引用它们使用的配置,会造成入口 index.php 自动加载的 main.php 文件复杂臃肿,难以维护和阅读。
解决耦合可以从以下几个方面的尝试
“根据环境分拆配置文件
根据环境,加载不同的文件,可以 通过域名,变量等方式确定环境,进而分离配置文件。

YII2 入口文件及环境配置.png
根据组件分拆配置文件,实现组件和模块的按需加载。
复制优于依赖
“Alittle copyiing is better than a litter dependcy
有时候不一定要优先追求共享代码,应该有一部分复制冗余。公用代表着多处使用,和依赖耦合。复制虽然增加了复制的成本,却独立自由。
怎么理解这句话?
我们以 YII2 工程为例,官方推荐的 Advanced 模版中有一个公共工程 common
那我们是不是应该把项目中可以共用的数据层都放到 common 里?

YII2-模块.png
如上图,passport 和 admin 两个模块,如果都涉及同一张 User 表,依据复制优于依赖的原则,没有必要公用一个 User 类,可以单独存放为两个 User 类,用命名空间做隔离。更何况因为模块不一样,即使同一个数据表对象,相关的数据操作也会不一样。
/** * @inheritdoc */ public function init() { if (!$this->accountId) throw new InvalidConfigException('accountId required.'); if (!$this->secretKey) throw new InvalidConfigException('secretKey required.'); }
PHP 如何做单元测试
这个可以作为一个面试题与候选者沟通,但是我下边这段话,不适合作为答案。
当然会有一些单元测试组件,比如 YII2 下的 Codeception,PHPUnit 进行数据 Mock。可实际情况呢,程序直接用 var_dump,REST 接口测试程序即可调试,达到单元测试的目的。
这就是 最简单的理论和实际的出入,理论结合实践的实话。
总结
看看程序语言的发展脉络,以及前后端发展的变革,可以总结出两个词:演变和趋势。在应用程序开发中,前端这个职位是从后端细化和演变而来的,前后端分离和独立就是技术的趋势。 首先技术层面的技术选择和生态,其次职位的前端工程师和后端工程师区分,在者部门的设立原则前端部门和后端部门。

改变思路.png
演变代表着万变不离其宗,趋势代表着先进的技术就是先进的生产力。 本来想写一篇关于重新定位 YII2 的文章,最后发现本文的重点其实不是 YII2 ,而是这种变化趋势对于相关决策的度量参考。 唯有改变思路,才有出路,用发展的眼光去追技术。
参考资料
[1]
composer 管理 js css 等依赖文件: https://www.zhaokeli.com/article/8522.html
[2]
YII2 官方文档: https://www.yiichina.com/doc/guide/2.0
[3]
使用 Yii 作为微框架: https://www.yiichina.com/doc/guide/2.0/tutorial-yii-as-micro-framework