到现在终于将yii2的官方文档读过一次了,在此将我的理解和小注解张贴上来
$model->getErrors()
在yii内部会有验证的规则,$model->validate()
根据model层定义的rules去检查用户输入的数据,有时候我们在保存的数据库的时候会出现保存失败,我们需要调用$model->getErrors()
去获取错误详情
定义别名
aliases 为系统路径定义别名
bootstrap
指定启动阶段yii\base\Application::bootstrap()
需要运行的组件。
yii\base\Application::components
允许注册多个在其他地方使用的应用组件,
name
展示给终端用户的应用名称、
应用组件
在config中的component中定义的都是应用组件,比如数据库连接,就是一个组件
控制器的请求逻辑
执行的顺序:
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);//查看参数
|
索引查询结果
返回结果如下
批量处理查询
在处理到大数据时我们需要考虑到数据量对服务器性能的影响,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);
}
|
运行结果
1
2
3
| foreach ($query->batch() as $user) {//100条的数组或小于100
var_dump($user);
}
|
AR
AR的操作更为简便
一个AR类关联一张数据表,一个AR对象对应表中的一行记录
基本和yii1无异不做过多介绍了
数据验证
使用$model->validate()
执行验证
验证规则:
自定义错误信息
‘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
| Changed current directory to <directory>
|
将 <directory>/vendor/bin
增加到你的 PATH 环境变量中
ps:方法
输入如下内容
1
2
| export PATH=/Users/root/.composer/vendor/bin:$PATH
|
运行source ~/.bash_profile
,就可以在命令行中全局的使用 codecept
命令了