三默网为您带来有关“Yii2 常用操作总结”的文章内容,供您阅读参考。
Yii2 常用操作总结
2023-01-21 19:16:21
时区配置
#common\config\main.php
return [
'timeZone' => 'Asia/Shanghai',
]
a标签
<?= Html::a('Delete',
['delete', 'id' =>$model->id],
['class' => 'btn btn-danger',
'data' => ['confirm' => 'Are you sure you want to delete this item?','method' => 'post',
],
]) ?>
#第一个参数是超链接的标题。它不会被转码,所以如果是用户输入数据, 你需要使用 Html::encode() 方法进行转码。第二个参数是 <a 标签的 href 属性的值。 关于该参数能够接受的更详细的数据值,请参阅 Url::to()。 第三个参数是标签的属性数组。
#这个和上面比较看可能更好理解
<?= Html::a('已授权列表', ['cancel-grant', 'id' => yii::$app->request->get('id'),'rType'=>yii::$app->request->get('rType')], [
'class' => 'btn btn-success','style' => 'margin-bottom:10px;'
]) ?>
展示图片
[
'attribute' => 'cover',
'format' => 'raw',
'value' => function($model){
return Html::img("{$model->cover}",['alt' => '缩略图', 'width' => 80]);
}
],
获取最后一次插入的id
Yii::app()->db->getLastInsertId();
返回字段的一位数组
Member::find()->select('userid')->asArray()->column();
# 或者:
\yii\helpers\ArrayHelper::getColumn(Member::find()->all(), 'userid')
rules验证
['catid', 'in', 'range' => category::find()->select('id')->asArray()->column()],
#当然,这个也可以通过下面这样子写,一样的:
['catid', 'in', 'range' => \yii\helpers\ArrayHelper::getColumn(category::find()->all(), 'catid')],
友好时间访问
Yii::$app->formatter->asRelativeTime($value, $referenceTime = null)
使用不同的响应类型或者自定义响应类型
#有效的格式:
FORMAT_RAW
FORMAT_HTML
FORMAT_JSON
FORMAT_JSONP
FORMAT_XML
#JSON响应
public function actionIndex()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$items = ['some', 'array', 'of', 'data' => ['associative', 'array']];
return $items;
}
#返回:
{
"0": "some",
"1": "array",
"2": "of",
"data": ["associative", "array"]
}
组件配置
return [
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'redis' => [
'class' => 'yii\redis\Connection',
'hostname' => '127.0.0.1',
'port' => 6379,
'database' => 0,
'password' => '!chxlqqx!',
],
],
];
#在项目中通过yii::$app->redis调用
AR入库前时间通过在模型重写behaviors方法实现优雅入库方式。
如下:
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'creation_time',
ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time',
],
'value' => function() { return date('U'); // unix timestamp },
],
];
}
除配置组件记录不同级别日志外,也可以自定义在某个地方记录LOG日志
use yii\log\Logger;
\Yii::getLogger()->log('User has been created', Logger::LEVEL_INFO);
Yii2 获取接口传过来的 JSON 数据:
接收get和post的数据很容易,那么接收json数据呢?!没关系,看这里:
Yii::$app->request->rawBody;
座机和手机号码必须填写一个:
public function rules()
{
return [
[['telephone', 'mobile'], function ($attribute, $param) {//至少要一个
if (empty($this->telephone) && empty($this->mobile)) {
$this->addError($attribute, 'telephone/mobile至少要填一个');
}
}, 'skipOnEmpty' => false],
];
}
where多条件查询示例:
//and复杂示例:
$time = time();
Member::find()->where(['and', ['userid' => 1, 'company' =>'测试公司'], ['>', 'addtime', $time]]);
//SELECT * FROM `member` WHERE ((`userid`=1) AND (`company`='测试公司')) AND (`addtime` > 1447587486)
//and和or组合示例:
$query = Member::find()->where(['and', ['>','userid',2], ['or', ['company' => '深圳市新民家具有限公司'], ['address' => '深圳']]]);
//SELECT * FROM `member` WHERE (`userid` > 2) AND ((`company`='深圳市新民家具有限公司') OR (`address`='深圳'))
关于事务:
优雅的写法
Yii::$app->db->transaction(function() {
$order = new Order($customer);
$order->save();
});
这相当于下列冗长的代码:
$transaction = Yii::$app->db->beginTransaction();
try {
$order = new Order($customer);
$order->save();
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
rest风格API获取客户端提交的get和post的数组
// post
Yii::$app->request->bodyParams
// get
Yii::$app->request->queryParams;
一个控制器调用其他控制器action的方法:
方法一:
是经典的重写actions方法
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
actions继承yii\base\Actions类,并重写父类的run方法。
方法二:
site控制器如下,访问MemberController控制器下面的index方法。
class SiteController extends Controller
{
public function actionIndex(){
Yii::$app->runAction('member/index', ['param'=>'123']);
}
}
MemberController控制器如下:
class MemberController extends Controller
{
public function actionIndex($param = '456'){
echo "second Controller".$param;
}
}
访问:http://www.yii.dev/site/index.html
输出:second Controller123
点击下载,如下载安卓APK文件。
public function actionDownload(){
return \Yii::$app->response->setDownloadHeaders("http://xxx.com/apk/com.trade.activity.3.0.8.apk");
//return \Yii::$app->response->sendFile("./com.trade.activity.3.0.8.apk");
}
YII模块IP白名单设置,增加安全性
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1','10.10.1.*'],
];
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.33.1'],
];
防止 SQL 和 Script 注入
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;
echo Html::encode($view_hello_str) //可以原样显示<script></script>代码
echo HtmlPurifier::process($view_hello_str) //可以过滤掉<script></script>代码
验证某个ID值是否存在
//之前一直用$model->findOne($id);exists()方法,资源节约,有没有?!
public function validateAttribute($model, $attribute)
{
$value = $model->$attribute;
if (!Status::find()->where(['id' => $value])->exists()) {
$model->addError($attribute, $this->message);
}
}
批量查询
#如查询并循环10000条数据。一次性拿1万条内存会有压力,通过批量查询,每次拿1000条,那么内存始终只有1000条的占有量。
foreach(Member::find()->batch(1000) as $value){
//do something
//print_r(count($value));
}
关于CSRF验证
方法一:关闭Csrf,除非必要,否则不推荐
public function init(){
$this->enableCsrfValidation = false;
}
方法二:普通提交,form表单中加入隐藏域
<input name="_csrf" type="hidden" id="_csrf" value="<?= Yii::$app->request->csrfToken ?>">
方法三:ajax异步提交,加入_csrf字段
var csrfToken = $('meta[name="csrf-token"]').attr("content");
$.ajax({
type: 'POST',
url: url,
data: {_csrf:csrfToken},
success: success,
dataType: dataType
});
YII命令行生成数据库文件
自动列出可用的migrate文件
php yii migrate
从vendor/callmez/wechat/migrations目录下生成数据表
php yii migrate [email protected]/wechat/migrations
从当前应用/migrations/db1下初始化数据到db1表
php yii migrate [email protected]/migrations/db1 --db=db1
关联查询
//客户表Model:CustomerModel
//订单表Model:OrdersModel
//国家表Model:CountrysModel
//首先要建立表与表之间的关系
//在CustomerModel中添加与订单的关系
Class CustomerModel extends \yii\db\ActiveRecord
{
...
public function getOrders()
{
//客户和订单是一对多的关系所以用hasMany
//此处OrdersModel在CustomerModel顶部别忘了加对应的命名空间
//id对应的是OrdersModel的id字段,order_id对应CustomerModel的order_id字段
return $this->hasMany(OrdersModel::className(), ['id'=>'order_id']);
}
public function getCountry()
{
//客户和国家是一对一的关系所以用hasOne
return $this->hasOne(CountrysModel::className(), ['id'=>'Country_id']);
}
....
}
// 查询客户与他们的订单和国家
CustomerModel::find()->with('orders', 'country')->all();
// 查询客户与他们的订单和订单的发货地址
CustomerModel::find()->with('orders.address')->all();
// 查询客户与他们的国家和状态为1的订单
CustomerModel::find()->with([
'orders' => function ($query) {
$query->andWhere('status = 1');
},
'country',
])->all();
yii2中关闭debug后return url);不能跳转,服务器报500错误
问题分析:
1.必须 return 才能让$this->redirect($url);立马跳转, 而不执行后续代码;
2.redirect() 中指定了响应的 http status code,默认是302;
3.当执行$this->redirect($url)时,不管是否在后面加return false 、return true都没有用,还是继续执行完代码。使用header("Location:$url");exit;可以解决此问题,但是,这不是yii2的逻辑,并不完美。
解决办法:
【本文由php_sir的博客 http://blog.sina.com.cn/phpsir原创,未经授权禁止转载】
1.在正常情况下,使用 return $this->redirect($url);
2.在解决方案1不生效时,用$this->redirect($url);Yii::$app->response->send();
3.在解决方案2不生效时,用$this->redirect($url);Yii::$app->end();
总结:
用Yii::$app->end();、Yii::$app->response->send();不管在actionXXX还是init方法都能终止代码,而return只能在action终止代码,是因为在init()里仅仅是代码的执行,return只是代码返回。
Yii2 修改导航栏
#后台
#views/layouts/main.php
<?php
NavBar::begin([
'brandLabel' => Yii::$app->name,
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar-inverse navbar-fixed-top',
],
]);
$menuItems = [
['label' => '小说', 'url' => ['/book/index']],
['label' => '漫画', 'url' => ['/comic/index']],
['label' => '渠道商', 'url' => ['/channel/index']],
[
'label' => '队列',
'items' => [
['label' => '状态', 'url' => '/queue/index'],
['label' => '任务添加', 'url' => '/queue/add'],
],
],
];
修改项目名称,以及修改项目为中文
return [
'id' => 'app-backend',
'name' => '棉花糖',#此处修改项目名称
'language' => 'zh-CN',#修改项目为中文
...
]
修改searchModel 添加查询条件
public function search($params)
{
$query = Book::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'sourceId' => $this->sourceId,
'status' => $this->status,
'finished' => $this->finished,
'chapterCount' => $this->chapterCount,
'lastCid' => $this->lastCid,
'gender' => $this->gender,
'mainCate' => $this->mainCate,
'subCate' => $this->subCate,
'score' => $this->score,
'words' => $this->words,
'orgCreated' => $this->orgCreated,
'orgUpdate' => $this->orgUpdate,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]);
$query->andFilterWhere(['like', 'orgId', $this->orgId])
->andFilterWhere(['like', 'title', $this->title])
->andFilterWhere(['like', 'author', $this->author])
->andFilterWhere(['like', 'cover', $this->cover])
->andFilterWhere(['like', 'tags', $this->tags])
->andFilterWhere(['like', 'intro', $this->intro])
->andFilterWhere(['like', 'copyright', $this->copyright]);
if($this->cancelId){
$query->andFilterWhere(['in','id',$this->cancelId]);
}
if($this->grantedId){
$query->andFilterWhere(['not in', 'id', $this->grantedId]);
}
return $dataProvider;
}
控制器向公共模板发送数据
#方法一:
#控制器中:
Yii::$app->view->params['name'] = $name;
#视图中
$this->params['name']
#方法二
#控制器
$this->name = $name;
#视图中
$this->context->name;
获取yii版本
Yii::getVersion()