Yii2笔记


Yii 维护页面

  1. 网站维护,入口文件index.php 直接echo
  2. 在应用的配置文件(man.php)中加入以下代码:
1
2
3
4
5
<?php
'catchAll' => [             //打开之后所有页面进入维护模式
        'site/maintenance',    //维护页面控制器
        'message' => '网站维护',  //参数(可有可无)
     ],      

registerJsFile()

1
2
<?php
$this->registerJsFile('@web/js/about.js',['depends'=>'yii\web\YiiAsset','position'=>\yii\web\View::POS_END]);

参数说明


注册用户,当输入用户名的时候,直接判断是否存在,而不是提交再判断

那么这种做法是,开启ActiveFormenableAjaxValidation

1
2
<?php 
<?php $form = ActiveForm::begin(['id' => 'form-signup','enableAjaxValidation' => true]);?>

然后在controller里添加一个ajax验证字段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php
$model = new SignupForm();
        if ($model->load(Yii::$app->request->post())) {
            if (Yii::$app->request->isAjax) {
                    Yii::$app->response->format = Response::FORMAT_JSON;

                    return ActiveForm::validate($model);
            } //ajax提交过来的会直接进行验证
            if ($user = $model->signup()) {
                if (Yii::$app->getUser()->login($user)) {
                    return $this->goHome();
                }
            }
        }

        return $this->render('signup', [
            'model' => $model,
        ]);

权限流程

  1. 菜单管理添加菜单,在数据选项中添加{"icon":"fa fa-rss"}可以更换图标,要用双引号
  2. 路由列表 – 添加路由
  3. 权限管理新增权限,把新添加的菜单权限放进去,并分配路由
  4. 角色管理 – 把新增的菜单分配给角色

添加新的应用

  1. 根目录下Copy一份backend 应用改名为blogapp
  2. 打开environments/index.php 增加其初始化工作。(开发环境和生产环境里面配置如下
 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
<?php
return [  
    'Development' => [  
        'path' => 'dev',  
        'setWritable' => [  
            'backend/runtime',  
            'backend/web/assets',  
            'frontend/runtime',  
            'frontend/web/assets',  
            'api/runtime',  
            'api/web/assets',  
        ],  
        'setExecutable' => [  
            'yii',  
        ],  
        'setCookieValidationKey' => [  
            'backend/config/main-local.php',  
            'frontend/config/main-local.php',  
            'api/config/main-local.php',  
        ],  
    ],  
    'Production' => [  
        'path' => 'prod',  
        'setWritable' => [  
            'backend/runtime',  
            'backend/web/assets',  
            'frontend/runtime',  
            'frontend/web/assets',  
            'api/runtime',  
            'api/web/assets',  
        ],  
        'setExecutable' => [  
            'yii',  
        ],  
        'setCookieValidationKey' => [  
            'backend/config/main-local.php',  
            'frontend/config/main-local.php',  
            'api/config/main-local.php',  
        ],  
    ],  
];  
  1. 根目录  **environments/**中dev/prod/下各copy一份backend命名为blogapp即可
  2. common/config/bootstrap.php 里添加Yii::setAlias('@blogapp', dirname(dirname(__DIR__)) . '/blogapp');
  3. 有关应用blogapp文件夹里所有文件,有backend关健字全改成blogapp。才样,才能使用这个独立应用,
  4. 最重要的一步: 在服务端本地都要进行一次初始化,即更新一下入口文件个和配置,windows使用init,linux 使用./init

Yii 验证码的使用

site/contact下有默认的验证码可以参考

现在给注册用户页面添加一个验证码的功能:

  1. Form表单(frontend/models/SignupForm):
 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
<?php
class SignupForm extends Model{
  public $username;
    public $email;
    public $password;
    public $repassword;
    public $verifyCode;//验证码这个变量是必须建的,因为要储存验证码的值   
    public function rules()
    {
        return [
            ['username', 'match', 'pattern' => "/^[a-z0-9_\x{4e00}-\x{9fa5}]{2,10}$/ui",'message'=>'用户名不合格'],
            ['username', 'required'],
            ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => Yii::t('app/user','This username has already been taken.')],
            ['username', 'string', 'min' => 2, 'max' => 255],

            ['email', 'filter', 'filter' => 'trim'],
            ['email', 'required'],
            ['email', 'email'],
            ['email', 'string', 'max' => 255],
            ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => Yii::t('app/user','This email address has already been taken.')],

            [['password'], 'required'],
            ['password', 'string', 'min' => 6, 'max' => 16],
            ['repassword', 'required'],
            ['repassword', 'compare', 'compareAttribute'=>'password', 'message' => '两次密码不一致'],
            ['verifyCode', 'captcha', 'captchaAction'=>'site/captcha'],//如果是自定义的验证码,那么需要在这儿进行路由添加并且要跟view里的路径一样,否则会一直验证码错误,默认为site/catpcha
        ];
    }
//继续其他的
}
  1. 控制器(如果上面没有指定captchaAction,可以在这块位置来定义,现在定义在SiteController
 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
<?php
public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, //验证码是否为固定值,默认为空。如果是测试环境,就是固定值为testme
                'backColor' => 0x00FF99, //背景颜色,默认白色
                'foreColor' => 0xFF66FF, //字体颜色,默认蓝色
                'maxLength' => 4,  //最大字符长度,默认7
                'minLength' => 4,  //最小字符长度,默认6
                'height' => 35,  //高度,默认50
                'width' => 80,  //宽度,默认120
                'offset' => -1, //字符之间的间隔,默认-2
                'fontFile' => '@yii/captcha/SpicyRice.ttf',  //字体文件
                'imageLibrary ' => 'gd',//使用的库,默认为空,自己确定,优先使用imagick。只支持gd 和 imagick
                'padding' => 1, //文本周围填充,默认2
                'transparent' => false, //是否开启透明背景,默认false
                'testLimit' => 999, //见下
            ],
            'captcha1' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, //测试环境代码相同
            ],
        ];
    }
  1. 视图页面(view/site/signup):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
 <?php $form = ActiveForm::begin(['id' => 'form-signup','enableAjaxValidation' => true]); ?>
        <<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>

                <?= $form->field($model, 'email') ?>

                <?= $form->field($model, 'password',['enableAjaxValidation'=>false])->passwordInput() ?>

                <?= $form->field($model, 'repassword',['enableAjaxValidation'=>false])->passwordInput() ?>

                <?= $form->field($model, 'verifyCode',['enableAjaxValidation'=>false,'enableClientValidation' => true])->widget(Captcha::className(), [
                    'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
                    'captchaAction'=>'site/captcha', //注意,这里要跟form里的一样,要不然会报错
                    'imageOptions'=>['alt'=>'点击换图','title'=>'点击换图', 'style'=>'cursor:pointer'],
                ]) ?>
<?php ActiveForm::end(); ?>
  1. 验证码总是不正确:
    testLimit含义:相同验证码出现的次数。默认为3。(小于等于0的值意味着不限制)为1,或小于3,这种情况下,相同的验证码只能出现一次,而用户如果开启了ajax验证的话,填写的时候ajax验证一次已达到上限1次,提交的时候再验证一次,他会判断是否大于了testLimit的值,第二次验证testLimit会加1,显然大于了1,这时会重新生成验证码,从而出现验证码老是不正确

另一个原因:因为开启了enableAjaxValidation ,通过查看请求连接发现:虽然关闭验证码的enableAjaxValidation,但是,当点击提交的时候,还是会发送ajax请求(来验证整个输入的表单),然而,因为我们在controller 里添加了一个验证,所以验证成功之后就刷新了验证码,导致提交时候的验证就失效了
大概的流程如下: ① 点击提交 ② 开启了enableAjaxValidation (不开启就不会报错)的时候会带着整个表单进行验证 ③ controller中有一句话

1
2
3
4
5
<?php
if (Yii::$app->request->isAjax) {
                    Yii::$app->response->format = Response::FORMAT_JSON;
                    return ActiveForm::validate($model);//在这儿第一次验证,成功了,所以已经刷新了
            }

④ 这个位置因为验证成功不会报错,所以又继续进行$model->signup.然而,在这个函数中,有这么一句话

1
2
3
4
<?php
 if (!$this->validate()) { //这儿进行第二次验证,因为码已经刷新,所以报错
            return null;
        }

⑤ 只需要吧最后一步的验证中的验证码验证取消即可

1
2
3
4
<?php
 if (!$this->validate(['username','password','email','repassword'])) {
            return null;
        }

⑥ 所以验证码报错,可以取消最后一步验证,也可以直接取消enableAjaxValidation

附上验证码的验证过程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
class CaptchaAction extends Action{
    public function validate($input, $caseSensitive)
    {
        $code = $this->getVerifyCode();
        $valid = $caseSensitive ? ($input === $code) : strcasecmp($input, $code) === 0;
        $session = Yii::$app->getSession();
        $session->open();
        $name = $this->getSessionKey() . 'count';
        $session[$name] = $session[$name] + 1;
        if ($valid || $session[$name] > $this->testLimit && $this->testLimit > 0) {
            $this->getVerifyCode(true); 
        }
        return $valid;
    }
}
  1. 设置参考链接1–关于设置 刷新网页的时候自动刷新验证码,前提是开启enableClientValidation ; 参考链接2–关于出错的链接 当然,Form表单的enableClientVaidation默认就是开启的

composer 更改为中国镜像

  1. 修改 composer 的全局配置文件(推荐方式)
    打开命令行窗口(windows用户)或控制台(Linux、Mac 用户)并执行如下命令: composer config -g repo.packagist composer https://packagist.phpcomposer.com
  2. 修改当前项目的 composer.json 配置文件
    进入你的项目的根目录(也就是 composer.json 文件所在目录),执行如下命令:
    composer config repo.packagist composer https://packagist.phpcomposer.com
    上述命令将会在当前项目中的 composer.json 文件的末尾自动添加镜像的配置信息(你也可以自己手工添加):
1
2
3
4
5
6
"repositories": {
     "packagist": {
           "type": "composer",
           "url": "https://packagist.phpcomposer.com"
     }
  }

checkbox默认选中

假设status要显示成复选框,在controller层:

1
2
3
4
5
<?php
$model->status = true;
return $this->render('create', [
                'model' => $model,
            ]);

view层:

1
2
3
4
<?php
<div class="col-md-1 checkbox">
	<?=$form->field($model,'status')->checkbox(['label'=>'原创','style'=>['zoom'=>'150%','margin-top'=>0]])->label(false)?>
</div>

这样默认就会选中,在checkedbox的参数中添加'checked'=>true无效

控制台带选项带参数写法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
namespace console\controllers;

use yii\console\Controller;

class HelloController extends Controller
{
	public $rev;

	public function options()
	{
		return ['rev'];
	}

	public function optionAliases()
	{
		return ['r'=>'rev'];
	}

	public function actionAll(array $name)
	{
		$this->rev == true ? var_dump(array_reverse($name)):var_dump($name);
	}
}

使用:yii hello/all -r q,w,e,r 或者yii hello/all --r q,w,e,r
输出结果都是翻转后的数组,区别是一个横杠表示使用选项别名,两个表示使用全称的选项

api中三种认证方式的区别

HttpBasicAuth : access token 作为一个用户名被传递。这种情况只适合“当access token可以安全的存储在API 接收端”的情况, 比如 调用 API 的是一个在服务器上运行的程序
QueryParamAuth:access token 在 API URL 中作为一个查询参数被传递,比如 https://example.com/users?access-token=123456789
因为多数的 Web 服务器会保存 query 参数在服务器日志中, 这个方法应该主要是用于响应无法使用 HTTP 头部信息来发送 access token 的 JSONP 请求的。
OAuth 2:遵照 OAth2.0 协议, 调用者从一个 授权服务器 上获取 access token, 再通过 HTTP Bearer Tokens 发送给 Api 服务器。

使用migration新建数据库迁移

新建:yii migrate/create <name>
执行:yii migrate/up

批量插入

是批量插入,不是多次插入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
$data = [
  ['user1','goods1'],
  ['user2','goods2']
];
Yii::$app->db->createCommand()
             ->batchInsert('{%table_name}',['user','goods'],$data)
             ->execute();
}
// {%tablen_name}是yii AR中的表名格式 (应使用两个花括号,此处使用一个是因为hugo会解析)

composer全局设置

composer config -g 全局命令 设置

AR模型中的with

查询多个数据,建议使用with,比如

1
2
3
4
5
6
7
8
<?php
// SQL executed: SELECT * FROM customer LIMIT 100
$customers = Customer::find()->limit(100)->all();
foreach ($customers as $customer) {
    // SQL executed: SELECT * FROM order WHERE customer_id=...
    $orders = $customer->orders;
    // ...处理 $orders...
}

以上代码将执行101 条SQL,第一条 SQL 查询语句取回100个客户,然后, 每个客户要执行一条 SQL 查询语句以取回该客户的所有订单。如果使用了with,只需要两条sql语句:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php
// SQL executed: SELECT * FROM customer LIMIT 100;
//               SELECT * FROM orders WHERE customer_id IN (1,2,...)
$customers = Customer::find()->limit(100)
    ->with('orders')->all();
foreach ($customers as $customer) {
    // 没有 SQL 语句被执行
    $orders = $customer->orders;
    // ...处理 $orders...
}

更详细的介绍:http://www.yiichina.com/doc/guide/2.0/db-active-record# 看第九条 延迟加载和及时加载