学习Yii好久了,一直作的是小案例,自觉得学的还不错。直到最近用Yii开发了一个很是简单的CMS,一路下来,磕磕绊绊,才知本身不足。加上最近正学习着偏架构方面的知识。特此总结一下。小白经验,大神轻拍,欢迎讨论。php
本篇文章主要是将一些 MVC 代码组织的技巧,不会涉及详细编码。声明使用的模版是Yii高级模板。java
全部的php框架几乎都遵循MVC模式设计,网络各类教程、官方手册,也是一股脑的说着按着MVC组织代码。
先说说开发中个人悲惨历史。数据库
你们都知道,在Yii中,一张表对应一个AR,再对应一个控制器。c#
在开发开始的时候确实是不错的。好比留言功能里面。我在common\models
下生成了对应的AR类。而后在frontend
和backend
的控制器里导入了这个AR类,修改相应视图。而后根据须要对查询作了简单封装,便是在生成的AR类中写了一些方法,而后控制器调用。功能实现,代码逻辑也清晰。自觉棒棒哒。后端
而后就到痛苦的时候了。在设计文章和栏目的时候,我分了三张表:文章表,栏目表,文章内容表。在common\models
生成三个AR类,后台、前台分别调用。因为建立文章时三张表都须要同时用到,以及插入、修改、删除的时候,须要用事务保证一致性。因而我只能就在文章的控制器里添加了一个又一个涉及数据库操做的方法。而后在前台显示的时候,又在对应的模型类里添加了一些方法,前台控制器又是通常修改。首页显示的控制器,映入了八个AR类。而后到最后,看着控制器里一个个AR查询的方法,AR类中又是一堆不一样的查询方法,我完全懵逼了。php框架
好不容易实现完功能,本身都不敢看本身的代码了。微信
开发完以后,痛定思痛。在大量阅读博客、书籍之下。得到如下经验,与君共享。网络
关于MVC中,首先声明的一点是设计要“胖Model痩Controller”,即Controller
应该只有薄薄的一层。主要业务逻辑都在Model中。架构
视图层和控制层不用多谈,你们都知道。主要该谈谈的是模型层。app
对于先后都要用到的模型,你们都会生成AR类到common\models
,而后在frontend
和backend
的控制器里导入了这些AR类。可是,这不是一个好的习惯。先后台有着不一样的应用逻辑。引用同一个AR类必然职责不清。正确的作法是在先后台的models
文件夹里,新建不一样的类,而后继承common\models
中的AR类,作到模型分离。
举个例子。在common\models
中有个Post.php
AR类,你应该在backend\models
中新建一个Post.php
而后继承common\models
中的Post.php
类。前台也是如此,作到引用分离。
开发中一定涉及到多表关联。若是所有在控制器中引入模型类,写查询语句,代码组织就会很是糟糕,不利于维护管理,更正确的作法是。创建一个业务逻辑层(service)。
也就是作backend
和frontend
文件夹下创建一个services
文件夹,保存咱们的业务逻辑。好比我前面有三张表:文章表,栏目表,文章内容表,分别对应三个模型。当我须要保存一片文章时,同时涉及到三张表的操做。我就能够创建一个PostService.php
,里面引入这三个AR类,而后创建一个SavePost()
方法,在方法里同时对三张表作操做。这样,控制器里只需引入这个服务类,调用相应方法就好了。
实际的应用都是读多写少,所以,咱们能够作到代码层面的读写分离。(详细的能够了解了解CQRS架构),方便分别优化。并且Yii中的AR虽然很方便,可是效率不高,太复杂的查询也是很差实现的。
这里Yii提供了一个简单高效的SQL
查询。那就是DAO。
就是使用方式是这个的东西。
$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status') ->bindValue(':id', $_GET['id']) ->bindValue(':status', 1) ->queryOne();
咱们能够在services
文件夹里创建只提供查询的文件,好比PostQuery.php
文件提供对文章的查询
第一次开发一个完整的东西,学习到了不少。最近打算对这个CMS进行重构。道路阻且长,加油!
共 6 条评论
楼主写的不错,但愿分享更多经验
写的不错!我也是刚刚学习,交流下经验。对于model层,我通常都是放在common中,可是为了防止混淆,我会创建表单模型,譬如:Post.php,我会让它对应一个PostForm.php(继承自Model),让它处理业务逻辑,Post.php仅仅处理简单的数据操做或者彻底就是一个数据模型。若是,按照楼主的方法,虽然先后端代码分离的更加清晰,可是我想这样作代码是否是会有不少重复了。。毕竟,模型层的操做会有不少同样的。
嗯嗯,学习了,这个方法不错。关于先后端分别建一个 Model,继承 common 中的 model,也只是针对一些复杂的,须要较多业务操做的,简单的直接 common 中一个model 就好了。一切根据需求来就好了,不致使过分设计。
至关不错。个人也是都放在
common/models
只有特殊的才放在 各自frontend
或backend
文件夹下。都没有考虑过继承。总结的不错,学习了
至关不错;特别是对于模型处理;还有就是处理业务逻辑service与java的思想差很少
AR模型虽然效率低一些,可是有更多的高级功能。好比事件,行为,事务等等。拿写操做来讲,AR模型中提供beforeSave, afterSave这这两个方法,这两个方法会触发相应的事件,你能够在这些事件上绑定一些事件处理器完成对写流程的控制或者完成额外的一些操做,这是Yii2操做数据库最为高级的方式,也是最精华的优势之一。我的觉得,牺牲点运行性能,增长开发和理解上的便利性是划算的。
很差意思,是我没有表述清楚。我说的是代码层面的读写分离。并非全用 SQL 语句。
数据库操做就涉及增、删、改、查,其中增、删、改都是会对数据库的内容的状态形成改变,而查操做是不会对数据产生修改的。
针对这个特性,咱们能够在代码层面作出读(即查)写(即增、删、改)分离。便于针对不一样的优化。
我提出的是,写操做使用 AR 模型,读操做则直接用 SQL 语句。
缘由有这么几点:
其实究根结底,最终仍是为了性能和维护。
我认为你的观点——使用AR模型作写操做,而用SQL作读操做很是有道理。Yii的读操做也是分为几个层次,原生态上SQL,DAO和AR模型。DAO的方式读,也提供了Query和BuildQuery帮你生成复杂的SQL语句,可是执行的方式几乎仍是和PDO同样,因此效率高的同时,方便性也获得保障。