前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >yii2开发中19条推荐实践

yii2开发中19条推荐实践

原创
作者头像
阿北
发布2018-06-02 15:57:18
3.3K0
发布2018-06-02 15:57:18
举报
文章被收录于专栏:阿北的知识分享

虽然每个人的编程风格不同,但是有些建议能让你的代码更加规范和稳定,本次就我这次网站更新总结如下几点,希望对你的yii2学习和使用有所帮助。

环境说明

  • 服务器环境: CentOS
  • 开发环境及IDE:mac & phpstorm
  • Yii:v2.0.15 基础版

接下来开说

开发前

先说说开发前的事情,磨刀不误砍柴工,将yii2配置到一个最易开发的状态。

Composer

这个是做yii2开发的基石,除非没有办法使用,否则请不要放弃,除了更容易的安装yii2及第三方扩展外,能使用Composer代表着你的服务器最少能运行起来php-cli,那么你就可以使用yii命令行,它会为你的开发带来无尽的遍历。

对于composer,有些关键词你要特别关注 install、update、require。

中文化

默认安装yii2时,程序的相关信息是英文的,第一步我们需要改成中文的,很简单。

代码语言:txt
复制
// config/web.php
'language'=>'zh-CN'

静态缓存问题

在用yii2的时候,我们习惯将静态文件(图片、css文件、js文件等)放到资源类中管理,但是可能存在浏览器缓存问题,在开发阶段可以通过配置来避免这个问题,尤其是开发移动端页面的时候特别有用。

代码语言:txt
复制
// config/web.php
'assetManager'=>[
    'appendTimestamp' => true
],

配置DB

虽然yii2对数据库,尤其是对mysql是很友好的,但是我们还是应该使用稳定高一点的版本,别说你的程序将来没有移动端,早早的选择一个支持emoji的数据库会避免我们下载第三方库去解决报错问题。

如果可以

  • mysql5.3.3 +
  • config/db.php 的charset=utf8mb4

配置debug

如果可能,请配置一个类似于xdebug的PHP扩展并且集成到你的IDE中,开发过程中难免遇到不好捕获的bug,这需要你在一个yii2生命周期内持续的观察某些变量的值及赋值路径,具体配置可以参考我之前的课程, 用xdebug支持yii2调试之 - PhpStorm配置篇

当然,yii2自己的debug扩展也极其有用,尤其配置urlManager的时候。

开发中

本段为你介绍我在yii2开发中一些习惯和小技巧,希望对你有用。

单一职责

一个类和一个方法应该只有一个职责,比如下面的代码

代码语言:txt
复制
function getFullName(){
    $isAdmin = Administrator::find()->where(['user_id'=>$this->id])->one();
    if($isAdmin && $this->xxx == 1){
        return $this->first_name . " " . $this->last_name;
    }
}

比如上面的情况我们最好是将对是否为管理员的判断单独提取出来,如下

代码语言:txt
复制
function getFullName(){
    
    if($this->isAdmin() && $this->xxx == 1){
        return $this->first_name . " " . $this->last_name;
    }
}

function isAdmin(){
    return Administrator::find()->one();
}

每个方法是一个最小化的问题解决单元,相关知识可以看下《重构 - 既有代码的改善》这本书,北哥大约三年前读过,很多小技巧,受益颇多。

模型的重要性

很多yii2的初学者喜欢将大量逻辑写到控制器的动作(action)中,这是不对的,我们的重点应该在模型中,而控制器仅仅是做输入输出。

我们拿关联举个例子,下面的这段代码是不好的。

代码语言:txt
复制
// 某个控制器
public function actionIndex(){
    // 这里还有很多代码
    ....
        
    //	获得三天前的某个会员的订单集合
	$order = Order::find()->where(["user_id"=>$userId])->andWhere([">","created_at",strtotime(date("Y-m-d",time()))-86400*3])->all();    
}

我们最好将这段逻辑放到会员模型中

代码语言:txt
复制
// 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();
}

控制器的代码力求简单,只做基本的输入帅选以及输出渲染。

规则

对与错,不要随便就写。

代码语言:txt
复制
// 某个控制器的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和场景吧。一切。

复用随时要想到(小挂件)

编码的原则是尽最大努力让代码复用,尤其是小挂件,它让视图层实现了复用,小挂件的使用非常简单

1、在@app下建立一个文件夹components

2、在components内建立一个挂件类(必须继承yii\base\Widget)

3、渲染一个小挂件的视图(如果需要,在components/views下)

4、使用它

没看明白?我给个例子。

代码语言:txt
复制
// 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');
    }
}

写一个视图

代码语言:txt
复制
// components/views/top10.php
<h1>Hello Top10</h1>

使用它

代码语言:txt
复制
// 某个视图
<?= \app\components\Top10::widget();?>

当然挂件可以很复杂,比如我们使用的ActiveForm、GridView等。关于小挂件我之前也写了一篇文章,有兴趣的同学可以看看。 传送门

AR关联的循环要很小心

这个问题我之前也视频说过,就是惰性加载和即时加载的问题,比如下面的代码并不好

代码语言:txt
复制
$customers = Customer::find()->limit(100)->all();

foreach ($customers as $customer) {
    // SELECT * FROM `order` WHERE `customer_id` = ...
    $orders = $customer->orders;
}

上面的代码执行了101次查询,如果数据更多那?对于上面的问题我们是这样解决的。

代码语言:txt
复制
// 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次。

让你的代码更加“简洁”

这里说的简洁并不是说代码量,而是表意。比如下面的代码

代码语言:txt
复制
// 方式1
if($num > 100){
    return 1
}else{
    return 2
}

// 方式2
return $num > 100 ? 1 : 2;

代码逻辑很简单的时候我们都喜欢第二种方式,但是如果逻辑复杂些,我更喜欢方式1,虽然它可能很多行,但是表意简洁,你能看懂、他也能看懂。

何苦废了牛劲去写一个自我感觉巨牛逼的表达式那!!!

为视图的PHP代码增加一个try

在写action或模型方法的时候,为了保证代码的稳定性,我们一般都会用try....catch语法结构,但是在yii2的视图内很少有人用,记住,也要用! 比如下面这段代码。

代码语言:txt
复制
// 视图内
<?= \app\components\WechatLangSideMenu::widget();?>

如果上面代码出错了怎么办,我推荐如下方式写

代码语言:txt
复制
<?php
try {
    echo \app\components\WechatLangSideMenu::widget();
}catch(\Exception $e){
	//	可以不处理也可以写你自己的错误处理。
}
?>

小心使得万年船。

勿写死,用常量或配置。

有些代码需要一些判断,而判断的参考是某些值,比如下面的代码

代码语言:txt
复制
if($this->type === 1){
    return "文章";
}else if($this->type === 2){
    return "专栏";
}

我推荐这样写

代码语言:txt
复制
if($this->type === Item::ARTICLE_TYPE){
    return "文章";
}else if($this->type === Item::TOPIC_TYPE){
    return "专栏";
}

ARTICLE_TYPE 和 TOPIC_TYPE是Item模型的两个常量。

使用迁移脚本

我说过了很多次,本篇还是要说一次,对于一个yii2程序的数据库部分请用migration来管理。

并且这些脚本应该一起放到到你的版本控制里,记住,迁移脚本一般包含两个部分。

  • 结构脚本
  • 种子数据的导入

很多人都忽略了第二类。另外在做迁移脚本的时候,如果你的表有前缀,那么在脚本里的写法如下

代码语言:txt
复制
{{%user}}// discuz_user

时间问题

使用yii2开发mysql类web应用的时候,数据表的时间类字段我们喜欢用时间戳,一般表内都会有记录生成时间和更新时间字段。

对于他们的更新请使用yii2内置的TimestampBehavior行为类,则字段数据的填充我们就无需操心了,如下代码

代码语言:txt
复制
namespace app\models;

use Yii;
use yii\behaviors\TimestampBehavior;

class Article extends \yii\db\ActiveRecord {
    
    public function behaviors(){
        return [
            [
                'class' => TimestampBehavior::className(),
            ]
        ];
    }    
}

因此在数据表中我推荐时间字段命名规则如下

  • 生成时间 created_at
  • 更新时间 updated_at

这样如上代码就完全够用了,无需指定字段。

记住:去掉在rules内对created_at和updated_at字段required的限制。

是父类还是行为

其实我是不排斥任何一种的,各有利弊吧,父类使用简单但是增加了耦合,行为耦合度低但是配置比直接父类复杂些。

当然从理念上说也有点不同

  • 行为 一些类附加的属性
  • 父类 一些类共同的属性

我的用法(不一定就是对的),尤其在模块中我喜欢为控制器增加一层父类。

开发完

程序开发完还需要对yii2程序进行一些配置,很多你一定已经会了。

入口文件

我们首先要改变yii2的运行模式,从开发模式变为生产模式,一般代码如下

代码语言:txt
复制
// index.php
defined('YII_DEBUG') or define('YII_DEBUG', false);
defined('YII_ENV') or define('YII_ENV', 'prod');

报错页面

对于一个稳定的程序,报错不要紧,要紧的是报错后的处理,既然用户觉得有好又对开发人员有帮助,我之前写过一篇文章,你可以看下 《用yii2实现youtube风格的错误处理页面》

urlManager

严格来说这个应该在开发阶段做,为了对搜索引擎更有好,也为了增加程序的安全性,我们应该对url进行美化,比如

代码语言:txt
复制
/index.php?r=admin/user/index // 写成 /admin/user-index.html

具体关于urlManager的配置及常用web服务器配置可以看下我之前写的速查表,有现成的代码。

小结

一不小心写了这么多,当然yii2开发要注意的地方何止这些,以后慢慢说。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开发前
    • Composer
      • 中文化
        • 静态缓存问题
          • 配置DB
            • 配置debug
            • 开发中
              • 单一职责
                • 模型的重要性
                  • 规则
                    • 复用随时要想到(小挂件)
                      • AR关联的循环要很小心
                        • 让你的代码更加“简洁”
                          • 为视图的PHP代码增加一个try
                            • 勿写死,用常量或配置。
                              • 使用迁移脚本
                                • 时间问题
                                  • 是父类还是行为
                                  • 开发完
                                    • 入口文件
                                      • 报错页面
                                        • urlManager
                                        • 小结
                                        相关产品与服务
                                        云服务器
                                        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档