“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
2016年9月11日drupal深圳社区组织了一次聚会,做了个D8入门分享,这里整理了一下,D8正式版是2015年11月19日发布,我也是从这个时候开始学习研究drupal ,过去差不多一年时间了,入门过程的很多东西记忆犹新,可能将来这些感受会慢慢的忘记,所以在这一次聚会征集的时候我把它记录分享出来,一来可以帮助处于drupal大门之外正在观望的朋友以及决定深入研究正在入门的朋友,二来自己也做一个笔记,drupal很庞大,我的学习还处于不断进行中,有些地方可能讲的不准确,还请已经走过来的朋友指正。
首先我做一个简短的自我知识背景介绍,这样可以和大家产生一个共鸣,理解到我学习drupal过程中出现的感受,从事php有8年时间,经历学习过c、c++、java现在专注于php,在web领域深入理解过的cms有phpcms,帝国cms,特别是帝国cms,为它开发了一些插件。深入理解使用的框架有CodeIgniter简称ci,用ci开发过微信公众号管理系统等等,这些背景知识会在学习drupal的过程中产生对比和共振。以上就是大致的背景知识,我没有了解过drupal8以前的版本,第一次接触drupal就是从这个面向对象的d8开始的,下面分几个部分来讲。
一:为什么选择drupal
希望这部分对正在判断要不要深入研究drupal的朋友和正在坚持学习D8的朋友们有用。准备花大量时间去学习一个cms,选择一定是非常慎重的,我认为有两件东西非常重要:精力和坚持,它直接决定一个人整个生命周期能产出的价值,这是我选择php又进一步选择其中的drupal最底层的一个原因,人的精力必须要得到尊重和高效利用,选择php就是因为它的设计哲学是人的时间比机器的时间更加宝贵,我想这当然是对我们有限生命的人类来说是应该的,相比其他语言它更加智能,为我们做的更多,省更多的时间,直接对一个实例化的对象赋值一个不存在的属性是不是很自由方便呢?不用考虑数据类型,但想考虑的时候又能考虑到是不是很自由方便呢?这些都是c和java等不具备的,至于拿运行速度说事的人我想说可能得直接去用汇编或者机器语言了,这里我不是说哪个开发语言不好,他们有各自的历史角色和定位,存在必有道理,我认同php的设计哲学,所以我选择了php,说了那么多php其实我是想说选择drupal的原因和它根本上是一模一样的,这里说说我的经历,进入web领域以来建站开发是从dz开始的,但他只是个论坛,我想要的很多东西没有,所以开始了cms之路,使用大众化的cms极大的满足了很多需求,相比自己去开发一个专用系统节省了不少的时间,那时候我主要选择帝国cms做工具,和帝国同行是从6.0版本开始的,对于当时没有太多想法的我来说那是很满足的,可问题慢慢的出现,在2009年的时候我接触过劳务派遣,就是把许多的临时工在不同的工厂之间进行调派,大量的工作需要电话和现场处理,于是想到建立一个网站系统去处理工厂与工人的结算问题、互相评价问题、自动调派问题等等,这个时候再看帝国cms就已经严重的不能满足需求了,摆在面前有两条路,首先就是大规模的二次开发,这个时候发现如果这么做,帝国升级的时候会产生大量的工作要做,而且由于帝国历史原因程序里面的命名等开发规范不是太规范,这样对协同开发产生不利影响,所以放弃了。只能进行第二条路:完全的自己开发,如果从底层php级别开始的话无疑浪费大量时间,团队运作成本很高,这个时候开始把希望寄托于php框架,经过对比后选择了ci框架,用了框架之后感觉是很省事而且自由,也能容易的找到协同开发的人员,可是事情还是感觉远远的不完美,有大量的组件在php大社区里面有功能类似的,但各自都在重复的发明轮子,如果已经发明的轮子不够好重新发明当然是好的,但如果已经很好了,还有必要吗,而且自己真的有精力把各个细分领域的轮子都给造一遍吗?当然是否定的。这个时候多么希望php大社区的尖端人才统一的规范化自己在行的东西,让使用者可以把它们像搭积木一样用到自己的系统中去,这个时候我开始寻求新的解决之道,开始在全世界搜索,最开始找到joomla,但由于那段时间正在开发微信公众号管理系统暂时没有去理睬这个事情,等2015年回过头来的时候意外的发现了drupal,结果一番搜索对比之后感觉joomla和drupal的对比如同windows和linux一样,一直感觉linux才是极客的玩具(在这里我没有真的去看过joomla的实现,仅仅来源于一些资料,白宫使用drupal更加印证这一点,如果有谁研究过这两cms很希望能发一些对比出来),简单接触之后发现drupal很多概念比较抽象而且学习难度更高,正合我意,往往越抽象的东西越接近事物的本质,会越强大越灵活,就像数学一样,这个说明drupal应该是很强大的,另外一方面学习曲线高,强大的东西这是必然的,这是最初的心路,后来了解到它在世界范围内广泛使用,有活跃的社区,这点很重要,有生态才有标准才有协作,才能不重复发明轮子,所以决定深入的学习drupal,选择drupal还有一个原因:现在很多网站还是给人类看的,对机器目前也只考虑到了残疾人的残障辅助设备和搜索引擎,而当今正在进入万物互联的世界,以后越来越多的会给机器看,drupal的格式协商机制就很好的满足了这个,目前国内大众的cms还没有看到谁考虑到了物联网对网站的要求,现在的网站和以前已经不大一样了正在向网络应用系统转变,不单纯的指一系列的html网页集合,而drupal有强有力的社区支持有生态圈,这一点会做的很好,社区开源软件的先天优势让它不落伍,值得把自己的时间花在上面。通过这些应该可以看出选择drupal的理由。
二:需要具备的知识准备/工具环境准备
D8很先进,对运行环境要求相对于目前国内开源系统来说很前卫,运行环境要求是:php5.59 浏览器IE9+,自身也采用前沿的技术组件等等,D8就是一群极客的化身,我感觉国内的软件开发者首要想的是去适应环境,而国外软件开发者更多的是考虑系统本身怎么极致,会主动改造环境, 这是两种哲学状态。
那么要开始D8需要提前准备哪些背景知识?怎么建立工作环境:
背景知识:
1:面向对象开发模式,让自己从过程式开发方式中转变过来
2:了解php5.x各版本的差异,比如三元运算符的简化形式?:、数组的简化形式[]、运算结合性质等等,这些在php的官方网站有专门的升级页面来介绍这些,在官网手册附录部分http://php.net/manual/zh/appendices.php,drupal里面使用了很多新特性,如果不理解,在看代码的时候会被老是打断去查询用法,每个开发者建议自备一个文档去记录常用的快速备查,比如什么特性是在哪个版本开始的,自己对某技术难点的理解,在这里建议大家查询php语言本身的东西首先到php官方网站,如果查询不能满足再到其他地方搜索,官网目前很完善,信息也比较及时,我发现其他一些地方的信息是不完备甚至是错误的。
3:熟悉PHP标准库 (SPL),比如drupal搜索主题、模块等扩展时就用到了spl里面的目录迭代器
4:了解psr规范,很简单,也很简短,官方地址是http://www.php-fig.org/psr/
5:先学习composer,它是drupal的基石之一,是一个独立的软件,进行依赖管理,通过php的类文件自动加载机制产生类加载器,这个是drupal8程序启动的第一件事情
6:学习symfony,地址是http://symfony.com/,其实开始不用精细的学习,并不是不了解他就不能理解drupal,但drupal是建立在它之上的,开始少许理解会对drupal的学习加速,对symfony深入学习可以在drupal学习的同时进行,学习drupal前先看一看symfony各组件的文档,目前drupal8.1.9使用是的symfony2.8版本,symfony现在已经是symfony3.1版本了,很多弃用的东西可以不用理会,比如依赖注入组件的容器范围Scope,这些在程序里面有弃用提示
7:学习Twig,在drupal外独立使用一下它,开始只需要知道使用方法即可,不需要去看程序代码,它用到了编译原理的知识,没有这方面知识可能难于理解,关于编译原理这一块知识量很大,是专门的一个领域,以后可以慢慢研究。
8:了解一下软件设计模式方面的知识,drupal里面到处是设计模式,但不建议去买大部头的书来学,百度一下,看一些小小的程序案列就能明白,太多的书把设计模式讲复杂了,搞的人云里雾里,反而打扰积极性,很多事情本不难,都是沟通惹的祸。
工具环境准备:
1:首先解决语言不通的问题,建议大家安装“有道词典”,它可以对浏览器划词翻译,强迫自己多到英文的drupal官网去看,开始会不习惯,但慢慢的就习惯使用英语,越来越不需要翻译软件的辅助
2:找到合手的开发工具,我比较喜欢的是phpdesigner、phpstorm编辑软件,和phpstudy环境软件。
社区里面有工具环境这方面的专门页面,大家可以看一看
3:社区概况,资料查询、规范
我的学习是这样一个过程:先看一遍使用文档,再看一遍api文档、最后去读代码。一定不要一开始就试图通过读代码来了解drupal,因为drupal太庞大,如果没有一些概念的认识和架构的全局印象图,会让人承受不了,读代码最讨厌的就是不能和开发者思维同步。
在看使用文档的时候,推荐看一本书《Beginning-Drupal8》,Todd Tomlinson写的,drupal中国站drupalchina.cn的站长龙马已经组织翻译了这本书,我也参加了这本书的翻译,该书面向新手,比较浅显,但能对drupal的使用看个大概,目前20160910官网(如无特别指出均是指英文的官网)正在进行文档的重组,不知道重组后效果怎么样,所以对以后的文档使用现在没法分享,在这之前我看完了所有的文档,印象是是这样的:drupal各个版本间文档有交叉混杂,没有彻底分开,文档均来源于社区,由很多个人写成,详细程度不一,排序也有点问题,甚至有些部分的排序是按照首字母来进行的,没有照顾到学习心理问题,和主次问题,所以大家不要试图去按次序阅读所有的文档,根据自己的实际情况、学习曲线和关注点跳跃式的去查询阅读。虽然不完善但整个社区的文档还是不错的,能解决大部分疑惑,没有详细资料的情况下代码注释会成为最后选择,实在找不到可以先记录下来,后面的读代码阶段一定能理解,或者是咨询他人,了解清楚使用和一些概念后就进入第二阶段,读api文档,api文档是自动从程序代码的注释中提取的,所以是能跟上新版本的节奏,这些文档不长,短于第一阶段的开发文档,所以能快速阅读建立程序运行印象,如果有不清楚的可以到社区发问,或是记录下来在读代码阶段一定会明白,比如很多新人就不明白模块的文件夹名、info文件名、及里面的name值有什么区别,但看完扩展发现类后就好会豁然开朗,这给读代码带来乐趣,一时不明白以后终将明白。
关于规范,这是一个很重要的话题,官网有详细的文档,里面清晰的描述了文件命名、变量函数类命名、组织、提问怎么提等等一系列规范,在进行开发之前一定是要了解的,这样才能和社区协作,将来为社区提供模块才能被接受,详细的规范请大家去官网看,不守规范会被鄙视,无法使社区力量强大
关于查询,官网的搜索功能都比较强大,但还得依仗大家的英语水平,才能提出准确的关键字,这也是为什么我推荐大家看英文的官网,即使用翻译软件去看,因为那里的资料最丰富,自己也能慢慢接受英语的使用。
这里额外说一下,drupal官网分享的一些链接在国内打不开,原因大家都知道,甚至有时候drupal官网本身都打不开,这个时候大家可以使用vpn网络,搜索一下有很多,找一个注册账号,每个月二三十块钱解决,谷歌、Facebook等等就在眼前了
4:drupal运作框架,启动逻辑
学习drupal先应该对它的整体架构及执行流程有宏观上的了解,知道这个后,在后面的学习中就明确知道自己处于逻辑大厦的哪个地方,为什么程序要这样设计等等,现在来说一说这块内容:
drupal8是建立在symfony开源框架之上的,drupal8.1.9使用的是symfony2.8,symfony是一款非常流行的框架,强调模块化,由许多组件构成,组件可复用,相互独立解耦,在symfony的官网首页说symfony就是一个可复用的php组件集,我们可以将任何一个组件独立的运用到自己的应用程序中来,在symfony官网里面每一个组件都有独立的文档,这些组件有些被drupal8直接使用,有些根据D8自己的特性进行了修改,有些则没有使用,可以说学习Drupal8你将也会顺带着学习完一款如此优秀的框架(symfony的作者Fabien Potencier法宾是个狂人,从94年就开始专注于web,模板引擎twig就是出自他手,对RFC文档十分了解)。现在来看一下symfony的执行流程【收到请求》查找处理器》解析参数》执行处理器》产生响应】:
这个流程是drupal的主流程,drupal8是在此基础上细化的,symfony的执行流程是由它的http-kernel组件定义,symfony认为任何一个网站系统其实就是一个把请求转换为响应的系统,所以以此为标准来设计了这个流程。drupal8的流程是建立在symfony流程之上进行细化的:
这个流程图请下载pdf文档放大看,地址:
好了现在了解了drupal8的架构和执行流程,我们来看一看实际的程序代码是怎么开始的,她是怎么执行的:
也可以说Drupal8是遵循mvc模式的,他有唯一的一个统一的入口,所有的请求被服务器通过.htaccess配置转接到index.php,一般需要一个漂亮的url的话需要开启服务器的重写模块,如果没有则需要用查询串的方式明确定义到这个文件上来,不管怎么样整个系统都是从这个文件开始执行的,下面谈一下开始执行后它所做的事情:
1:调用composer自动生成的类加载器,它通过php的自动加载机制凭借名字空间去包含include类文件,不必在程序代码里面手动包含,里面已经配置好了系统基本的加载路径等对应关系
2:启动drupal处理核心,将请求对象传给他,让他将其转换为响应页面,然后发送给浏览器
3:完成请求,发送出页面后,再做一些收尾的工作
简单讲就这么几步,核心工作集中在核心上,那么核心如何工作?它其实做了两大块事情,先准备服务容器,也叫依赖注入容器,然后让容器里面的服务在http-kernel服务的流程控制下运作起来,相互作用产生响应,我们看一下drupal容器准备完成之前都做了什么,是怎么完成容器对象的,容器可以说是D8学习的重中之重,他是系统的中枢,这就是DrupalKernel.php在完成的事情,从名字可以看出它的drupal核心地位,可以打开core/lib/Drupal/Core/DrupalKernel.php看一看:
1:预置启动环境,它加载基本的D8函数库,并设置php有一个统一的运行环境,比如session配置、编码检查、错误报告、设置异常处理函数等等,都是在这个阶段完成的
2:初始化设置,根据请求判断是哪一个站点,(这里说一下drupal8的多站点功能,它其实就是多个站点复用同一套程序代码而已,而且仅此而已,从逻辑上讲是独立的网站,他们有自己独立的数据库,站点与站点并无关联,这个和站群是有区别的),然后加载这个站点的配置文件,配置文件是require进系统里面的,这可以看出可以在配置文件settings.php中进行程序编写,甚至退出系统。然后判断域名是否是被允许的域名
3:判断系统是否已经安装,如果系统尚未安装的话转向安装程序。
4:如果已经安装则启动核心,在这个阶段会先建立一个基本的容器,称之为引导容器,它为后续工作提供数据库连接和缓存支持,有这样的准备之后才开始真正的初始化服务容器。
程序进入初始化服务容器阶段,这里有个注意事项:在drupal核心的lib下面(core\lib\Drupal)有两个文件夹:组件Component、核心Core,很多初学者不知道为什么要把库分到这两个类别里面,他们的区别是核心里面的程序是和drupal本身紧密联系的,没有考虑给其他项目复用,而组件里面的东西是由drupal社区开发但可以离开drupal独立复用的,或者在symfony框架范围内复用,这样的安排适合管理代码,协同开发。
容器初始化:
1:查找缓存中是否有有效的容器定义数据,如果有,直接使用它初始化容器
2:如果没有缓存,去构建容器定义数据,编译一个容器
3:初始化服务提供器来准备容器定义数据,加载核心和扩展的services.yml文件,同时加载服务提供器,扩展是通过扩展发现类来完成的,他使用spl的目录迭代器和过滤迭代器去查找有效的info.yml文件
4:编译容器,编译容器就是在容器形成前有一次机会让服务间相互作用和关联(有些关联是在定义服务参数时无法考虑到的)比如通过服务标签将访问检查器注册到访问管理器里面,这个属于依赖注入组件的范畴,称为编译Pass
5:容器形成后附加一些外部合成对象进去,并把容器赋值给全局的Drupal类静态储存引用,以后就可以使用\Drupal:: getContainer()取得容器,方便全局引用
6:容器已经形成了,将容器定义数据导出Dumper,存储到缓存,以便下次请求提高性能
至此第一大块的工作完成,后面开始容器里面的服务互动过程, http-kernel开始运作
精彩还在继续,但作为入门分享就到此结束了,谢谢各位
交流互动