目录

Yii2官方文档阅读小记

到现在终于将yii2的官方文档读过一次了,在此将我的理解和小注解张贴上来

$model->getErrors()

在yii内部会有验证的规则,$model->validate() 根据model层定义的rules去检查用户输入的数据,有时候我们在保存的数据库的时候会出现保存失败,我们需要调用$model->getErrors() 去获取错误详情

定义别名

aliases 为系统路径定义别名

bootstrap

指定启动阶段yii\base\Application::bootstrap()需要运行的组件。

yii\base\Application::components

允许注册多个在其他地方使用的应用组件,

name

展示给终端用户的应用名称、

应用组件

在config中的component中定义的都是应用组件,比如数据库连接,就是一个组件

控制器的请求逻辑

https://img.cdn.resowolf.com/static/创建、配置控制器.png

执行的顺序:

model (模型)

yii 的模型中定义了属性、属性标签(attributeLabels()方法来实现)、块赋值、验证规则等,

应用场景及验证规则

模型的验证规则可以用rules()来声明,如果在多个场景需要用到同一个模型的不同验证规则,我们需要使用yii的场景概念,scenario属性及方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const SCENARIO_LOGIN = 'login';
const SCENARIO_REGISTER = 'register';

public function scenarios()
{
    return [
        self::SCENARIOS_LOGIN => ['username','password'],
        self::SCENARIOS_REGISTER =>['username','email','password']
    ];
}

配合验证规则使用,需要在rules()中添加on属性,

视图访问数据,

在视图中可以通过拉取的方式获取数据可以使用$this->context->id 视图间共享数据 设定参数

缺省路由

在首页的时候需要一个缺省路由去控制访问的控制器和方法,需要用到默认的路由 在配置文件中查找,'defaultRoute' =>'main/index';

catchAll路由(全拦截路由)

在维护模式使用这个属性,在配置文件中设置catchAll 的属性,'catchAll' => ['site/done'],

创建路由,

1
2
3
4
5
use yii\helpers\Url;

echo Url::to(['post/index']);

restful app

在需要获取PUT、PATCH等请求的发来的参数时,可以通过yii\web\Request::getBodyParams()来获取参数,

请求的方法

Yii::$app->request->method获取当前请求的方法,

对urls的处理

  • yii\web\request::url 返回当前url除域名(ip)外的信息
  • yii\web\request::absoluteUrl 返回整个url信息
  • yii\web\request::hostInfo 返回域名(ip)
  • yii\web\request::pathInfo 入口文本之后,查询参数之前
  • yii\web\request::queryString 查询的参数
  • yii\web\request::baseUrl 域名和入口文本之间的内容
  • yii\web\request::scriptUrl 没有path info和查询字符串部分。
  • yii\web\request::serverName
  • yii\web\request::serverPort

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$request = Yii::$app->request;
var_dump($request->url);
var_dump($request->hostInfo);
var_dump($request->absoluteUrl);
var_dump($request->pathinfo);
var_dump($request->queryString);
var_dump($request->baseUrl);
var_dump($request->scriptUrl);
var_dump($request->serverName);
var_dump($request->serverPort);

响应

设置状态码

1
2
3
Yii::$app->response->statusCode = 200;

throw new \yii\web\NotFoundHttpException;

以下为Yii预定义的HTTP异常:

  • yii\web\BadRequestHttpException: status code 400.
  • yii\web\ConflictHttpException: status code 409.
  • yii\web\ForbiddenHttpException: status code 403.
  • yii\web\GoneHttpException: status code 410.
  • yii\web\MethodNotAllowedHttpException: status code 405.
  • yii\web\NotAcceptableHttpException: status code 406.
  • yii\web\NotFoundHttpException: status code 404.
  • yii\web\ServerErrorHttpException: status code 500.
  • yii\web\TooManyRequestsHttpException: status code 429.
  • yii\web\UnauthorizedHttpException: status code 401.
  • yii\web\UnsupportedMediaTypeHttpException: status code 415.
  • 创建异常throw new \yii\web\HttpException(402);

Sessions 和 Cookies

yii为session和cookie封装了专门的对象来处理和使用,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$session = Yii::$app->session;

// 检查session是否开启
if ($session->isActive) 

// 开启session
$session->open();

// 关闭session
$session->close();

// 销毁session中所有已注册的数据
$session->destroy();

当session数据为数组时,session组件会限制你直接修改数据中的单元项, 例如:

1
2
3
4
5
6
7
8
9
// 如下代码不会生效
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;

// 如下代码会生效:
$session['captcha'] = [
    'number' => 5,
    'lifetime' => 3600,
];

可使用以下任意一个变通方法来解决这个问题:

  • 直接使用$_SESSION (确保Yii::$app->session->open() 已经调用)
  • 先获取session数据到一个数组,修改数组的值,然后保存数组到session中

使用ArrayObject数组对象代替数组

使用带通用前缀的键来存储数组

Flash数据

Flash数据是一种特别的session数据,一旦在某个请求中设置后,只会在下一个请求中有效,然后就会被删除。

用法:

1
2
3
$session = Yii::$app->session;
$session->setFlash('postDeleted', 'You have successfully deleted your post.');
echo $session->getFlash('postDeleted');

behavior 行为

在控制器或模型的方法前写behavior

yii2 的curd操作

yii2中的curd和yii1的分类大致一样,主要分为QB(查询生成器) 和AR(活动记录)

QB

QB较yii1的QB更为简单了

直接实例化query就可以了

1
2
$query = new Query();
$query->select('*')->from(self::tableName())->where()->all();

需要注意的是在对数据库进行操作的时候要进行数据验证,为了避免从删库到跑路的发生,

去除重复行

1
$query->select('user_name')->distinct();

查询字段使用别名

1
$query->select(['id'=>'user_id','username']);

所查询的数据表用别名

1
$query->from(['u' => 'user','o'=>'order']);

条件语句(使用绑定参数的时候只会 取到该数组的第一个元素)

1
$query->where('id = :id',[':id' =>$id]);

查看sql语句

有时候我们想看看组建的sql语句,我们需要以下代码

1
2
3
$query->createCommand();
var_dump($query->sql);//查看sql
var_dump($query->param);//查看参数

索引查询结果

1
$query->indexBy('id');

返回结果如下 https://img.cdn.resowolf.com/static/MedQGu.png

批量处理查询

在处理到大数据时我们需要考虑到数据量对服务器性能的影响,yii2为我们提供了相应的操作方法

1
2
3
4
5
6
7
8
$id = [2,3,4,5];
$query = (new Query())->select(['id','username'])
    ->from(self::tableName())
    ->where(['id' => $id])
    ->indexBy('username');
foreach ($query->each() as $user) {//单条记录
    var_dump($user);
}

运行结果 https://img.cdn.resowolf.com/static/zhjU3U.png

1
2
3
foreach ($query->batch() as $user) {//100条的数组或小于100
    var_dump($user);
}

AR

AR的操作更为简便

一个AR类关联一张数据表,一个AR对象对应表中的一行记录

基本和yii1无异不做过多介绍了

数据验证

使用$model->validate()执行验证

验证规则:

  • required->必填
  • email->邮箱

自定义错误信息

‘message’ => ‘dasd’

条件式验证

1
2
3
['name','required','when' => function($model) {
    return $model->city == 'bj';
}]

客户端条件验证

1
2
3
4
5
['name','required','when' => function($model){
    return $model->city == 'bj';
},'whenClient'=>"function(arrtibute,value){
    return $('#city').value == 'bj';
}"]

数据预处理

1
2
3
return[
    [['username'],'trim'],
];

空输入

1
2
3
return[
    ['order','default','value'=>1],
];

使用isEmpty

1
2
3
['agree',required','isEmpty' => function($value){
    return empty($value);
}]

核心验证器

yii提供用户输入验证的规则

  • 验证是否必填 [['email','password'],'required'],
  • 验证布尔值
1
2
3
4
['status','boolean'],

['status','boolean','trueValue' => true, 'falseValue' => false, 'strict' => true],

  • 验证两次密码是否相同
1
['password','compare'],
  • 验证文件
1
['primaryImage', 'file', 'extensions' => ['png', 'jpg', 'gif'], 'maxSize' => 102410241024],

临时验证,在没有任何模型参数绑定的值进行验证,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$validator = new EmailValidator();
if (!empty(Yii::$app->request->post())){
    $user = Yii::$app->request->post('User');
    if ($validator->validate($user['username'],$error)){
        echo '合法的email';
    }else{
        echo $error;
    }
    exit;
}

可以即时添加特性和验证规则的定义

1
2
3
4
5
6
7
8
9
$model = DynamicModel::validateData(compact('name,email'),[
    [['name','email'],'string','max' =>128],
    ['email','email'],
]);
if ($model->hasErrors()){
    echo “验证失败”;
}else{
    echo “验证成功”;
}

Model方法

  • yii\base\Model::loadMultiple() 将数据加载到一个数组中。
  • yii\base\Model::validateMultiple() 验证一系列模型。

格式化输出数据

1
2
$formatter = \Yii::$app->formatter;
echo $formatter->asDate('2016-07-28′,'long');

有很多格式化数据的方法具体参见yii\i18n\Formatter文件中的定义

分页

yii提供了内置的分页组件

  • 模板中
1
2
3
4
5
6
7
8
9
use yii\data\Pagination;

$query = Article::find()->where(['status' => 1]);
$count = $query->count();

$pagination = new Pagination(['totalCount' => $count]);
$articles = $query->offset($pagination->offset)
    ->limit($pagination->limit)
    ->all();
  • 视图中
1
2
3
4
5
use yii\widgets\LinkPager;

echo LinkPager::widget([
    'pagination' => $pagination,
]);

数据提供器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$dataProvider = new ActiveDataProvider([
    'query' => LogApi::find(),
    'pagination' => [
        'pageSize' => 30,
    ],
    'sort' => [
        'defaultOrder' => [
            'ctime' => SORT_DESC,
        ]
    ],
]);

数据部件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?= GridView::widget([
    //'responsive'=>true,
    //'hover'=>true,
    //'floatHeader'=>true,
    //'showPageSummary'=>true,
    'layout'       => "{items}\n{pager}",
    //'filterModel' => $searchModel,
    'dataProvider' => $dataProvider,
    'columns'      => [
        ['class' => 'yii\grid\SerialColumn'],
        // 数据提供者中所含数据所定义的简单的列
        // 使用的是模型的列的数据
        [
            "attribute" => "id",
            'value'     => function ($data) {
                return Html::a($data->id, "/log/get?id={$data->id}", ['target' => '_blank']);
            },
            "format"    => 'raw',
            "label"     => 'ID',
        ],
        'qid',
        'level',
        'category',
        'log_time',
//        [
//            'class'     => 'yii\grid\DataColumn',
//            "attribute" => "log_time",
//            "format"    => ['date', 'php:Y-m-d H:i:s:u'],
//            "label"     => '时间',
//        ],
//        'prefix',
//        'message',
//        'server',
        'uid',
        'type',
//        'query',
//        'unique_tag',
//        [
//            "attribute" => "return",
//            "format"    => 'text',
//            "label"     => '结果',
//        ],
        [
            "attribute" => "ctime",
            "format"    => 'text',
            "label"     => '创建时间',
        ],
    ],
]);?>

测试环境的搭建

1
2
3
4
composer global require "codeception/codeception=2.0.*"
composer global require "codeception/specify=*"
composer global require "codeception/verify=*"

或者

1
2
3
composer global require "codeception/codeception=2.1.*"
composer global require "codeception/specify=*"
composer global require "codeception/verify=*"

不过我在执行composer global require "codeception/codeception=2.0.*"

会提示我安装错误,但2.1是没有问题的

定义全局变量

1
composer global status

窗口会显示

1
Changed current directory to <directory>

<directory>/vendor/bin 增加到你的 PATH 环境变量中

ps:方法

1
vim ~/.bash_profile

输入如下内容

1
2
export PATH=/Users/root/.composer/vendor/bin:$PATH

运行source ~/.bash_profile,就可以在命令行中全局的使用 codecept 命令了