当前位置: 首页 > 后端技术 > PHP

YII2项目的几个常用技能知识总结

时间:2023-03-30 01:43:03 PHP

1.获取AR执行的原生SQL语句,打印可变数据,不记录$query=User::find()->select(['username'])->where(['id'=>[1,2,3,4])//在YII2中获取AR原始sql$commandQuery=clone$query;echo$commandQuery->createCommand()->getRawSql();$users=$query->all();打印变量数据可以这样写://referencenamespaceuseyii\helpers\VarDumper;//useVarDumper::dump($var);//use2第二个参数是数组的深度第三个参数是是否显示代码高亮显示(默认不显示)VarDumper::dump($var,10,true);2、从数据库的二维数组返回一维数组,配合规则校验规则,实现分类数据过滤。普通返回表记录的二维数组Member::find()->select('userid')->asArray()->all();Array([0]=>Array([userid]=>1)[1]=>Array([userid]=>2)[2]=>Array([userid]=>3))返回一维字段数组Member::find()->select('userid')->asArray()->列();或者:\yii\helpers\ArrayHelper::getColumn(Member::find()->all(),'userid')Array([0]=>1[1]=>2[2]=>3)返回一维数组,用校验规则校验数据的正确性。比如categorycatid正确的划分只有1-4,但是在devTools中打开,修改catid为5,提交也会去数据库,此时会校验规则,规则如下如下:['catid','in','range'=>category::find()->select('id')->asArray()->column()],当然这个也可以传如下这样写,一样的:['catid','in','range'=>\yii\helpers\ArrayHelper::getColumn(category::find()->all(),'catid')],像这样你可以过滤错误分类的数据!3.友情时间表示方式之前一直使用自定义的友情时间函数。前几天发现万能的YII提供了友好的时间访问。代码如下:Yii::$app->formatter->asRelativeTime('1447565922');//2小时前4.使用不同的响应类型或自定义响应类型的有效格式:FORMAT_RAWFORMAT_HTMLFORMAT_JSONFORMAT_JSONPFORMAT_XMLJSONresponsepublicfunctionactionIndex(){\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"]}自定义响应格式让我们创建自定义响应格式。示例做一些有趣而疯狂的事情,我返回一个PHP数组。首先,我们需要格式化程序本身。创建组件/PhpArrayFormatter.php:getHeaders()->set('Content-Type','text/php;charset=UTF-8');如果($response->data!==null){$response->content="data)。";\n";}}}组件配置:return[//...'components'=>[//...'response'=>['formatters'=>['php'=>'app\components\PhpArrayFormatter',],],],];现在可以使用了。在controllers/SiteController中创建一个新方法actionTest:publicfunctionactionTest(){Yii::$app->response->format='php';return['hello'=>'world!',];}返回如下:'world!',];5.AR存储前,重写模型中的behaviors方法,实现优雅的存储方式。如下:publicfunctionbehaviors(){return['timestamp'=>['class'=>TimestampBehavior::className(),'attributes'=>[ActiveRecord::EVENT_BEFORE_INSERT=>'creation_time',ActiveRecord::EVENT_BEFORE_UPDATE=>'update_time',],'value'=>function(){返回日期('U');//unixtimestamp},],];}6.除了配置组件记录不同级别的日志外,还可以自定义Somewhere记录LOG日志useyii\log\Logger;\Yii::getLogger()->log('用户已创建',Logger::LEVEL_INFO);7.ActiveForm类不允许生成label标签//方法一,通过ActiveForm类$form->field($model,'fieldname')->passwordInput(['maxlength'=>true])->label(false)?>//方法二、通过HTML类Html::activeInput($type,$model,'fieldname')Yii2为必填项添加星标,样式如下:div.requiredlabel:after{content:"*";color:red;}8.Yii2获取接口传过来的信息JSON数据:get和post数据很容易接收,那么接收json数据呢?!没关系,看这里:Yii::$app->request->rawBody;9、座机和手机号码必须填写:publicfunctionrules(){return[[['telephone','mobile'],function($attribute,$param){//至少一个if(empty($this->telephone)&&empty($this->mobile)){$this->addError($attribute,'电话/手机必须至少填写一个');}},'skipOnEmpty'=>false],];}10.where多条件查询示例://and复杂示例:$time=time();Member::find()->where(['and',['userid'=>1,'company'=>'测试公司'],['>','addtime',$time]]);//SELECT*FROMmemberWHERE((userid=1)AND(company='testingcompany'))AND(addtime>1447587486)//andandor组合示例:$query=Member::find()->where(['and',['>','userid',2],['or',['company'=>'深圳市新民家具有限公司'],['address'=>'深圳']]]);//SELECT*FROMmemberWHERE(userid>2)AND((company='深圳市新民家具有限公司')OR(address='深圳'))11.关于事务:优雅的写法Yii::$app->db->transaction(function(){$order=新订单($客户);$订单->保存();});这等同于以下冗长的代码:$transaction=Yii::$app->db->beginTransaction();try{$order=newOrder($customer);$order->save();$transaction->commit();}catch(\Exception$e){$transactionn->rollBack();throw$e;}12.rest风格API获取客户端提交的get和post数组//postYii::$app->request->bodyParams//getYii::$app->请求->查询参数;13、一个控制器调用其他控制器动作的方法:方法一:经典的重写动作方法publicfunctionactions(){return['error'=>['class'=>'yii\web\ErrorAction',],'captcha'=>['class'=>'yii\captcha\CaptchaAction','fixedVerifyCode'=>YII_ENV_TEST?'testme':null,],];}actions继承自yii\base\Actions类,重写了父类的run方法。方法二:站点控制器如下,访问MemberController控制器下的index方法。classSiteControllerextendsController{publicfunctionactionIndex(){Yii::$app->runAction('member/index',['param'=>'123']);}}MemberController控制器如下:classMemberControllerextendsController{publicfunctionactionIndex($param='456'){echo"secondController".$param;}}访问:http://www.yii.dev/site/index...输出:secondController12314,点击下载,例如下载AndroidAPK文件。publicfunctionactionDownload(){return\Yii::$app->response->setDownloadHeaders("http://xxx.com/apk/com.trade.activity.3.0.8.apk");//返回\Yii::$app->response->sendFile("./com.trade.activity.3.0.8.apk");}15.YII模块IP白名单设置,增加安全性$config'modules'=['class'=>'yii\gii\Module','allowedIPs'=>['127.0.0.1','::1','10.10.1.*'],];$config'modules'=['class'=>'yii\debug\Module','allowedIPs'=>['127.0.0.1','::1','192.168.0.*','192.168.33.1'],];16.防止SQL和脚本注入($view_hello_str)//可以过滤掉代码17.验证某个ID值是否存在//我之前一直在使用$model->findOne($id);exists()方法,保存资源,有吗!公共函数validateAttribute($model,$attribute){$value=$model->$attribute;如果(!Status::find()->where(['id'=>$value])->exists()){$model->addError($attribute,$this->message);}}18、批量查询,比如查询循环10000条数据,一次获取10000条内存会有压力。通过批量查询,如果每次获取1000条,那么内存永远只占用1000条数量。foreach(Member::find()->batch(1000)as$value){//dosomething//print_r(count($value));}19.关于CSRF验证方法一:非必要关闭Csrf不推荐publicfunctioninit(){$this->enableCsrfValidation=false;}方法二:普通提交,在表单中添加一个隐藏字段request->csrfToken?>">方法三:ajax异步提交,添加_csrf字段varcsrfToken=$('meta[name="csrf-token"]').attr("content");$.ajax({type:'POST',url:url,data:{_csrf:csrfToken},success:成功,dataType:dataType});20.YII命令行生成的数据库文件自动列出可用的migrate文件phpyiimigrate从vendor/callmez/wechat/migrations目录生成数据表phpyiimigrate--migrationPath=@callmez/wechat/migrations从当前应用初始化数据/migrations/db1todb1tablephpyiimigrate--migrationPath=@app/migrations/db1--db=db121.Associatedquery//客户表Model:CustomerModel//订单表Model:OrdersModel//国家表Model:CountrysModel//首先建立表间关系//在CustomerModel类中添加与订单的关系CustomerModelextends\yii\db\ActiveRecord{...publicfunctiongetOrders(){//客户和订单是一对多的关系,所以使用有Many//这里OrdersModel在CustomerModel的最顶层,别忘了加上对应的命名空间//id对应OrdersModel的id字段,order_id对应CustomerModel的order_id字段return$this->hasMany(OrdersModel::className(),['id'=>'order_id']);}publicfunctiongetCountry(){//客户和国家是一对一的关系所以使用hasOnereturn$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();22、在yii2中关闭debug并返回$this->redirect($url);无法跳转,服务器报500错误问题分析:1.必须返回make$this->redirect($url);立即跳转,不执行后续代码;2.响应的http状态码在redirect()中指定,默认为302;3、$this->redirect($url)执行时,不管加returnfalse还是returntrue都没用,还是继续执行代码。使用header("Location:$url");exit;可以解决这个问题,但是,这不是yii2的逻辑,还不完美。解决方法:【本文由php_sir的博客http://blog.sina.com.cn/phpsi撰写...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只是代码返回。