Yii2一些方法技巧小记

表单验证
表单验证,两个参数中至少需要一个:
public function rules()
{
return [
[[‘card_id’, ‘card_code’],
function ($attribute, KaTeX parse error: Expected '}', got 'EOF' at end of input: … if (empty(this->card_code) && empty($this->card_id)) {
t h i s − > a d d E r r o r ( this->addError( this>addError(attribute, ‘card_id/card_code至少要填一个’);
}
},
‘skipOnEmpty’ => false],
];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
表单验证,去除首尾空格:
public function rules()
{
return [[title’, ‘content’],‘trim’]];
}
1
2
3
4
校验 user_id 在User表中是否存在,并自定义错误信息。
public function rules()
{
return [

[[‘user_id’], ‘exist’,
‘targetClass’ => User::className(),
‘targetAttribute’ => ‘id’,
‘message’ => ‘此{attribute}不存在。’
],

];
}
1
2
3
4
5
6
7
8
9
10
11
12
Model 里面 rules 联合唯一规则
[[‘store_id’, ‘member_name’], ‘unique’, ‘targetAttribute’ => [‘store_id’, ‘member_name’], ‘message’ => ‘The combination of Store ID and Member Name has already been taken.’],
1
表单提交失败获取save()错误信息调试代码
echo array_values( m o d e l − > g e t F i r s t E r r o r s ( ) ) [ 0 ] ; e x i t ; v a r d u m p ( model->getFirstErrors())[0];exit; var_dump( model>getFirstErrors())[0];exit;vardump(model->getErrors());die;
1
2
单独为某个Action关闭 Csrf 验证
新建一个Behavior

use Yii;
use yii\base\Behavior;
use yii\web\Controller;

class NoCsrf extends Behavior
{
public $actions = [];
public c o n t r o l l e r ; p u b l i c f u n c t i o n e v e n t s ( ) r e t u r n [ C o n t r o l l e r : : E V E N T B E F O R E A C T I O N = > ′ b e f o r e A c t i o n ′ ] ; p u b l i c f u n c t i o n b e f o r e A c t i o n ( controller; public function events() { return [Controller::EVENT_BEFORE_ACTION => 'beforeAction']; } public function beforeAction( controller;publicfunctionevents()return[Controller::EVENTBEFOREACTION=>beforeAction];publicfunctionbeforeAction(event)
{
$action = e v e n t − > a c t i o n − > i d ; i f ( i n a r r a y ( event->action->id; if(in_array( event>action>id;if(inarray(action, $this->actions)){
$this->controller->enableCsrfValidation = false;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
然后在Controller中添加Behavior

public function behaviors()
{
return [
‘csrf’ => [
‘class’ => NoCsrf::className(),
‘controller’ => $this,
‘actions’ => [
‘action-name’
]
]
];
}
1
2
3
4
5
6
7
8
9
10
11
12
数据查询
where 多个查询条件示例:
User::find()->where([‘and’, [‘xxx’ => 0, ‘yyy’ => 2], [’>’, ‘zzz’, $time]]);
1
查询的时候 where 的 OR 和 AND 一起用
Topic::updateAll(
[‘last_comment_time’ => new Expression(‘created_at’)],
#[‘or’, [‘type’ => Topic::TYPE, ‘last_comment_username’ => ‘’], [‘type’ => Topic::TYPE, ‘last_comment_username’ => null]]
[‘and’, [‘type’ => Topic::TYPE], [‘or’, [‘last_comment_username’ => ‘’], [‘last_comment_username’ => null]]]
);
1
2
3
4
5
嵌套查询,groupBy 分组之后排序功能
$subQuery = new Query();
$subQuery->from(PostComment::tableName())->where([‘status’ => PostComment::STATUS_ACTIVE])->orderBy([‘created_at’ => SORT_DESC]);

$comment = PostComment::find()->from([‘tmpA’ => $subQuery])
->groupBy(‘post_id’)
->all();
1
2
3
4
5
6
生成的语句是

SELECT * FROM (SELECT * FROM post_comment WHERE status=1 ORDER BY created_at DESC) tmpA GROUP BY post_id
1
sql计算字段中相同值重复次数,并排序*
$query = static::find()
->select([‘package_uuid’, ‘count() AS count’, ‘cost’, ‘package_shop_id’])
->groupBy(‘package_uuid’);
->orderBy(‘count DESC’)
->limit(10);
1
2
3
4
5
避免select里面的子查询被识别成字段
$quert = User::find()
->select([
new Expression('count(
) as count , count(distinct mobile) as mnumber’)
])->asArray()
->all();
1
2
3
4
5
LIKE 查询 单边加%
[‘like’, ‘name’, ‘tester’] 会生成 name LIKE ‘%tester%’。

[‘like’, ‘name’, ‘%tester’, false] => name LIKE ‘%tester’

$query = User::find()
->where([‘LIKE’, ‘name’, $id.’%’, false]);
1
2
3
4
5
6
SQL 随机抽取十名幸运用户
$query = new Query;
$query->select(‘ID, City,State,StudentName’)
->from(‘student’)
->where([‘IsActive’ => 1])
->andWhere([‘not’, [‘State’ => null]])
->orderBy([‘rand()’ => SORT_DESC])
->limit(10);
1
2
3
4
5
6
7
yii2 多表联查 where条件里 A表字段=B表字段怎么表示?
#想在where条件里加上c.type=b.type怎么加?
$res =self::find()
->select([‘a.id’,‘a.name’])
->join(‘LEFT JOIN’,‘b’,‘b.qid=a.id’)
->join(‘LEFT JOIN’,‘c’,‘c.uid=b.uid’)
->where([‘a.state’=>0, ‘b.state’=>0, ‘c.state’=>0, ‘c.uid’=>123456])
->asArray()->all();

#方法:
$query->andWhere(new \yii\db\Expression(‘c.type = b.type’));
1
2
3
4
5
6
7
8
9
10
where条件中两字段相加或相减
$query->andWhere([’<’, ’updated_at + duration', time()])->all();
1
输出查询的sql语句
$query = Weibo::find()->joinWith(‘account’)->where([
‘and’,
[‘is_forward’ => 0],
[‘status’ => Weibo::STATUS_NORMAL_WITH_STAT],
[‘account_open_id’ => KaTeX parse error: Expected '}', got 'EOF' at end of input: …d_at` BETWEEN {now}-account.scrape_time*60 AND {$now}-account.scrape_time*60+60");

$commandQuery = clone $query;
// 输出SQL语句
echo $commandQuery->createCommand()->getRawSql();

$weibo = $query->all();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
输出语句:

SELECT weibo.* FROM weibo
LEFT JOIN account
ON weibo.account_open_id = account.open_id
WHERE ((is_forward=0)
AND (status=1)
AND (account_open_id IN (‘123456789’, ‘987654321’, ‘098765432’, ‘234123455’))
AND (read_limit_time IS NULL))
AND (posted_at BETWEEN 1474946053-account.scrape_time*60 AND 1474946053-account.scrape_time*60+60)
1
2
3
4
5
6
7
8
搜索的时候添加条件筛选
$dataProvider = s e a r c h M o d e l − > s e a r c h ( Y i i : : searchModel->search(Yii:: searchModel>search(Yii::app->request->queryParams);
$dataProvider->query->andWhere([‘pid’ => 0]);
1
2
如果要用 find_in_set 需要使用到 Expression 表达式:
User::find()
->where(new Expression(‘FIND_IN_SET(:status, status)’))
->addParams([’:status’ => 1])
->all();
1
2
3
4
MySQL 数据处理
yii2 给mysql数据库表添加字段后,立即使用这个字段时会出现未定义的情况(Getting unknown property)
原因:yii 对数据表结构进行了缓存。

方法1. 清理掉runtime下的cache缓存之后也可以正常使用这个字段。

方法2. 修改完表字段后执行

清理指定表结构缓存数据

Yii:: a p p − > d b − > g e t S c h e m a ( ) − > r e f r e s h T a b l e S c h e m a ( app->db->getSchema()->refreshTableSchema( app>db>getSchema()>refreshTableSchema(tableName);

清理所有表结构缓存数据

Yii::$app->db->getSchema()->refresh();
1
2
3
4
5
6
7
建议将以上代码添加到修改数据表结构的migration中。

字段去重的三种方法
static::find()
->where([
‘user_id’ => $user_id,
])
->groupBy(‘uuid’)
->all();
1
2
3
4
5
6
static::find()
->select([‘uuid’])
->where([
‘user_id’ => $user_id,
])
->distinct()
->count();
1
2
3
4
5
6
7
static::find()->where([
‘user_id’ => $user_id,
])->count(‘distinct uuid’);
1
2
3
事务
t r a n s a c t i o n = Y i i : : transaction = Yii:: transaction=Yii::app->db->beginTransaction();
try {
//… SQL executions
$transaction->commit();
} catch (Exception $e) {
$transaction->rollBack();
}
1
2
3
4
5
6
7
关于事务:

Yii::$app->db->transaction(function() {
o r d e r = n e w O r d e r ( order = new Order( order=newOrder(customer);
$order->save();
o r d e r − > a d d I t e m s ( order->addItems( order>addItems(items);
});

// 这相当于下列冗长的代码:

t r a n s a c t i o n = Y i i : : transaction = Yii:: transaction=Yii::app->db->beginTransaction();
try {
o r d e r = n e w O r d e r ( order = new Order( order=newOrder(customer);
$order->save();
o r d e r − > a d d I t e m s ( order->addItems( order>addItems(items);
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
查找 auth_times 表 type=1 并且 不存在 auth_item 表里面的数据
// AuthItem.php 关键是 onCondition 方法
public function getAuthTimes()
{
return $this->hasOne(AuthTimes::className(), [‘name’ => ‘name’, ])->onCondition([AuthTimes::tableName() . ‘.type’ => 1]);
}

// AuthTimes.php 文件
// …
AuthItem::find()->joinWith(‘authTimes’)->where([self::tableName() . ‘.name’ => null])->all();
1
2
3
4
5
6
7
8
9
生成SQL:

SELECT auth_item.* FROM auth_item LEFT JOIN auth_times ON auth_item.name = auth_times.name AND auth_times.type = 1 WHERE auth_times.name IS NULL
1
执行SQL查询并缓存结果
s t y l e I d = Y i i : : styleId = Yii:: styleId=Yii::app->request->get(‘style’);
c o l l e c t i o n = Y i i : : collection = Yii:: collection=Yii::app->db->cache(function( d b ) u s e ( db) use( db)use(styleId){
return Collection::findOne([‘style_id’=>$styleId]);
}, self::SECONDS_IN_MINITUE * 10);
1
2
3
4
批量插入数据 
第一种方法
m o d e l = n e w U s e r ( ) ; f o r e a c h ( model = new User(); foreach( model=newUser();foreach(data as $attributes)
{
$_model = clone $model;
m o d e l − > s e t A t t r i b u t e s ( _model->setAttributes( model>setAttributes(attributes);
$_model->save();
}
1
2
3
4
5
6
7
第二种方法

m o d e l = n e w U s e r ( ) ; f o r e a c h ( model = new User(); foreach( model=newUser();foreach(data as $attributes)
{
$model->isNewRecord = true;
m o d e l − > s e t A t t r i b u t e s ( model->setAttributes( model>setAttributes(attributes);
$model->save() && $model->id = 0;
}
1
2
3
4
5
6
7
URL
假设我们当前页面的访问地址是:http://localhost/public/index.php?r=news&id=1

获取url中的host信息:

http://localhost

Yii:: a p p − > r e q u e s t − > g e t H o s t I n f o ( ) 12 获 取 u r l 中 的 路 径 信 息 ( 不 包 含 h o s t 和 参 数 ) : Y i i : : app->request->getHostInfo() 1 2 获取url中的路径信息(不包含host和参数): Yii:: app>request>getHostInfo()12urlhostYii::app->request->getPathInfo()
1
获取不包含host信息的url(含参数):

/public/index.php?r=news&id=1

Yii:: a p p − > r e q u e s t − > u r l 或 者 Y i i : : app->request->url 或者 Yii:: app>request>urlYii::app->request->requestUri
1
2
3
4
获取完整url(含host以及参数):
Yii::$app->request->getHostInfo() . Yii::app()->request->url
1
只想获取url中的参数部分:

r=news&id=1

Yii:: a p p − > g e t R e q u e s t ( ) − > q u e r y S t r i n g 12 获 取 某 个 参 数 的 值 , 比 如 i d Y i i : : app->getRequest()->queryString 1 2 获取某个参数的值,比如id Yii:: app>getRequest()>queryString12idYii::app->getRequest()->getQuery(‘id’); //get parameter ‘id’
1
获取(除域名外的)首页地址

/public/index.php

Yii:: a p p − > u s e r − > r e t u r n U r l ; 12 获 取 R e f e r e r Y i i : : app->user->returnUrl; 1 2 获取Referer Yii:: app>user>returnUrl;12RefererYii::app->request->headers[‘Referer’]
或者
Yii::$app->getRequest()->getReferrer()
1
2
3
前端显示
英文不换行问题
当GridView和DetailView列表中的某一条内容为连续的英文或数字(比如网站链接等)时,该内容会不换行,导致该列宽度被顶的特别长,甚至超出div的宽度。

在全局Css中添加以下样式:

word-break:break-all; //只对英文起作用,以字母作为换行依据

eg:

html,
body {
height: 100%;
font-family: “Microsoft YaHei”;
word-break: break-all;
}
1
2
3
4
5
6
Yii给必填项加星
css:
div.required label:after {
content: " *";
color: red;
}
1
2
3
4
5
控制器获取当前Module name,Controller name和action name
#在控制器里面使用
$this->module->id;
$this->id;
$this->action->id;

#其他位置使用
\Yii::KaTeX parse error: Expected 'EOF', got '\Yii' at position 30: …r->module->id; \̲Y̲i̲i̲::app->controller->id;
\Yii::KaTeX parse error: Expected 'EOF', got '\Logger' at position 68: … 日志 use yii\log\̲L̲o̲g̲g̲e̲r̲; \Yii::getLogg…app->request->rawBody;
1
有两种方式获取查询出来的 name 为数组的集合 [name1, name2, name3]:
方式一:

return \yii\helpers\ArrayHelper::getColumn(User::find()->all(), ‘name’);
1
方式二:

return User::find()->select(‘name’)->asArray()->column();
1
防止 SQL 和 Script 注入:
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;

echo Html::encode( v i e w h e l l o s t r ) / / 可 以 原 样 显 示 < s c r i p t > < / s c r i p t > 代 码 e c h o H t m l P u r i f i e r : : p r o c e s s ( view_hello_str) //可以原样显示<script></script>代码 echo HtmlPurifier::process( viewhellostr)//<script></script>echoHtmlPurifier::process(view_hello_str) //可以过滤掉代码
1
2
3
4
5
打印对象数组数据:
// 引用命名空间
use yii\helpers\VarDumper;

// 使用
VarDumper::dump($var);

// 使用2 第二个参数是数组的深度 第三个参数是是否显示代码高亮(默认不显示)
VarDumper::dump( v a r , 10 , t r u e ) ; d i e ; 12345678 r e s t f u l 获 取 G E T 和 P O S T 过 来 的 数 据 ( 得 到 结 果 是 数 组 ) : / / p o s t Y i i : : var, 10 ,true);die; 1 2 3 4 5 6 7 8 restful 获取 GET 和 POST 过来的数据(得到结果是数组): // post Yii:: var,10,true);die;12345678restfulGETPOST//postYii::app->request->bodyParams

// get
Yii::KaTeX parse error: Expected 'EOF', got '\yii' at position 72: …Html::a("链接1", \̲y̲i̲i̲\helpers\Url::t…app->urlManager->createUrl([‘mysql/chart’, ‘id’ => 43,‘time_interval’ => ‘1800’, ‘end’=>‘0’]));
1
2
一个控制器调用其他控制器action的方法:
Yii::$app->runAction(‘new_controller/new_action’, p a r a m s ) ; / / 或 者 r e t u r n ( n e w S e c o n d C o n t r o l l e r ( ′ s e c o n d ′ , Y i i : : params); // 或者 return (new SecondController('second', Yii:: params);//return(newSecondController(second,Yii::app->module))->runAction(‘index’, d a t a ) ; 123 点 击 下 载 文 件 a c t i o n p u b l i c f u n c t i o n a c t i o n D o w n l o a d ( data); 1 2 3 点击下载文件 action public function actionDownload( data);123actionpublicfunctionactionDownload(id)
{
$model = t h i s − > f i n d M o d e l ( this->findModel( this>findModel(id);

if ($model) {
    // do something
}
return \Yii::$app->response->setDownloadHeaders($model->downurl);

}
1
2
3
4
5
6
7
8
9
10
发送邮件 
a.config/config.php中的components配置
‘mailer’ => [
‘class’ => ‘yii\swiftmailer\Mailer’,
‘useFileTransport’ => false,
‘transport’ => [
‘class’ => ‘Swift_SmtpTransport’,
‘host’ => ‘smtp.gmail.com’,
‘username’ => ‘[email protected]’,
‘password’ => ‘password12345678’,
‘port’ => 587,//or 25/587
‘encryption’ => ‘tls’,//tls or ssl
]
],
1
2
3
4
5
6
7
8
9
10
11
12
b.使用

Yii:: a p p − > m a i l e r − > c o m p o s e ( ) − > s e t F r o m ( [ ′ a d m i n @ g m a i l . c o m ′ = > Y i i : : app->mailer->compose() ->setFrom(['[email protected]' => Yii:: app>mailer>compose()>setFrom([admin@gmail.com=>Yii::app->name])
->setTo(‘[email protected]’)
->setSubject(‘test subject’)
->setTextBody(‘test body’)
->send();
1
2
3
4
5
6
修改登陆状态超时时间(到期后自动退出登陆) config/web.php中的components
‘user’ => [ 
‘class’=>’yii\web\User’, 
‘identityClass’ => ‘common\models\User’, 
‘loginUrl’=>[‘/user/sign-in/login’], 
‘authTimeout’ => 1800,//登陆有效时间 
‘as afterLogin’ => ‘common\behaviors\LoginTimestampBehavior’ 
],

修改返回的数据格式(详见Response::FORMAT_XXXX)
$result = array(‘code’ => $code, ‘msg’ => $msg, ‘data’ => $data);
c a l l b a c k = Y i i : : callback = Yii:: callback=Yii::app->request->get(‘callback’,null);

$format = c a l l b a c k ? R e s p o n s e : : F O R M A T J S O N P : R e s p o n s e : : F O R M A T J S O N ; Y i i : : callback ? Response::FORMAT_JSONP : Response::FORMAT_JSON; Yii:: callback?Response::FORMATJSONP:Response::FORMATJSON;Yii::app->response->format = $format;

if($callback){
return array(
‘callback’ => $callback,
‘data’ => $result
);
}
return $result;
1
2
3
4
5
6
7
8
9
10
11
12
13
场景: 数据库有user表有个avatar_path字段用来保存用户头像路径
需求: 头像url需要通过域名http://b.com/作为基本url

目标: 提高代码复用

此处http://b.com/可以做成一个配置
1
示例:

User.php

class User extends \yii\db\ActiveRecord
{

public function extraFields()
{
$fields = parent::extraFields();

    $fields['avatar_url'] = function () {
        return empty($this->avatar_path) ? '可以设置一个默认的头像地址' : 'http://b.com/' . $this->avatar_path;
    };

    return $fields;
}
...

}

ExampleController.php

class ExampleController extends \yii\web\Controller
{
public function actionIndex()
{
$userModel = User::find()->one();
$userData = $userModel->toArray([], [‘avatar_url’]);

    echo $userData['avatar_url']; // 输出内容: http://b.com/头像路径
}

}
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
Yii2-GridView 中让关联字段带搜索和排序功能 
情境要求: 
要在订单(Order)视图的gridview中显示出客户(Customer)姓名,并使其具有与其它字段相同的排序和搜索功能。
数据库结构 
订单表order含有字段customer_id 与 客户表customer的id字段关联

首先确保在Order Model中包含以下代码:

public function getCustomer()
{
return $this->hasOne(Customer::className(), [‘id’ => ‘customer_id’]);
}
1
2
3
4
用gii会自动生成此代码;

第一步: 
在OrderSearch添加一个$customer_name变量

class OrderSearch extends Order
{
public $customer_name; //<=====就是加在这里
}
1
2
3
4
第二步: 
修改OrderSearch中的search函数

public function search($params)
{
$query = Order::find();
$query->joinWith([‘customer’]);<=====加入这句
$dataProvider = new ActiveDataProvider([
‘query’ => $query,
]);

$dataProvider->setSort([
    'attributes' => [
        /* 其它字段不要动 */    
        /*  下面这段是加入的 */
        /*=============*/
        'customer_name' => [
            'asc' => ['customer.customer_name' => SORT_ASC],
            'desc' => ['customer.customer_name' => SORT_DESC],
            'label' => 'Customer Name'
        ],
        /*=============*/
    ]
]); 

if (!($this->load($params) && $this->validate())) {
    return $dataProvider;
}

$query->andFilterWhere([
    'id' => $this->id,
    'user_id' => $this->user_id,
    'customer_id' => $this->customer_id,
    'order_time' => $this->order_time,
    'pay_time' => $this->pay_time,
]);

$query->andFilterWhere(['like', 'status', $this->status]);
$query->andFilterWhere(['like', 'customer.customer_name', $this->customer_name]) ;//<=====加入这句

return $dataProvider;

}
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
第三步: 
修改order/index视图的gridview

$dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'id', 'customer_id', 'status', ['label'=>'客户', 'attribute' => 'customer_name', 'value' => 'customer.customer_name' ],//<=====加入这句 ['class' => 'yii\grid\ActionColumn'], ], ]); ?>

1
2
3
4
5
6
7
8
9
10
11
12
格式化输出Json字符串
[
‘attribute’ => ‘source’,
‘format’ => ‘raw’,
‘value’ => function (KaTeX parse error: Expected '}', got 'EOF' at end of input: …e(Json::decode(model->source), JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT) . ‘’;

}

],
1
2
3
4
5
6
7
8
邮件发送
注意,使用邮件发送前发送邮件的邮箱必须开启 POP3/SMTP/IMAP 服务,请在邮箱账号设置中自行开启

components 配置(以126邮箱为例):
‘mailer’ => [
‘class’ => ‘yii\swiftmailer\Mailer’,
//‘viewPath’ => ‘@common/mail’,
// 默认把所有邮件发送到一个文件里,若需要发送真邮件,你需要把userFileTransport设置为false,并且添加邮件的配置
‘useFileTransport’ => false,
‘transport’ => [
‘class’ => ‘Swift_SmtpTransport’,
‘host’ => ‘smtp.126.com’,
‘username’ => ‘[email protected]’,
‘password’ => ‘’
],
‘messageConfig’=>[
‘charset’ => ‘UTF-8’,
‘from’=>[ ‘[email protected]’ => ‘发件人名称’]
],
],
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
发送邮件
m a i l = Y i i : : mail= Yii:: mail=Yii::app->mailer->compose()
->setTo(‘[email protected]’)
->setSubject(‘邮件标题’)
->setHtmlBody(‘邮件内容’);

if($mail->send()) {
echo ‘发送成功’;
} else {
echo ‘发送失败’;
}


本文来自 写回 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/weixin_41282397/article/details/80838864?utm_source=copy

你可能感兴趣的:(yii2)