首页
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
Search
1
NAS的简单介绍
707 阅读
2
网站环境一键部署工具推荐
504 阅读
3
tp5-模型数据处理
393 阅读
4
第20200225期-电脑壁纸-P10
350 阅读
5
PHP常用系统函数速查表
340 阅读
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
登录
Search
标签搜索
ThinkPHP
MySQL
Laravel
PHP
API
GIT
Windows10
markdown
Web
跨域
ajax
小程序
壁纸
Linux
jsonp
try
异常
Dcat
UEFI
win10
phpfunny
累计撰写
104
篇文章
累计收到
24
条评论
首页
栏目
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
页面
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
搜索到
22
篇与
的结果
2020-07-13
tp5一对一关联
关联查找hasOne主表拥有副表的资源在主表模型层使用hasOne('关联模型名','外键名','主键名',['模型别名定义'],'join类型');直接用主表名::get('id值');belongsTo相对关联在副表模型层使用belongsTo('关联模型名','外键名','关联表主键名',['模型别名定义'],'join类型');直接用副表名::get('id值');关联新增使用正规封装//控制器使用封装模型 $data=[ 'user_name'=>'zhuoxiang123','password'=>md5(123), 'pic_url'=>'aaaa','thumb_url'=>'bbb', ]; $obj=new Member(); $result=$obj->add($data); //模型 public function add($data){ try{ //开启事务 $this->startTrans(); $this->isUpdate(false)->allowField(true)->save($data); $this->logo()->save(['pic_url'=>$data['pic_url'],'thumb_url'=>$data['thumb_url']]); $this->commit(); return true; }catch(Exception $e){ $this->error=$e->getMessage(); $this->rollback(); return false; } }hasOne形式//控制器直接使用(不规范,严谨在项目中使用) $obj=Member::create(['user_name'=>'zhuo','password'=>md5(123)]); $obj->logo()->save(['pic_url'=>'aaa','thumb_url'=>'bbb']);//logo是从表中的方法关联自动写入的定义,需要配合hasOne中的定义方法名//添加主表Member数据 $obj1=New Member(); $obj1->user_name='zhuoxiang2333'; $obj1->password=md5(123); //添加副表Avatar数据 $obj2=New Avatar(); $obj2->pic_url='cccc'; $obj2->thumb_url='cccc'; $obj1->logo=$obj2; $result=$obj1->together('logo')->save(); var_dump($result);关联修改第一种:(不推荐,在项目不要在控制器写逻辑)$obj=Member::get(1024); $result=$obj->logo->save(['thumb_url'=>'cccccc']); var_dump($result);第二种:(常用) //控制器 $data=[ 'user_id'=>1024, 'user_name'=>'zhuo666666', 'password'=>md5(123), 'pic_url'=>'aaaa', 'thumb_url'=>'qqqqqqqqqqq2', ]; $obj=new Member(); $result=$obj->edit($data); //模型层更新封装 public function edit($data){ try{ $this->startTrans(); if(empty($data)){ return false; } $this->isUpdate(true)->allowField(true)->save($data); $this->logo()->save(['pic_url'=>$data['pic_url'],'thumb_url'=>$data['thumb_url']]); $this->commit(); return true; }catch(Exception $e){ $this->error=$e->getMessage(); $this->rollback(); return false; } }第三种:(更改字段少时好用) $obj=Member::get(1025); $obj->password=md5(12345678); $obj->logo->pic_url='1234567.jpg'; $result=$obj->together('logo')->save(); var_dump($result);关联删除方法1:(快速,常用)//控制器(也可以封装到模型) $obj=Member::get(1027); $result=$obj->togetther('logo')->delete(); var_dump($result);方法2:(麻烦)//控制器 $obj=Member::get(1027); $result=$obj->delete();//删主表 $result=$obj->logo()->delete();//删副表 var_dump($result);方法3:使用模型层封装上面的的代码//控制器使用 $result=Member::delete2(1027); var_dump($result); //使用new方式 public function delete2($data){ try{ $this->startTrans(); $obj=Member::get($data);//可以使用$obj=$this->find($data); $obj->delete(); $obj->logo()->delete(); $this->commit(); return true; }catch(Exception $e){ $this->error=$e->getMessage(); $this->rollback(); return false; } } //使用静态方式 public static function delete3($data){ try{ self::startTrans(); $obj=Member::get($data); $obj->delete(); $obj->logo()->delete(); self::commit(); return true; }catch(Exception $e){ self::rollback(); return false; } }
2020年07月13日
172 阅读
0 评论
0 点赞
2020-07-07
tp路由
前言意义:隐藏真实的项目地址(防止非法入侵的人直接获取真实的项目地址) 方便用户的记忆,起到见名之意的效果 更适合搜索引擎的优化注意:1.使用路由定义时,入口文件依然需要在url中来写,如果需要隐藏入口文件,需要配合Apache或者Nginx这类发布容器来进行隐藏,只需要修改配置文件(重写规则)即可;而路由是框架来定义的,所以放到Apache和nginx都好使,所有一般隐藏入口文件用Apache或者nginx的重写功能(Rewrite)来完成;具体的路由都按照框架的路由方式来定义。2.如果要隐藏入口文件,在apache环境下可以使用.htaccess文件来隐藏,但5.6以上版本需要把规则改成RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]规则:多条路由执行时,后面相同规则会覆盖前面的 不用的规则,但解析的结构相同时,先解析的先执行\think\Route::rule('路由表达式','路由地址','请求类型',[路由参数],[变量规则]);tp5路由的三种模式:【普通模式】 path_info访问//设置 'url_route_on' => false, // 按照顺序解析变量 'url_param_type' => 1,路由关闭后,不会解析任何路由规则,采用默认的PATH_INFO 模式访问URL【混合模式】开启路由,并使用路由定义+默认PATH_INFO方式的混合'url_route_on' => true, 'url_route_must'=> false,【强制路由】开启路由,并设置必须定义路由才能访问'url_route_on' => true, 'url_route_must' => true,动态注册think\Route::rule('index/:id','index/News/read')参数1:路由表达式'/' => 'index', // 首页访问路由 'my' => 'Member/myinfo', // 静态地址路由 'blog/:id' => 'Blog/read', // 静态地址和动态地址结合 'new/:year/:month/:day'=>'News/read', // 静态地址和动态地址结合 ':user/:blog_id'=>'Blog/read',// 全动态地址首页:/静态地址:直接以字符串来定义动态地址:以冒号开始后面跟着变量名,相当于给静态地址传入一个pathinfo的参数,参数名就是变量名可选定义:如果像省略不写=》[] 可选参数只能放到路由规则的最后,如果在中间使用可选参数那后面的变量也都变成可选参数(在tp中可能会报错误控制器不存在)完全匹配:如果希望完全匹配,可以在路由表达式最后使用$符号; 如果不加完全匹配,可能出现前半部分与路由表达式匹配成功,后面又添加了一些参数,也能(错误的)匹配成功;//开启路由定义的全局完全匹配 'route_complete_match' => true,额外参数:类似隐式传参,但是通过url方式传递的参数,只是外界看不到,可以进行一些安全的防范;例如:传参配合自动注入+静动态地址结合//route.php \think\Route::rule('path/:id','index/Index/pu'); //Index.php public function pu($id){ echo $id.'<br>'; return '动态注册'; } //访问; shop.com/path/233路由参数(数组)第四个参数的两种写法//方法1 \think\Route::rule('rt/[:id]','index/Index/ob','get',[],['id'=>'\d+'])//rt/11 //方法2 \think\Route::get('rt/[:id]','index/Index/ob',['method' => 'get'],[],['id'=>'\d+'])//rt/11 参数2:路由地址路由到达的目标(代码)5中定义方式:定义方式定义格式方式1:路由到模块/控制器'[模块/控制器/操作]?额外参数1=值1&额外参数2=值2...'方式2:路由到重定向地址'外部地址'(默认301重定向) 或者 ['外部地址','重定向代码']方式3:路由到控制器的方法'@[模块/控制器/]操作'方式4:路由到类的方法'\完整的命名空间类::静态方法' 或者 '\完整的命名空间类@动态方法'方式5:路由到闭包函数闭包函数定义(支持参数传入)方式1和方式3的区别:方式1会初始化模块(通过对模块内的配置想是否读取就能进行验证);方式3仅仅是路由到控制器的方法,模块不会被初始化;换句话这时候控制器类似于普通的类文件方式3会调用应用类方式4只会使用第三方类参数3:请求类型get和postput和Delete{Restful}any(*)请求参数大写多个类型用| 竖线分割。比如GET|POST参数4:路由参数对路由的规则进行参数的限制或者定义详细参数(数组)见tp官方手册https://www.kancloud.cn/manual/thinkphp5/118034行为层必须使用run方法比如建立文件application\behavior\UserCheck.php<?php namespace app\index\behavior; class UserCheck{ public function run(){ echo request()->url(); if('/fn/0' ==request()->url()){ return false; } } }栗子:\think\Route::any('url',function(){ return "url"; },['htpps'=>true]); \think\Route::any('fq',function(){ return "fq"; },['callback'=>'my_check_fun']); \think\Route::any('fqq',function(){ return "fqq"; },['before_behavior'=>'\app\index\behavior\UserCheck']);参数5:变量规则针对的是路由表达式中的动态参数来指定对应参数的规则(参该如何写,通常为正则表达式来设定)全局变量规则:针对每条路由规则中的参数单独定义局部变量规则:针对每条路由规则中的对应参数进行定义完整URL规则:如果要对整个URL进行规则检查,可以进行__url__变量规则,例如:['__url__'=>'new\/\w+$']栗子://方式1 \think\Route::pattern('name','\d+'); //方式2(局部定义-常用) \think\Route::rule('new/:na',function($na){ return "OK:".$na; },'GET|POST',[],['__url__'=>'new\/\w+$']); 组合变量在定义某些特殊路由规则是可以使用组合变量例如Route::get('item-<name>-<id>','index/detail',[],['name'=>'\w+','id'=>'\d+']);使用闭包测试栗子://浏览器输入http://网址/date/abc05 \think\Route::rule('date/<na><id>',function($na,$id){ return $id."=>".$na; },'GET|POST',[],['na'=>'[a-zA-Z]+','id'=>'[0-5]+']); //浏览器输入http://网址/datee/abc-05 \think\Route::rule('datee/<na>-<id>',function($na,$id){ return $id."<=组合变量=>".$na; },'GET|POST',[],['na'=>'\w+','id'=>'[0-5]+']);批量注册方式一:将理由表达式的参数通过数组方式定义,键名为路由表达式,键值为里有地址;规则中的路由地址由空字符串占位,其他参数不遍;方式二:通过配置文件的return数组形式定义,关联数组的键名为路由表达式: 键值为索引数组,形式为[路由地址(5种),路由参数(数组),变量规则(数组)]'__pattern__'为全局变量规则,具体规则用关联数组来定义[变量名=>变量规则]栗子://访问浏览器 //http://地址/blog/15.html //http://地址/bg2.html //http://地址/bg3/abc/15.html return [ 'blog/:id' =>['blog',['ext'=>'html'],['name'=>'[a-zA-Z]+','id'=>'[0-5]+']], 'bg2'=>['@index/Index/bg23',['ext'=>'html'],['name'=>'[a-zA-Z]+','id'=>'[0-5]+']], 'bg3/:name/:id'=>['bg24',['method'=>'get|post','ext'=>'html'],['name'=>'[a-zA-Z]+','id'=>'[0-5]+']], ];快捷路由直接为控制器定义一个路由规则,每个方法的名字为请求类型+方法名(驼峰法命名)// 给Index控制器设置快捷路由 Route::controller('in','index/Index');创建类库文件(自动生成一下方法)>php think make:controller index/Usernamespace app\index\controller; class User { public function getInfo(){} public function getPhone(){} public function postInfo(){} public function putInfo(){} public function deleteInfo(){} } //通过一下方式访问 //get http://localhost/user/info //get http://localhost/user/phone //post http://localhost/user/info //put http://localhost/user/info //delete http://localhost/user/info路由别名路由别名功能可以使用一条规则,批量定义一系列的路由规则。// user 别名路由到 index/User 控制器 \think\Route::alias('user','index/User'); //或者 return [ '__alias__' => [ 'user' => 'index/User', ], ]; //访问方式: //http://serverName/index.php/user/add //http://serverName/index.php/user/edit/id/5 //http://serverName/index.php/user/read/id/5 // user 路由别名指向 User控制器类 Route::alias('user','\app\index\controller\User'); // user 别名路由到 index/user 控制器 Route::alias('user','index/user',['ext'=>'html']);路由别名不支持变量类型和路由条件判断,单纯只是为了缩短URL地址,并且在定义的时候需要注意避免和路由规则产生混淆。路由分组路由分组功能允许把相同前缀的路由定义合并分组,这样可以提高路由匹配的效率,不必每次都去遍历完整的路由规则。我的理解是建立一个2级路由然后组内的路由规则可以统一定义管理方便。设置公共的路由参数栗子://访问浏览器 //http://地址/group/15.html //http://地址/group/bg2.html //http://地址/group/bg3/abc/15.html \think\Route::group('goods',[ 'blog/:id' => ['blog'], 'bg2'=>['@index/Index/bg23'], 'bg3/:name/:id'=>['bg24'], ],['method'=>'get|post','ext'=>'html'],['name'=>'[a-zA-Z]+','id'=>'[0-5]+']);使用闭包方式注册路由分组栗子:\think\Route::group('blog',function(){ Route::any(':id','blog/read',[],['id'=>'\d+']); Route::any(':name','blog/read',[],['name'=>'\w+']); },['method'=>'get','ext'=>'html']); //或者 \think\Route::group(['method'=>'get','ext'=>'html'],function(){ Route::any('blog/:id','blog/read',[],['id'=>'\d+']); Route::any('blog/:name','blog/read',[],['name'=>'\w+']); });路由分组嵌套栗子:\think\Route::group(['method'=>'get','ext'=>'html'],function(){ Route::group('blog',function(){ Route::any('blog/:id','blog/read',[],['id'=>'\d+']); Route::any('blog/:name','blog/read',[],['name'=>'\w+']); } });MISS路由如果希望在没有匹配到所有的路由规则后执行一条设定的路由,可以使用MISS路由功能,只需要在路由配置文件中定义return [ 'new/:id' => 'News/read', 'blog/:id' => ['Blog/update',['method' => 'post|put'], ['id' => '\d+']], '__miss__' => 'public/miss', ]; //或者使用miss方法注册路由 \think\Route::miss('public/miss');也可以写在分组路由配置中路由绑定可以使用路由绑定简化URL或者路由规则的定义不建议用和其他路由规则冲突绑定到模块/控制器/操作// 绑定当前的URL到 index模块 \think\Route::bind('index'); // 绑定当前的URL到 index模块的blog控制器 \think\Route::bind('index/blog'); // 绑定当前的URL到 index模块的blog控制器的read操作 \think\Route::bind('index/blog/read');绑定到命名空间// 绑定命名空间 \think\Route::bind('\app\index\controller','namespace'); //访问http://地址/index/Blog/read绑定到类// 绑定到类 \think\Route::bind('\app\index\controller\Blog','class'); //http://地址/read/id/5入口文件绑定见手册介绍:https://www.kancloud.cn/manual/thinkphp5/118040资源路由\think\Route::resource('blog','index/blog'); //或者 return [ // 定义资源路由 '__rest__'=>[ // 指向index模块的blog控制器 'blog'=>'index/blog', ], // 定义普通路由 'hello/:id'=>'index/hello', ]设置后会自动注册7个里有规则标识请求类型生成路由规则对应操作方法(默认)indexGETblogindexcreateGETblog/createcreatesavePOSTblogsavereadGETblog/:idreadeditGETblog/:id/editeditupdatePUTblog/:idupdatedeleteDELETEblog/:iddelete访问方法:http://域名/blog/http://域名/blog/128http://域名/blog/28/edit创建类库文件(自动生成上面7个方法)>php think make:controller index/UserURL生成ThinkPHP5.0支持路由URL地址的统一生成,并且支持所有的路由方式,以及完美解决了路由地址的反转解析,无需再为路由定义和变化而改变URL生成。Url::build('地址表达式',['参数'],['URL后缀'],['域名'])url('地址表达式',['参数'],['URL后缀'],['域名'])地址表达式和参数//定义一个路由规则 \think\Route::rule('blog/[:abc]$','index/Index/blog2'); \think\Route::rule('ver','@index/Index/ver'); //用以下方式生成url地址 echo Url::build('index/Index/blog2',['abc'=>'aabbcc'],'',true); echo Url::build('@index/Index/ver',['abc'=>'aabbcc'],'',true); //最后输出结果 /* http://shop18/blog/aabbcc http://shop18/ver/abc/aabbcc */使用模块/控制器/操作生成// 生成index模块 blog控制器的read操作 URL访问地址 Url::build('index/blog/read','id=5&name=thinkphp'); // 使用助手函数 url('index/blog/read','id=5&name=thinkphp');使用类的方法生成//定义动态路由规则 \think\Route::rule(['verify','ver'],'\app\index\controller\Index@ver'); \think\Route::rule(['zx','zx'],'\com\zx\Zhuoxiang::showMsg?id=123'); //用以下方式生成url地址 echo Url::build('verify',['name'=>'zhangsan'],'',true); echo Url::build('zx',['name'=>'zhangsan'],'',true); //最后输出结果 //http://shop18/ver/name/zhangsan //http://shop18/zx/name/zhangsanURL后缀//默认情况下,系统会自动读取url_html_suffix配置参数作为URL后缀(默认为html) 'url_html_suffix' => 'shtml' //生成地址为:/index.php/blog/5.shtml //设置支持多个后缀 'url_html_suffix' => 'html|shtml' //指定URL后缀生成 Url::build('index/blog/read','id=5','shtml'); url('index/blog/read','id=5','shtml');域名生成生成锚点隐藏或显示入口文件详情请看tp官方文档:https://www.kancloud.cn/manual/thinkphp5/118041
2020年07月07日
168 阅读
0 评论
0 点赞
2020-03-23
控制器输出
控制器输出json数据打印简单的json数据在headers头文件中内容类型还是html格式文件public function zy(){ $arr=Db::table('app_users') ->field('id,username,sex,email') ->find(); echo json_encode($arr); }运行结果{"id":13,"username":"admins","sex":1,"email":"fengerda@163.com"}//将数组转成json格式数据json_encode($arr);只是将显示得结果转为json数据,但格式还是原先得html格式查看html源代码可以看出来不光有结果还有tp的一些东西要想只显示json数据内容 在echo后面写exit(); return代替echo会获取空值,因为会两次json编译在ajax中使用服务器返回数据类型为json$.ajax({ type:'post', .... success:function(data){}, dataType:'json'//回调数据的格式html,text,json,xml });返回得结果和内容属性都是json格式输出方式【强制设置输出类型】根据请求类型直接判断进行输出\think\Config::set('default_return_type','json'); return $arr;【原生方式】通过原生方式返回数据不会设置头信息echo json_encode($arr); exit();json_encode(数据,额外参数)第2参数:额外参数可以设置成定义的常量例如不写第二参数那么最后显示的带有中文的字符会自动转为'\u8d85'这种形式加入JSON_UNESCAPED_UNICODE后即可显示原样中文字符JSON_HEX_QUOT,JSON_HEX_TAG,JSON_HEX_AMP,JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT,JSON_PRESERVE_ZERO_FRACTION,JSON_UNESCAPED_UNICODE, JSON_PARTIAL_OUTPUT_ON_ERROR。具体含义参考:预定义常量【自动输出】根据请求类型来觉得用什么格式的数据输出,输出的同时会自动设置头信息return $arr通过配置项来修改设置\think\Config::set('default_return_type',json);'default_return_type'=>'html','default_ajax_return'=>'json','default_jsonp_handler'=>'jsonpReturn'【手动输出】根据我们的需求进行输出,输出是会自动匹配头信息的格式//类的静态调用 return Respanse::create($data,'json',$code,$header,输出参数); //助手函数 return json(c1,c2,c3,c4); 参数1:数组数据,参数2:状态码,参数3:头信息参数,参数4:额外参数关于设置头信息请参考ThinkPHP5控制器从入门到精通-第八章响应输出-设置信息头
2020年03月23日
161 阅读
0 评论
0 点赞
2020-03-13
tp的命名空间加载
1.根命名空间加载在tp中有三个预定义的根命名空间app应用类库 applicationthink系统核心类库thinkphp/library/thinktraits系统Trait类库thinkphp/library/traits//use的使用方法: use think\Request use think\Session如果需要增加新的根命名空间,有两种方式:注册新的根命名空间或者放入EXTEND_PATH目录(自动注册)2.自动注册需要把自己的类库包目录放入EXTEND_PATH目录(默认为extend,可配置),就可以自动注册对应的命名空间。通俗来讲是在extend目录下新建一个文件就这个文件夹名字当作一个根命名空间栗子://类文件位于extend/my/Test.php//命名空间是namespace my; //直接new $test = new \my\Test();应用入口重新定义EXTEND_PATH常量可以改变\my\Test类文件的位置define('EXTEND_PATH','../vendor/');那么\my\Test类文件的位置就变成了/vendor/my/File.php。注意不能定义含有预定义的三个根命名空间名字3.手动注册手动定义一个根命名空间比自动定义还要方便,更自由。//单独注册 \think\Loader::addNamespace('命名空间','路径'); \think\Loader::addNamespace('my\test','../application/extend/my/test');//批量注册 \think\Loader::addNamespace([ '命名空间1','路径1', '命名空间2','路径2', ...... ]);4.类库映射定义一个完整的命名空间的类名//单独注册 loader::addClassMap('think\log',LIB_PATH,'think\log.php');//批量注册 $map = [ 'think\Log' => LIB_PATH.'think\Log.php', 'org\util\array'=> LIB_PATH.'org\util\Array.php' ]; Loader::addClassMap($map);5.手动加载手动加载自由度最大,①可以有命名空间,遵循tp规范。②可以有命名空间,不遵循tp规范。③没有命名空间。使用think\Loader类的import方法手动加载类库文件loader('类库命名空间字符串','起始路径','文件拓展名')栗子://加载当前模块应用类库 Loader::import('@.test.wechat#mail#class');//目录中斜杠用点替换,类中的点用井号代替 //加载其它模块的类库 \think\Loader::import('index.zx.zx',APP_PATH,'.class.php'); \think\Loader::import('index.zx.zx','../application','.class.php');6.Composer下载依赖类包名字和相关信息定义成json文件加载类文件:配置和所需的类包进行关联,降低程序代码耦合度代码的仓库:所有类库都是发布在他的平台https://packagist.org/栗子://下载topthink作者的处理图片类 $img=\think\Image::open('static/img/in.jpg')->size(); //查看本地图片的尺寸
2020年03月13日
167 阅读
0 评论
0 点赞
2020-03-02
关于success在frameset框架中跳转套娃问题
清除tp中默认session作用域//检查是否登录public function __construct(Request $request){ parent::__construct($request); if(!session('?userid','','')){ $this->error('请先登录!','index/login/login'); } } session('名称',‘值’,‘前缀’)设置前缀为空字符串随之也修改session方法中protected function success($msg ='',$url=null,$data='',$wait=3,array $header=[],$parent='')将$result=[...]参数加入'parent'=>$parent,在最后一个参数加入$parent=''session('成功','index',[],3,[],'parent');最后一个参数为跳转的方式在$result中添加'parent'=>$parent,修改session作用域这一步骤可以省略,目的是避免session中多个作用域冲突修改跳转模板参数模板地址:thinkphp/library/tpl/dispatch_jump.tpl在location.href = href;代码前加入判断<?php echo($parent?$parent.'.':'')?>来根据session(‘’,‘’,‘parent’)来决定跳转的方式。同样error方法还有点击跳转也要加点击跳转的a标签加 target="_parent"总结success的跳转默认是在当前框架中子框架中跳转页面,想要跳出整个框架,需要用到js/jq的跳转代码location.href前面加上parent.这样就可以跳出框架的限制。附加-其他解决方式<script> if(window.top!=window){ window.top.location.href=document.location.href; } </script>
2020年03月02日
214 阅读
1 评论
1 点赞
2020-02-23
tp5-Token表单令牌
用途有效方式防止重复提交,以及跨站伪造请求(anti csrf)特点随机性不可预测原理原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。然后,如果应用于“anti csrf攻击”,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。用法在表单中添加<input type="hidden" name="__hash__" value="{$Request.token}" /> 或者 {:token()}在验证器中添加规则,验证是否符合protected $rule = [ '__token__' => 'require|token', ]; protected $message = [ '__token__.require' => '非法提交', '__token__.token' => '请不要重复提交表单' ];因为数据表中没有__hash__字段,要删除表单提交过来中数据中的__hash__字段控制器中使用自动逸令牌规则,调用Request类$token = $this->request->token('__token__', 'sha1'); $this->assign('token', $token);
2020年02月23日
174 阅读
0 评论
0 点赞
2020-02-22
tp5-验证器
验证器验证器可以利用写好的规则进行快速的验证并且提示出错误信息验证使用独立的think\Validare类//任何时候,都可以使用Validate类进行独立的验证操作 $validate = new Validate([ 'name' => 'require|max:25', 'email' => 'email' ]); $data = [ 'name' => 'thinkphp', 'email' => 'thinkphp@qq.com' ]; if (!$validate->check($data)) { dump($validate->getError()); }验证使用验证器进行验证//定义一个\app\index\validate\User验证器类用于User的验证 namespace app\index\validate; use think\Validate; class User extends Validate { protected $rule = [ 'name' => 'require|max:25', 'email' => 'email', ]; }//在需要进行User验证的地方,添加如下代码即可: $data = [ 'name'=>'thinkphp', 'email'=>'thinkphp@qq.com' ]; $validate = Loader::validate('User'); if(!$validate->check($data)){ dump($validate->getError()); } //Loader-加载|check-校验//使用助手函数实例化验证器 $validate = validate('User');验证规则设置规则详情见tp5官方开发手册规则定义在$rules=['name'=>'require'];中使用多个规则有两种方法可供选择1.使用管道符'name'=>'require|max:25'2.使用数组'name'=>['require','max'=>25]属性定义protected $rule = ['name' => 'require|max:25']; protected $message = [ 'name.require' => '名称必须', 'name.max' => '名称最多不能超过25个字符' ];数据验证(含批量,控制器类,闭包,自定义)$rule=['name'=>'require|max:25',]; $msg=['name.require'=>'名称必填',]; $data=['name'=>'admin123']; //普通验证 $validate=new Validate($rule,$msg); $result=$validate->check($data); //批量验证 $validate=new Validate($rule,$msg); $result=$validate->batch()->check($data); //使用定义的验证器验证 $validate = Loader::validate('User'); if(!$validate->check($data)){ dump($validate->getError()); } //闭包函数验证 $validate = new \think\Validate([ 'name' => function($value,$data) { //第一个参数是当前字段值,第二个参数是全部数据 return 'thinkphp'==$value ? true : false; }, ]); //自定义验证规则 class User extends Validate { protected $rule = [ 'name' => 'checkName:thinkphp', 'email' => 'email', ]; protected $message = [ 'name' => '用户名必须', 'email' => '邮箱格式错误', ]; // 自定义验证规则 protected function checkName($value,$rule,$data) { //$value,$rule,$data,$fieldname,$description //验证数据,验证规则,全部数据(数组),字段名,字段描述 return $rule == $value ? true : '名称错误'; } }错误信息使用默认的错误提示信息(默认)验证规则和提示信息分开(推荐)验证规则和提示信息一起定义使用多语言(不常用)验证场景场景验证只验证场景中规定的字段//验证不同场景 $rule=[...]; $msg=[...]; $data=[...]; $validate = new Validate($rule); $validate->scene('edit', ['name', 'age']); $result = $validate->scene('edit')->check($data); //使用验证器类 protected $rule=[]; protected $message=[]; protected $scene=['edit'=>['name','age']]; //然后在需要验证的地方使用scene方法 $data=[...]; $validate=new \app\index\validate\User($rule); $result=$validate->scene('edit')->check($data);也可以在定义场景的时候对某些字段的规则重新设置protected $scene=[ 'edit'=>['name','age'=>'require|number|between:1,120'], ];scene-场景验证方式:验证器验证(首选)、控制器的验证方法验证、模型类的方法验证(废弃) 验证规则:内置了非常丰富的内置规则;自定义规则; 错误信息:只需要定义信息文字即可在出现错误时返回错误信息 验证场景:根据需要在不同的情况下灵活使用已经定义好的验证规则->scene('场景') 高级的使用:批量验证(返回的错误是数组;每个字段是一个元素;每个字段只返回一个错误)、表单令牌(跨域提交csrf跨站脚本攻击)*内置规则require-必须number/integer/float-数字email-邮箱地址array-数字accepted-yes/no/1date-日期alpha-字母alphaNum-字母和数字alphaDash-字母/数字/_/-chs-汉字chsAlpha-汉字/字母chsAlphaNum-汉字/字母/数字chsDash-汉字/字母/数字/_/-activeUrl/url/ipdateFormat:format:y-m-d-指定格式日期lengthmax/minin/notIn/between/notBetweenafter:日期-之前before:日期-之后expire:开始时间,结束时间confirm:-比较另一个字段值different:-比较另一值不一致eq/same-等于某个值eqt/>=-大于等于gt/>-大于elt/<=-小于等于lt/<-小于正则上传行为其他验证控制器验证[验证方式①]验证器验证:定义一个验证器的类,在控制器中进行验证验证成功:返回true; 验证失败:返回false;如果需要获取错误信息:$validate->getError();$validate = Loader::validate('Users'); $result = $validate->check($post); //$result = $validate->batch(true)->check($post); if(!$result){ //var_dump($validate->getError()); $this->error($validate->getError()); //return json($validate->getError()); }[验证方式②]控制器的验证方法:验证成功:返回true;验证失败:返回错误信息;@param array $data 数据@param string|array $validate 验证器名或者验证规则数组@param array $message 提示信息@param bool $batch 是否批量验证@param mixed $callback 回调方法(闭包)$result = $this->validate($post,'Users'); //$result = $this->validate($post,'Users',[],true); if(true !== $result){ //var_dump($result); $this->error($result); } exit("验证通过!");
2020年02月22日
269 阅读
0 评论
1 点赞
2020-02-18
tp5-模型数据处理
模型数据处理模型提供比数据库类更为强大的数据处理功能,处理数据可以更方便,更安全获取器获取器的作用是对模型的数据对象的(原始)数据做出自动处理。定义:受保护的方法,名字格式为:get+FieldName(大驼峰)+Attr,一般数据库的字段都是小写+下划线格式所以需要转换为驼峰法写法://Model $protected function getFieldNameAttr($value){ return $value; } //View <{$vo['id']}>//原本输出代码 <{$vo->id}>//输出处理过的数据 <{$vo->getAttr('id')}>//输出处理过的数据 <{$vo->getData('id')}>//不触发-输出原数据自动触发:模型的数据对象取值操作($model->field_name);模型的序列化输出操作($model->toArray());显式调用getAttr方法($this->getAttr('field_name'));场景栗子:时间日期字段的格式化输出;$protected function getFieldNameAttr($value){ return data('Y-m-d H:i:s',$value); }时间戳转本地时间data('Y-m-d H:i:s',time())本地时间转时间戳strtotime('2020-02-18')集合或枚举类型的输出;//Config 'if_show'=>[ '0'=>'下架', '1'=>'上架', '3'=>'待审核' ] //Model $protected function getFieldNameAttr($value){ $if_show=\think\Config::get('if_show'); return $if_show[$value]; }虚拟字段的输出;使用虚拟一个字段来避免获取器重名,使一个字段达到不同效果//Model-1 $protected function getTextAttr($value,$data){ return $data['id']; } //HTML <{$vo->text}>组合字段的输出;//Model $protected function getFieldNameAttr($value,$data){ return '['.$data['id'].']——'.$value; }推荐使用3,虚拟字段和4, 组合字段一起使用效果更好修改器和获取器相反,修改器的主要作用是对模型设置的数据对象值进行处理触发条件模型对象赋值;调用模型的data方法,并且第二个参数传入true;调用模型的save方法,并且传入数据;显式调用模型的setAttr方法;定义了该字段的自动完成;//对密码字段进行MD5加密后存入数据库 protected function setUpwdAttr($value){ return md5($value); }场景栗子时间日期字段的转换写入;集合或枚举类型的写入;// 极少数情况会涉及到这种方式来处理 protected function setPermissionAttr($value){ $permission = \think\Config::get('permission'); foreach($permission as $k=>$v){ if($v === $value){ return $k; } } return 0; } //Config 'permission'=[ '0'=>'有权限', '1'=>'无权限' ]数字状态字段的写入;某个字段涉及其它字段的条件或者组合写入;自动时间字段待补// 开启时间字段自动写入protected $autoWriteTimestamp = true; // 定义时间字段名protected $createTime = 'create_at'; protected $updateTime = 'update_at'; 数据类型转换待补数据自动完成[自动完成]当提交的表单(数据)中不存在某个字段,我们可以通过自动完成的方式添加上这个字段,同时会触发该字段的修改器protected $auto = ['add_time']; // 针对添加和修改的动作的时候,对表单自动添加字段; protected $insert = ['permission'=>2];// 仅针对新增的情况 protected $update = ['login_times'];// 仅针对修改的情况待补充
2020年02月18日
393 阅读
0 评论
0 点赞
2020-02-12
tp5-CURD之更新2
CURD更新2讲实现方法1.Db类Db::table('user') ->where('id',1) ->update([ 'name'=>'topThink', 'email'=>'topThink@qq.com' ]);2.模型动态$user=User::get(1); $user->name='topThink'; $user->email='topThink@qq.com'; $user->save();或者$user=User::get(1); $user->save([ 'name'=>'topThink', 'email'=>'topThink@qq.com' ]);3.模型静态调用User::update([ 'name' => 'topthink', 'email' => 'topthink@qq.com', ], ['id' => 1]);区别save方法返回影响的记录数 update方法返回的是模型的对象实例模型和Db更新方法的区别是模型的更新只会更新有变化的数据,没有变化的数据是不会更新到数据库的,如果所有数据都没有变化,不会执行数据库更新操作。强制更新强制本次操作为更新与创建区分开//更新数据 $this->isUpdate(true)->allowField(true)->save($data); //创建数据 $this->isUpdate(false)->allowField(true)->save($data);更新条件1.默认主键更新//获取主键名 $this->getPk(); //$data函数必须含有主键字段 $this->isUpdate(true)->allowField(true)->save($data);2.where条件更新//$data数组中不能含有主键字段 $where=[ 'id'=>['>',676] ] $this->isUpdate(true)->allowField(true)->save($data,$where);注意:按着where条件更新时,要注意$data数组中不能含有主键字段,否则主键和where条件同时存在时,默认主键更新作为条件而where条件失效。3.主键和where同存判断$pk=$this->getPk(); if(empty($data[$pk]) && empty($where)){ $this->error="更新条件不能为空"; return false; } return $this->isUpdate(true)->allowField(true)->save($data,$where);如果主键存在,自动覆盖更新条件如果主键不存在,自动使用更新条件进行更新如果都不存在,提示错误4.数据无变化判断//控制器 $userObj=new Users(); $result=$userObj->edit($data,[]); if(false===$result){ $this->error('修改失败!原因:'.$shuxingObj->getError()); }elseif(0===$result){ $this->error('没有修改任何数据!'); }else{ return $this->fetch(); }代码栗子执行更新和删除的流程public function edit(){ //接参 //参数判断 //执行更新-执行删除 //业务跳转 }
2020年02月12日
172 阅读
0 评论
2 点赞
2020-01-14
tp5-模型层CURD1
CURD的三种写法1.第一种:Db类2.第二种:Model动态3.第三种:Model静态在写项目时,常用写法:创建和更新使用Model动态方法save()查一条和多条使用Model静态方法get(),all()删除使用Model静态方法destroy()模型类与Db类的区别:模型类具有修改器,获取器,自动完成,类型转换等高级操作,而Db类没有;异常Exceptionuse think\Exception;获取异常try{}catch(\think\Exception $e){//catch可以写多次}常用的属性:$this->error=$e->getMessage();//调用模型类的一个属性error,并将抛出的异常信息,赋值到error属性中getLastInsID()//作用是获取最后一次添加记录的主键(id)allowField(true)类似链式操作的一种写法//作用是在进行增加方法时,在用户提交的信息中将与数据库字段吻合的数据添加在异常中使用三种方法新增//测试是在控制器中,普通写法应该是在Model; try{ $data=[ 'name'=>'admin', 'pwd'=>md5(123), 'email'=>'110901678@qq.com' ] //1.使用Db类新增 $rt=Db::table('表名')->field(true)->insert($data); echo Db::getLastInsID(); //2.使用模型静态-不推荐 $rt=\app\index\model\Users::create($data); //3.使用模型动态-推荐 $rt->allowField(true)->save($data); }catch(\think\Exception $e){ echo $e->getMessage(); } 拓展:static与self在实例化的区别面向对象中new static 与new self区别:1.写在类的本身时没有区别2.写在类的继承时(例如下栗子)当红框中是self时,最后echo 的是'Text'.当红框中是static时,最后echo 的是'Zx'.
2020年01月14日
180 阅读
0 评论
0 点赞
2020-01-09
tp5-模型层
Db与模型的区别Db查询返回的数据类型为数组模型查询返回类型的是模型对象实例模型定义写法:<?php namespace app\index\model; use think\Model; class User extends Model{ }模型定义的要素:通常会继承 think\Model(或者子类) ,虚拟模型除外;一个模型可以一对一,一对多;(一个模型类对应操作的数据是一张表,模型类实例化对象就是表里的一条数据)模型名和数据表名可以不是直接对应关系空模型与Db类功能一样,但意义不用。模型定义的目的定义数据表(默认就是模型类名)定义数据表主键(默认会自动获取)定义数据库连接(默认使用数据库配置)定义数据处理逻辑(包括属性和方法)定义业务逻辑(方法)模型定义不支持数据表字段(不需要,会自动获取,并支持缓存机制)数据表前缀(不支持,模型不关心前缀)模型名对应数据表UseruserUserTypeuser_typeUserthink_userUserTypethink_user_type模型调用模型支持实例化调用和静态调用(主要是查询,查询后会返回一个模型对象实例)。实例化调用$user = new \app\index\model\User();静态调用$user = \app\index\model\User::get(1);助手函数$user = model('User');tp中表名都是按照小写加下划线的命名规则命名,表名转成类文件名和类名去掉表前缀,用驼峰法:one: ::two: :重用度高:three: :先整体后局部
2020年01月09日
133 阅读
0 评论
0 点赞
2020-01-07
tp5-分页
$list=$db->paginate('每页显示条数',true/false,['type'=>'bootstrap','var_page'=>'page','list_rows'=>15,]);一,原生分页求总数总数÷每页条数,得到一个值向上取整,得出总数limit 方法算一个起始结束位置计算分页链接二,分页实现Db类查询的时候调用paginate方法:// 查询状态为1的用户数据 并且每页显示10条数据 2.$list = Db::name('user')->where('status',1)->paginate(10); 3.// 把分页数据赋值给模板变量list 4.$this->assign('list', $list); 5.// 渲染模板输出 6.return $this->fetch(); //--------------------------------------- //模板输出{$list->paginate();}模型的分页查询代码// 查询状态为1的用户数据 并且每页显示10条数据 $list = User::where('status',1)->paginate(10); // 把分页数据赋值给模板变量 list$this->assign('list', $list); // 渲染模板输出return $this->fetch(); //---------模板文件输出--------------- <div> <ul> {volist name='list' id='user'} <li> {$user.nickname}</li> {/volist} </ul> </div> {$list->render()}单独赋值分页输出// 查询状态为1的用户数据 并且每页显示10条数据 $list = User::where('status',1)->paginate(10); // 获取分页显示 $page = $list->render(); // 模板变量赋值 $this->assign('list', $list); $this->assign('page', $page); // 渲染模板输出 return $this->fetch(); //----------模板文件分页输出--------------- <div> <ul> {volist name='list' id='user'} <li> {$user.nickname}</li> {/volist} </ul> </div> {$list->render()}三,分页参数list_rows-每页数量 page-当前页path-url路径query-url额外参数fragment-url锚点var_page-分页变量type-分页类名四,分页循环each(function($item,$key){xxxxx})$list=$db->paginate(5,false,[ 'type'=>'bootstrap', 'vat_page'=>'page', 'query'=>$request->get(), ]) ->each(function($item,$key){ $item['goods_name']='【'.$item['cate_name'].'】'.$item['goods_name']; });
2020年01月07日
180 阅读
0 评论
0 点赞
2019-11-08
tp5-数据库高级4
复习-查询构造器查询构造器分为:链式操作,查询语言【高级查询技巧】获取SQL语句【返回SQL语句】属于链式操作的一种;返回要执行的SQL语句,一般用于调试SQL语句报错信息解决办法:添加fetchSql(true)返回的是sql语句(字符串)方法1:链式操作之一 $result=Db::table('ecm_users') ->where('ids','>',20) ->fetchSql(true) ->select(); 方法2:数据库类的方法返回sql语句并在两端多了括号 $result=Db::table('ecm_users') ->where('ids','>',20) ->buildSql();【高级查询技巧】*聚合查询【聚合查询】每个方法对应的原生SQL都会自动加上limit 1;查询字段都会自动起别名CONUNT(*) as tp_count五个函数:sum,avg,count,min,max => limit 1返回的是字符串//参数可选的方式,不写参数为count(*) $result=Db::table('ecm_goods')->field(true)->count(); // SELECT COUNT(*) AS tp_count FROM `ecm_goods` LIMIT 1 //参数可选的方法,写参数count(id) $result=Db::table('ecm_goods')->field(true)->count('goods_id'); // SELECT COUNT(*) AS tp_count FROM `ecm_goods` LIMIT 1 //sum 和 avg $result=Db::table('ecm_goods')->field(true)->sum('price'); // SELECT SUM(price) AS tp_sum FROM `ecm_goods` LIMIT 1 $result=Db::table('ecm_goods')->field(true)->avg('price'); // SELECT AVG(price) AS tp_sum FROM `ecm_goods` LIMIT 1count例子中field链接没有用,查询时可以省略【高级查询技巧】*快捷查询-不同字段不同字段的相同值的查询,多个字段之间用|分隔表示OR查询,用&分隔表示AND查询$result=Db::table('ecm_goods') ->field(true) ->where('goods_id&if_show&recommended','=',1) //WHERE ('goods_id' = 1 AND 'if_show' = 1 AND 'recommended' = 1) ->where('if_show|recommended','=',1) //WHERE('if_show' = 1 OR 'recommended','=',1) ->select();【高级查询技巧】*快捷查询-相同字段相同字段的不相同值的查询$result=Db::table('ecm_goods') ->field(true) ->where('goods_id',['>=',1],['<=','10']) ->where('goods_name',['like','%杰记%'],['like','%海泉%'],['like','%0%'],'OR') ->select(); // ( `goods_id` >= 1 AND `goods_id` <= 10 ) //( `goods_name` LIKE '%杰记%' OR `goods_name` LIKE '%海泉%' OR `goods_name` LIKE '%0%' ) 【高级查询技巧】快捷表达式查询$result=Db::table('ecm_goods') ->field(true) //->where('goods_id','in',[1,2,3,4,5,6]) ->whereIn('goods_id',[1,2,3,4,5,6]) ->select();方法作用whereNull查询字段是否为NullwhereNotNull查询字段是否不为NullwhereIn字段IN查询whereNotIn字段NOT IN查询whereBetween字段BETWEEN查询whereNotBetween字段NOT BETWEEN查询whereLike字段LIKE查询whereNotLike字段NOT LIKE查询whereExistsEXISTS条件查询whereNotExistsNOT EXISTS条件查询whereExp表达式查询【高级查询技巧】*快捷查询-时间表达式whereTime('日期字段名',‘日期表达式’)$result=Db::table('ecm_goods') ->field(true) ->whereTime('add_time','>','2019-11-08') ->whereItme('add_time','d') ->select();支持的日期表达式包括:today或d今天week或w本周month或m本月year或y今年yesterday昨天last week上周last month上月last year去年-2 hours查询两个小时内10 hours ago10小时之前到先到【高级查询技巧】动态查询查询方法不是链式操作,要做为每次查询的最后一次调用的方法来使用,查询条件都是值等“=” getBy+FieldName() ,将要查询的字段转成驼峰法来写;根据某个字段里的值查询一条数据 getFieldBy+FieldName() ,返回一个字段里的值,根据一个字段的值查询另一个字段的值;默认排序的第一条的对应字段 动态查询描述getByFieldName(根据某个字段查询)getFieldByFieldName(根据某个字段获取某个值)根据字段的值查询记录(仅一条记录,默认排序规则的第一条),/-> getByFieldName(值) 返回值为一维数组|NULL 相当于find方法$result=Db::table('ecm_goods') ->field('description',true) ->getByGoodsId(1); //WHERE 'goods_id' = 1 LIMIT 1根据字段的值查询某个字段的值(仅一条记录,默认排序规则的第一条),-> getFieldByFieldName(值,字段名) 返回值为字符串|整型|NULL 相当于find方法$result=Db::table('ecm_goods') ->field('description',true) ->getFieldByGoodsId(111,'goods_name'); //SELECT 'goods_name' FROM 'ecm_goods' WHERE 'goods_id' = 1 LIMIT 1【高级查询技巧】*子查询1. 子查询作为新表进行查询$sql=Db::table('ecm_goods') ->field(true) ->where('goods_id','<',50) ->buildSql(); $result=Db::table($sql.' a') ->where('price','<',20) ->select(); //该例子为简单方式教学,通常第一个查询是很复杂(三表或多表联查)2.子查询作为字段进行查询$sql=Db::table('ecm_gcategory') ->alias('g') ->field('cate_id') ->where('c.cate_id=g.parent_id','exp','') ->limit(1) ->buildSql(); $result=Db::table('ecm_goods') ->alias('c') ->field('cate_id,cate_name,parent_id') ->field('if('.$sql.',1,0) as has_next') //->field('if(select cate_id from ecm_gcategory g where c.cate_id=g.parent_id limit 1),1,0) as has_next') ->where('c.parent_id',0) ->select(); 3.子查询作为查询条件,只会多数用于whereIn的条件中$result=Db::table('ecm_goods') ->field('goods_id,goods_name.price') ->whereIn('goods_id',function($query){ $query->table('ecm_users') ->field('id') ->where('uname','like','%a%') }) ->select(); >>END
2019年11月08日
201 阅读
0 评论
0 点赞
2019-11-07
tp5-数据库操作3
数据库操作查询语言的2个方法,3个用法,8个要诀两个方法:where,whereOr三个用法:表达式查询,数组查询,闭包查询八个要诀:•查询条件的调用次序就是生成SQL的条件顺序;•查询字段用&分割表示对多个字段使用AND查询;•查询字段用|分割表示对多个字段使用OR查询;•对同一个查询字段多次调用非等查询条件会合并查询;•闭包查询和EXP查询会在生成的查询语句两边加上括号;•用闭包查询替代3.2版本的组合查询;•除了EXP查询外,其它查询都会自动使用参数绑定;•如果查询条件来自用户输入,尽量使用表达式和闭包查询,数组条件查询务必使用官方推荐的方法获取变量;【查询构造器】查询语句:表达式查询表达式查询,三个参数,其中如果是等于的条件,可以省略等于的条件直接写两个参数$result=Db::table('ecm_goods') ->field(true) //->whereOr('goods_name','like','%thinkphp%') //->where('goods_id','>',1) //->where('goods_id','<',10) //->where('goods_id','<>',10) //->where('goods_id','between',[1,5]) // ->where('goods_id','in','1,2,3,4,5') // ->where('goods_id','in',[1,2,3,4,5]) //->where('goods_id',null) ->where('descriptopn','null','')//select * from 'ecm_goods' where 'descriptopn' is null ->where('descriptopn','')// 'descriptopn' = '' //特殊表达式 //->where("left(goods_name,2)='杰记'",'exp','')//expression 引号内可以写原生表达式 ,left是从左截取 //exp-表达式查询。原生的sql可以写在前面的参数或者后面的参数,唯一不能做的就是拆开写。 ->select();$result=Db:table('ecm_users')->where('add_time','> time',13570128000)->select(); $result=Db:table('ecm_users')->where('add_time','> time','2015/11/12')->select();时间比较(字符串或者数字)常用的符号> time< time>= time<= timebetween timenotbetween time【查询构造器】查询语句:数组查询不推荐使用['字段名1' =>['表达式'],['值'],'字段名2'=>['表达式','值']]$where=[ 'goods_id'=>['>',10], 'price' =>['<',50] ]; $map=[ 'goods_id'=>['>',20], 'goods_name'=>['like','%杰记%'] ]; $result=Db::table('ecm_goods') ->where($where) ->whereOr($map) ->select(); //执行的sql语句 SELECT * FROM `ecm_goods` WHERE `goods_id` > 10 AND `price` < 50 OR `goods_id` > 20 OR `goods_name` LIKE '%杰记%'【查询构造器】查询语句:闭包查询闭包查询(匿名函数),可以使用一次闭包就代表了加了一次括号$result=Db::table('ecm_goods') ->where(function($query){ $query->where('goods_id','between',[10,50]) ->whereOr('price','<',50); }) ->where('goods_name','like','%杰记%')->select(); //执行的sql语句 SELECT * FROM `ecm_goods` WHERE ( `goods_id` BETWEEN 10 AND 50 OR `price` < 50 ) AND `goods_name` LIKE '%杰记%' ->where(function($query){ $query->where(function($q){ $q->where('1=1') }) })闭包里还可以继续套闭包在闭包中使用变量需要在括号外添加use引入多层闭包需要多层引用$key='杰记'; $goods_id=10; $price=50; $result=Db::table('ecm_goods') ->where(function($query) use($goods_id,$price){ $query->where(function($q) ues($goods_id)P{ $q-where('goods_id','>',$goods_id) ->where('goods_id','<',80); }) ->whereOr('price','<',$price); }) ->where('goods_name','like','%'.$key.'%')->select(); >>END
2019年11月07日
188 阅读
0 评论
0 点赞
2019-11-06
tp5-数据库操作2
SQL中联表的三种方式内联,外联(左联-右联)左联与右联的区别:左联方式:在左表为主的数据和右表的数据展示出来右联方式:以右边为主查询数据,左表和右表有关联的数据展示出来,相同字段起别名区分。【链式操作】join*Db::table(表名)->alias(别名)->field(查找的字段)->join(要联的表名,字符串方式定义,不带数据表前缀的表名);参数1:要联的表名 ①数组方式定义,[' ```ecm_goods'=>'g'``` ],【任何时候都没有BUG】<br> ②字符串方式定义,‘ ```ecm_goods g``` ’ ,【当默认的表前缀与当前要联的表不一致时会自动加前缀,造成BUG】<br> ③不带数据表前缀的表名,‘ ```__GCATEGORY__ c``` ’ <br>参数2:联表的条件,按照where的条件定义方式来写 参数3:联表方式。LEFT、RIGHT、INNER(默认),当数据不存在时填充null :arrow_down_small:$field=['goods_id','goods_name','price','c.cate_id','cate_name','parent_id','g.if_show']; $result=Db::table('ecm_goods') ->alias('g') ->field($fielf) ->join(['ecm_gcategory'=>'c'],'g.cate_id=c.cate_id and c.if_show=1','LEFT') ->select();注意两个表相同的字段必须显示指明使用的哪个字段,如if_show 必须写成 g.if_show 注意两个表相同的字段作为where的查询条件时,如 if_show = 1 ,这个时候必须加别名或者表名指明是哪个表的字段 g.if_show = 1【链式操作】order*参数:排序的规则,逗号分隔的字符串或者数组$result=Db::table('ecm_goods') ->field(true) ->order('goods_id desc,add_time desc') ->select(); $result=Db::table('ecm_goods') ->field(true) ->order('goods_id'=>'desc','add_time'=>'desc') ->select(); $result=Db::table('ecm_goods') ->field(true) //->order(['goods_id'=>'desc']) //->order('add_time') ->orderRaw('rand()')//随机排序 //->find();只渲染一条数据 ->select();【链式操作】limit$result=Db::table('ecm_goods') ->field(true) ->limit('0,10') ->select(); $result=Db::table('ecm_goods') ->field(true) ->limit(0,10) ->select(); $result=Db::table('ecm_goods') ->field(true) ->limit(10) ->select();【链式操作】page,一般用于分页查询$result=Db::table('ecm_goods') ->field(true) ->page('2,10') ->select(); $result=Db::table('ecm_goods') ->field(true) ->page(2,10) ->select(); $result=Db::table('ecm_goods') ->field(true) ->page(2) ->limit(10) ->select();【链式操作】group,having$result = Db::table('ecm_goods') ->filed('goods_id,goods_name,cate_id,count(cate_id) as total') ->where('goods_id','<=',50) ->group('cate_id') ->having('total>5') ->select();【查询构造器】查询语言查询语言:2个方法(where,whereOr) 3个用法(表达式查询,数组查询,闭包查询)$result = Db::table('ecm_goods') //->filed(true) ->where('goods_id','>',1) ->where('price','<',10) ->select();$result = Db::table('ecm_goods') //->filed(true) ->where('goods_id','between','1,5') //->where('goods_id','between',[1,5]) //->where('goods_id','in','[1,2,3,5]') ->select();链式方法注意事项链式方法支持所有的CURD操作;链式方法本身只是返回查询对象,只有执行查询后才会返回结果,而且只能在查询方法之前被调用;不同链式方法的调用顺序不影响查询;相同链式方法的调用顺序可能会影响查询(至少会影响SQL语句)链式方法在完成查询后会自动失效;同一个链式方法在CURD操作中的作用可能不同;链式方法仅针对CURD方法,对原生查询无效;
2019年11月06日
98 阅读
0 评论
0 点赞
1
2