虽然每一个人的编程风格不一样,可是有些建议能让你的代码更加规范和稳定,本次就我此次网站更新总结以下几点,但愿对你的yii2学习和使用有所帮助。
环境说明php
接下来开说css
先说说开发前的事情,磨刀不误砍柴工,将yii2配置到一个最易开发的状态。html
这个是作yii2开发的基石,除非没有办法使用,不然请不要放弃,除了更容易的安装yii2及第三方扩展外,能使用Composer表明着你的服务器最少能运行起来php-cli,那么你就可使用yii命令行,它会为你的开发带来无尽的遍历。mysql
对于composer,有些关键词你要特别关注 install、update、require。web
默认安装yii2时,程序的相关信息是英文的,第一步咱们须要改为中文的,很简单。sql
// config/web.php 'language'=>'zh-CN'
在用yii2的时候,咱们习惯将静态文件(图片、css文件、js文件等)放到资源类中管理,可是可能存在浏览器缓存问题,在开发阶段能够经过配置来避免这个问题,尤为是开发移动端页面的时候特别有用。数据库
// config/web.php 'assetManager'=>[ 'appendTimestamp' => true ],
虽然yii2对数据库,尤为是对mysql是很友好的,可是咱们仍是应该使用稳定高一点的版本,别说你的程序未来没有移动端,早早的选择一个支持emoji的数据库会避免咱们下载第三方库去解决报错问题。编程
若是能够浏览器
若是可能,请配置一个相似于xdebug的PHP扩展而且集成到你的IDE中,开发过程当中不免遇到很差捕获的bug,这须要你在一个yii2生命周期内持续的观察某些变量的值及赋值路径,具体配置能够参考我以前的课程, 用xdebug支持yii2调试之 - PhpStorm配置篇缓存
固然,yii2本身的debug扩展也极其有用,尤为配置urlManager的时候。
本段为你介绍我在yii2开发中一些习惯和小技巧,但愿对你有用。
一个类和一个方法应该只有一个职责,好比下面的代码
function getFullName(){ $isAdmin = Administrator::find()->where(['user_id'=>$this->id])->one(); if($isAdmin && $this->xxx == 1){ return $this->first_name . " " . $this->last_name; } }
好比上面的状况咱们最好是将对是否为管理员的判断单独提取出来,以下
function getFullName(){ if($this->isAdmin() && $this->xxx == 1){ return $this->first_name . " " . $this->last_name; } } function isAdmin(){ return Administrator::find()->one(); }
每一个方法是一个最小化的问题解决单元,相关知识能够看下《重构 - 既有代码的改善》这本书,北哥大约三年前读过,不少小技巧,受益颇多。
不少yii2的初学者喜欢将大量逻辑写到控制器的动做(action)中,这是不对的,咱们的重点应该在模型中,而控制器仅仅是作输入输出。
咱们拿关联举个例子,下面的这段代码是很差的。
// 某个控制器 public function actionIndex(){ // 这里还有不少代码 .... // 得到三天前的某个会员的订单集合 $order = Order::find()->where(["user_id"=>$userId])->andWhere([">","created_at",strtotime(date("Y-m-d",time()))-86400*3])->all(); }
咱们最好将这段逻辑放到会员模型中
// User模型 public function recent3DaysOrders(){ return Order::find()->where(["user_id"=>$this->id])->andWhere([">","created_at",strtotime(date("Y-m-d",time()))-86400*3])->all(); } // 控制器中 public function actionIndex(){ $order = $user->recent3DaysOrders(); }
控制器的代码力求简单,只作基本的输入帅选以及输出渲染。
对与错,不要随便就写。
// 某个控制器的action中 public function actionCreate(){ $model = new User(); if(Yii::$app->request->isPost){ $model->load(Yii::$app->request->post()); if($model->xxx == xxxx){ // todo } if($model->save()){ // } } }
上面的代码再熟悉不过了,这是咱们指望的样子,可是有的时候输入并不会这样老实,咱们须要进行更多验证,请不要将验证直接写到action内,好比上面代码中的if判断。
将验证的工做交给模型的rule和场景吧。一切。
编码的原则是尽最大努力让代码复用,尤为是小挂件,它让视图层实现了复用,小挂件的使用很是简单
一、在@app下创建一个文件夹components
二、在components内创建一个挂件类(必须继承yiibaseWidget)
三、渲染一个小挂件的视图(若是须要,在components/views下)
四、使用它
没看明白?我给个例子。
// components/Top10.php <?php namespace app\components; use yii\base\Widget; class Top10 extends Widget { public function init(){ parent::init(); } public function run(){ parent::run(); return $this->render('top10'); } }
写一个视图
// components/views/top10.php <h1>Hello Top10</h1>
使用它
// 某个视图 <?= \app\components\Top10::widget();?>
固然挂件能够很复杂,好比咱们使用的ActiveForm、GridView等。关于小挂件我以前也写了一篇文章,有兴趣的同窗能够看看。 传送门
这个问题我以前也视频说过,就是惰性加载和即时加载的问题,好比下面的代码并很差
$customers = Customer::find()->limit(100)->all(); foreach ($customers as $customer) { // SELECT * FROM `order` WHERE `customer_id` = ... $orders = $customer->orders; }
上面的代码执行了101次查询,若是数据更多那?对于上面的问题咱们是这样解决的。
// SELECT * FROM `customer` LIMIT 100; // SELECT * FROM `orders` WHERE `customer_id` IN (...) $customers = Customer::find() ->with('orders') ->limit(100) ->all(); foreach ($customers as $customer) { // 没有任何的 SQL 执行 $orders = $customer->orders; }
从101次查询减小到2次。
这里说的简洁并非说代码量,而是表意。好比下面的代码
// 方式1 if($num > 100){ return 1 }else{ return 2 } // 方式2 return $num > 100 ? 1 : 2;
代码逻辑很简单的时候咱们都喜欢第二种方式,可是若是逻辑复杂些,我更喜欢方式1,虽然它可能不少行,可是表意简洁,你能看懂、他也能看懂。
何苦废了牛劲去写一个自我感受巨牛逼的表达式那!!!
在写action或模型方法的时候,为了保证代码的稳定性,咱们通常都会用try....catch语法结构,可是在yii2的视图内不多有人用,记住,也要用! 好比下面这段代码。
// 视图内 <?= \app\components\WechatLangSideMenu::widget();?>
若是上面代码出错了怎么办,我推荐以下方式写
<?php try { echo \app\components\WechatLangSideMenu::widget(); }catch(\Exception $e){ // 能够不处理也能够写你本身的错误处理。 } ?>
当心使得万年船。
有些代码须要一些判断,而判断的参考是某些值,好比下面的代码
if($this->type === 1){ return "文章"; }else if($this->type === 2){ return "专栏"; }
我推荐这样写
if($this->type === Item::ARTICLE_TYPE){ return "文章"; }else if($this->type === Item::TOPIC_TYPE){ return "专栏"; }
ARTICLE_TYPE 和 TOPIC_TYPE是Item模型的两个常量。
我说过了不少次,本篇仍是要说一次,对于一个yii2程序的数据库部分请用migration来管理。
而且这些脚本应该一块儿放到到你的版本控制里,记住,迁移脚本通常包含两个部分。
不少人都忽略了第二类。另外在作迁移脚本的时候,若是你的表有前缀,那么在脚本里的写法以下
{{%user}}// discuz_user
使用yii2开发mysql类web应用的时候,数据表的时间类字段咱们喜欢用时间戳,通常表内都会有记录生成时间和更新时间字段。
对于他们的更新请使用yii2内置的TimestampBehavior行为类,则字段数据的填充咱们就无需操心了,以下代码
namespace app\models; use Yii; use yii\behaviors\TimestampBehavior; class Article extends \yii\db\ActiveRecord { public function behaviors(){ return [ [ 'class' => TimestampBehavior::className(), ] ]; } }
所以在数据表中我推荐时间字段命名规则以下
这样如上代码就彻底够用了,无需指定字段。
记住:去掉在rules内对created_at和updated_at字段required的限制。
其实我是不排斥任何一种的,各有利弊吧,父类使用简单可是增长了耦合,行为耦合度低可是配置比直接父类复杂些。
固然从理念上说也有点不一样
个人用法(不必定就是对的),尤为在模块中我喜欢为控制器增长一层父类。
程序开发完还须要对yii2程序进行一些配置,不少你必定已经会了。
咱们首先要改变yii2的运行模式,从开发模式变为生产模式,通常代码以下
// index.php defined('YII_DEBUG') or define('YII_DEBUG', false); defined('YII_ENV') or define('YII_ENV', 'prod');
对于一个稳定的程序,报错没关系,要紧的是报错后的处理,既然用户以为有好又对开发人员有帮助,我以前写过一篇文章,你能够看下 《用yii2实现youtube风格的错误处理页面》
严格来讲这个应该在开发阶段作,为了对搜索引擎更有好,也为了增长程序的安全性,咱们应该对url进行美化,好比
/index.php?r=admin/user/index // 写成 /admin/user-index.html
具体关于urlManager的配置及经常使用web服务器配置能够看下我以前写的速查表,有现成的代码。
一不当心写了这么多,固然yii2开发要注意的地方何止这些,之后慢慢说。