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

YII2项目常用技能知识总结

时间:2023-03-30 01:28:01 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_XMLJSON响应publicfunctionactionIndex(){\Yii::$app->response->format=\yii\web\响应::FORMAT_JSON;$items=['some','array','of','data'=>['associative','array']];返回$项目;}返回:{"0":"some","1":"array","2":"of","data":["associative","array"]}自定义响应格式让我们创建自定义响应格式。示例做一些有趣而疯狂的事情,我返回一个PHP数组。首先,我们需要格式化程序本身。创建components/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';返回['你好'=>'世界!',];}返回如下:'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{内容:"*";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'=>'testcompany'],['>','addtime',$time]]);//SELECT*FROM`member`WHERE((`userid`=1)AND(`company`='testcompany'))AND(`addtime`>1447587486)//andandor组合示例:$query=Member::find()->where(['and',['>','userid',2],['or',['company'=>'深圳市新民家具有限公司'],['address'=>'深圳']]]);//SELECT*FROM`member`WHERE(`userid`>2)AND((`company`='深圳市新民家具有限公司')OR(`address`='深圳'))11.关于交易:优雅的方式编写Yii::$app->db->transaction(function(){$order=newOrder($customer);$order->save();});这等同于以下冗长的代码:$transaction=Yii::$app->db->beginTransaction();尝试{$订单=新订单($客户);$订单->保存();$transaction->commit();}catch(\Exception$e){$transaction->rollBack();throw$e;}12.reststyleAPI获取客户端提交的get和post数组//postYii::$app->request->bodyParams//getYii::$app->request->queryParams;13、一个controller调用其他controller的action方法:方法一:经典的重写action方法publicfunctionactions(){return['error'=>['class'=>'yii\web\ErrorAction',],'captcha'=>['class'=>'yii\captcha\CaptchaAction','fixedVerifyCode'=>YII_ENV_TEST?'testme':null,],];}actions继承yiibaseActions类,重写父类的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.html输出:第二个Controller12314,点击下载,比如下载AndroidAPK文件。publicfunctionactionDownload(){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");}15、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'],];16.防止SQL和Script注入useyii\helpers\Html;useyii\helpers\HtmlPurifier;echoHtml::encode($view_hello_str)//可以显示CodeechoHtmlPurifier::process($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(){//客户和订单的关系是一对多的,所以用hasMany//这里,OrdersModel在CustomerModel的最顶层,别忘了加上对应的命名空间//id对应idOrdersModel字段,order_id对应CustomerModel字段的order_idreturn$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');},'国家',])->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的逻辑,还不完美。解决方法: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只是代码返回。