百搜论坛欢迎您的加入!
adimg adimg
 
昨日:篇  今日:篇   总帖:篇   会员:
今日:0    总帖:115
admin
1154
thinkphp实现自动采集功能的三种方法:方法一:QueryList个人感觉比较好用,采集详情比较不错的选择,但是采集复杂一点的列表,不好用。具体使用:控制器示例:123456789101112131415public function index(){    // 使用采集类    // 使用手册 :http://www.php.cn/php/php-QueryList3-ThinkPHP.html    import('Org.QL.QueryList');    $url = "http://www.zyctd.com/gqqg/";    $reg = array();    $reg['title'] = array('.sulist_title','text');    $reg['shuliang'] = array('.su_li1','html');    $obj = new \QueryList($url,$reg);    $data = $obj->jsonArr;    // foreach($data as $v){    //     echo "<br>".$v['title'].'___'.$v['shuliang']."<br>";    // }    p($data);}相关推荐:《ThinkPHP教程》方法二:simple_html_dom这个方法比较适合采集一点结构简单的页面,HTML标签的类名比较明确的页面,还不错。具体使用:控制器示例:1234567891011public function index(){    // 参考文档:http://microphp.us/plugins/public/microphp_res/simple_html_dom/manual.htm#section_quickstart    // 下载地址:https://github.com/samacs/simple_html_dom/edit/master/simple_html_dom.php    // 使用方法:http://www.thinkphp.cn/topic/21635.html    import("Org.Util.simple_html_dom", '', '.php');    $html = file_get_html('http://www.zyctd.com/gqqg/');    $ret = $html->find('.supply_list_box ul',0)->first_child();    foreach($ret as $v){        echo $v;    };}方法三:获取页面HTMl,进行正则匹配采集举例一个Demo:采集一个页面:http://www.zyctd.com/gqqg/我要获取上面的四个信息:标题,数量,时间,跳转链接。获取这些信息,通过上面两种方法都采集不到,最后才选用的正则来采集。具体方法:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566public function index(){    $url = "http://www.zyctd.com/gqqg/";    // http://www.zyctd.com/gqqg-p1.html    $supplyDB = M('supply');        $urlList = array();    $array = array();    for($x=1; $x<=1; $x++) {        array_push($urlList,"http://www.zyctd.com/gqqg-p".$x.".html");    };            foreach($urlList as $v){        $curPageList = $this->getInfo($v);        array_push($array,$curPageList);    };    foreach($array as $v){        foreach($v as $vv){            //echo $vv['title']."__".$vv['weight']."__".$vv['time']."<br>";            $data = array();            $data['title'] = $vv['title'];            $data['weight'] = $vv['weight'];            $data['add_time'] = $vv['add_time'];            $data['url'] = $vv['url'];            //$res = $supplyDB->add($data);            //echo $res;            echo "<p><span style='display:inline-block; width:110px;'>".$vv['title']."</span>            <span style='display:inline-block; width:110px;'>".$vv['weight']."</span>            <span style='display:inline-block; width:110px;'>".$vv['add_time']."</span>            <span style='display:inline-block; width:110px;'>".$vv['url']."</span></p>";        }    }        // 获取信息        //$curPageList = $this->getInfo($html);        //p($curPageList);}private function getInfo($url){    $html = $this->getHtml($url);    $array = array();    // 匹配所有的标题    preg_match_all("#<divclass=\"sulist_title\"><i></i><span>(.*?)</span></div>#",$html,$matches);    $all_title = $matches[1];    preg_match_all("#<i>发布时间:</i><span>(.*?)</span>#",$html,$matches);    // 匹配所有的发布时间    $all_time = $matches[1];    // 匹配所有的求购数量    preg_match_all("#<i>求购数量:</i><span>(.*?)</span>#",$html,$matches);    $all_weight = $matches[1];    // 匹配跳转链接    preg_match_all("#<atarget=\"_blank\"href=\"(.*?)\">#",$html,$matches);    $all_url = $matches[1];    // 组合    foreach($all_title as $k => $v){        $arr = array();        $arr['title'] = $v;        $arr['weight'] = $all_weight[$k];        $arr['add_time'] = $all_time[$k];        $arr['url'] = $all_url[$k];        array_push($array,$arr);    }    return $array;}private function getHtml($url){    $html = file_get_contents($url);    $html = preg_replace("#\n#","",$html);    $html = preg_replace("#\r#","",$html);    $html = preg_replace("#\\s#","",$html);    return $html;}以上就是thinkphp自动采集怎么实现的详细内容
0 0 1375天前
admin
1070
thinkphp5出现500错误,如下图所示:相关推荐:《ThinkPHP教程》12require(): open_basedir restriction in effect. File(/home/wwwroot/pic/thinkphp/start.php) is not within the allowed解决方法:1、我是lnmp1.4 php5.6,php.ini里面的open_basedir 是注释掉的。2、查找到是fastcgi问题。3、修改fastcgi的配置文件。1/usr/local/nginx/conf/fastcgi.conffastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";修改为1fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/../:/tmp/:/proc/";4、重启 service nginx restart。以上就是thinkphp5出现500错误怎么办的详细内容
0 0 1375天前
admin
1042
thinkphp入口文件放哪?ThinkPHP采用单一入口模式进行项目部署和访问,无论完成什么功能,一个应用都有一个统一(但不一定是唯一)的入口。应该说,所有应用都是从入口文件开始的,并且不同应用的入口文件是类似的。入口文件定义入口文件主要完成:定义框架路径、项目路径(可选)定义系统相关常量(可选)载入框架入口文件(必须)5.0默认的应用入口文件位于public/index.php,内容如下:1234// 定义应用目录define('APP_PATH', __DIR__ . '/../application/');// 加载框架引导文件require __DIR__ . '/../thinkphp/start.php';入口文件位置的设计是为了让应用部署更安全,public目录为web可访问目录,其他的文件都可以放到非WEB访问目录下面。修改入口文件位置请查看章节<部署-虚拟主机环境>入口文件中还可以定义一些系统变量,用于相关的绑定操作(通常用于多个入口的情况),这个会在后面涉及,暂且不提。给APP_PATH定义绝对路径会提高系统的加载效率。在有些情况下,你可能需要加载框架的基础引导文件base.php,该引导文件和start.php的区别是不会主动执行应用,而是需要自己进行应用执行,下面是一个例子:12345678// 定义应用目录define('APP_PATH', __DIR__ . '/../application/');// 加载框架基础引导文件require __DIR__ . '/../thinkphp/base.php';// 添加额外的代码// ...// 执行应用\think\App::run()->send();本文来自ThinkPHP框架技术文章栏目:http://www.php.cn/phpkj/thinkphp/以上就是thinkphp入口文件放哪的详细内容
0 0 1375天前
admin
1073
ThinkPHP 是一个免费、开源的,快速简单地面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷Web应用开发和简化企业级应用开发而诞生的。首先:Web服务器环境是:phpstudy集成安装包phpstudy安装目录:D:\mydata\phpstudyphpstudy的Web根目录:D:\mydata\phpstudy\data\PHPTutorial\WWW1、下载并运行composer,找到php.exe的位置2、打开php.ini文件,开启openssl扩展。去掉extension=php_openssl.dll前面的分号3、下载composer.phar,将composer.phar文件放入php目录下,在php目录下新建一个文件composer.cmd,内容写成:@php “%~dp0composer.phar” %*保存。运行这个文件,然后打开cmd运行:composer会出现:4、打开命令行窗口,执行如下命令:1composer config -g repo.packagist composer https://packagist.phpcomposer.com注意:最近phpcomposer镜像存在问题,可以改成1composer config -g repo.packagist composer https://packagist.laravel-china.org然后在命令行下面,切换到你的web根目录下面并执行下面的命令:1composer create-project topthink/think=5.0.*  tp5  --prefer-dist5.1版本安装使用下面的指令即可1composer create-project topthink/think  tp5  --prefer-dist完成!想学习更多相关问题,请访问php中文网:thinkphp教程以上就是win10如何安装thinkphp的详细内容
0 0 1375天前
admin
1068
首先,介绍一下什么是模型(model)、视图(view)、控制器(controller)。模型(model)——负责存储系统的中心数据;视图(view)——将信息显示给用户;控制器(controller)——处理用户输入的信息,负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中处理用户交互的部分。负责管理与用户交互交互控制;视图和控制器共同构成了用户接口。且每个视图都有一个相关的控制器组件。控制器接受输入,通常作为将鼠标移动、鼠标按钮的活动或键盘输入编码的时间。时间被翻译成模型或试图的服务器请求。用户仅仅通过控制器与系统交互。结构:模型组件包含应用程序的功能内核,他封装了相应的数据并输出执行特定应用程序处理的过程;模型也提供访问数据的函数,这些数据有获得待显示的数据的视图组件使用。控制器代表用户调用所有这些过程。目的:实现一种动态的程序设计,是后序对程序的修改和扩展简化,并且使程序某一部分的重复利用称为可能。通过对复杂度的简化,使程序结构更加直观。将信息的内部表示与信息的呈现方式分离开来,并接受用户的请求。它分离了组件,并允许有效的代码重用。即,将模型和视图的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保模型和视图的同步,一旦模型改变,视图应该同步更新。以上内容仅供参考!推荐教程:ThinkPHP教程以上就是thinkphp的模型,控制器,视图,是什么的详细内容
0 0 1375天前
admin
1214
thinkphp富文本编辑器实现上传图片的方法步骤为:1、首先,实现文章发布或编辑的form表单,初始化layui富文本编辑器,效果如下:文章发布表单对应的HTML代码如下:2、其中是layedit的目标元素,建立编辑器以及表单提交的js代码如下:实现layedit插入图片接口需要在建立编辑器之前配置uploadImage,本例中配置代码如上图JS代码所示。3、layedit不提供服务端的图片接受,需要我们在接口中实现,图片上传成功后返回指定格式的JSON信息,格式如下:12345678{    "code": 0, //0表示成功,其它失败    "msg": "", //提示信息 //一般上传失败后返回    "data": {        "src": "图片路径",        "title": "图片名称" //可选    }}4、本例中用thinkPHP5实现编辑器插入图片接口的代码如下:我创建了一个资源上传的控制器,专门用来处理文件上传相关业务,其中有关thinkPHP5上传文件的代码请参考TP的官方文档,这里不做过多解释。5、然后,发布一篇科技互联网新闻,演示一下效果。在第一段后面添加一张图片,提交后效果如下:以上内容仅供参考!推荐教程:thinkphp教程以上就是thinkphp富文本编辑器如何实现上传图片的详细内容
0 0 1375天前
admin
1020
日志记录\ThinkPHP\Lib\Think\Core\Log.class.php (推荐学习:thinkphp5)1、可以在config.php中进行设置,默认为关闭状态。 'APP_DEBUG' => true打开\ThinkPHP\Common\debug.php文件可以查看debug的默认设置如下:123456789101112return array('LOG_RECORD'=>true, // 进行日志记录'LOG_RECORD_LEVEL' => array('EMERG','ALERT','CRIT','ERR','WARN','NOTIC','INFO','DEBUG','SQL'), // 允许记录的日志级别'DB_FIELDS_CACHE'=> false, //数据库字段缓存'SHOW_RUN_TIME'=>true, // 运行时间显示'SHOW_ADV_TIME'=>true, // 显示详细的运行时间'SHOW_DB_TIMES'=>true, // 显示数据库查询和写入次数'SHOW_CACHE_TIMES'=>true, // 显示缓存操作次数'SHOW_USE_MEM'=>true, // 显示内存开销'SHOW_PAGE_TRACE'=>true, // 显示页面Trace信息 由Trace文件定义和Action操作赋值'APP_FILE_CASE' => true, // 是否检查文件的大小写 对Windows平台有效);注意事项:DB_FIELDS_CACHE数据库字段缓存默认关闭状态,如果开启的话,会在Runtime\Data文件夹下生成文件缓存,并且修改表之后,如新加了字段,这个缓存无法记录你的操作,需要我们手动删除一次,对表的修改才会成功。如果只想显示一部分提示信息,如运行时间,内存开销等,可以在config.php中进行相应的设置即可,如:123456//'APP_DEBUG' => true, // 调试模式开关'SHOW_RUN_TIME' => true, //运行时间显示'SHOW_ADV_TIME' => true, //显示详细的运行时间'SHOW_DB_TIMES' => true, //显示数据库的操作次数'SHOW_CACHE_TIMES'=>true, //显示缓存操作次数'SHOW_USE_MEM' => true, //显示内存开销以上就是thinkphp错误日志在哪的详细内容
0 0 1375天前
admin
998
之前写过一篇文章讲了 PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsapi支付)流程。当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但应用到框架中,还是有一些问题,在ThinkPHP中,由于路由规则与支付授权目录有出入,所以会报错。本篇讲讲在TP中集成微信支付的流程。鹅厂出的SDK和文档,就是让你看不懂,使劲绕,这酸爽用了就知道。文档和SDK不是应该越简单通俗易懂越好么?难道只有使劲重构才能显示出鹅厂程序猿技术的高超咩?额...是不是暴露了我菜鸟的属性...其实SDK蛮好用,只是上一篇文章中也看到了,在支付完成回调函数中,着实让人绕的晕头转向。对于不想被官方绕的,想在TP中使用微信支付的可以看看一个大神自己根据官方文档重构精简打造而成的适用于TP的支付SDK,源码我下载下来看过了,代码写的很优雅简介,流程也很简单,通俗易懂。我自己还是皱着眉头,使用了官方的SDK,也成功实现了支付,下面跟大家分享一下流程:1.SDK下载和修改这个就不过多讲了,不知道的可以看看我的上一篇博文:PHP实现微信支付(jsapi支付)流程,里边详细详述了下载下来的文件哪些是需要修改的。2.公众号设置A. 还是需要设置网页授权域名,这个没啥特殊的;B. 这里要注意一下支付授权目录,使用TP很多人都使用的是重写模式(REWRITE模式)或者在使用REWRITE模式的同时,使用伪静态模式,这时候生成的链接为:[http://serverName/Home/Blog/read/id/1];如果使用的是PATHINFO模式的话,生成的链接就是:[http://serverName/index.php/Home/Blog/read/id/1],比如在Home模块下的Blog控制器中的某个方法进行支付,我们支付的授权目录应该是[http://serverName/Home/Blog/]或者[http://serverName/index.php/Home/Blog/],这个根据自己的TP的设置的URL模式而定。3.支付流程(1)统一下单下单的支付参数配置,这个跟上一篇讲的基本不变,重点注意的是支付回调验证链接,因为要多次调用,我就直接在Application/Common/Common/function.php中将参数配置封装起来了,我的SDK放在项目根目录下的Api目录下,所以引入SDK的时候不是使用Vendor函数。123456789101112131415161718192021222324252627282930313233/** * 微信支付 * @param  string   $openId openid * @param  string   $goods 商品名称 * @param  string   $attach 附加参数,我们可以选择传递一个参数,比如订单ID * @param  string   $order_sn订单号 * @param  string   $total_fee  金额 */function wxpay($openId,$goods,$order_sn,$total_fee,$attach){require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";require_once APP_ROOT."/Api/wxpay/payment/WxPay.JsApiPay.php";require_once APP_ROOT.'/Api/wxpay/payment/log.php';//初始化日志$logHandler= new CLogFileHandler(APP_ROOT."/Api/wxpay/logs/".date('Y-m-d').'.log');$log = Log::Init($logHandler, 15);$tools = new JsApiPay();if(empty($openId)) $openId = $tools->GetOpenid();$input = new WxPayUnifiedOrder();$input->SetBody($goods);//商品名称$input->SetAttach($attach);//附加参数,可填可不填,填写的话,里边字符串不能出现空格$input->SetOut_trade_no($order_sn);//订单号$input->SetTotal_fee($total_fee);//支付金额,单位:分$input->SetTime_start(date("YmdHis"));//支付发起时间$input->SetTime_expire(date("YmdHis", time() + 600));//支付超时$input->SetGoods_tag("test3");//$input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php");  //支付回调验证地址$input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php/WexinApi/WeixinPay/notify");$input->SetTrade_type("JSAPI");//支付类型$input->SetOpenid($openId);//用户openID$order = WxPayApi::unifiedOrder($input);//统一下单$jsApiParameters = $tools->GetJsApiParameters($order);return $jsApiParameters;}注意,注意,敲黑板划重点了:支付回调验证链接,必须是没有权限验证的,如果你自己访问那个链接,还需要登录注册验证的,就不要尝试了,必须要可以无障碍访问的链接,而且也不要有一连串的参数传递。最好就是简单粗暴的[http://serverName/xxx.php],我在跟目录下,类似于index.php,重新写了一个专门的供支付回调的入口文件payment.php,和它对应的Application/目录下的模块(WexinApi)、控制器(WeixinPay)及方法(notify):12345678910111213141516171819// 检测PHP环境if(version_compare(PHP_VERSION,'5.3.0','<'))  die('require PHP > 5.3.0 !');    // $_GET['m']='Admin';// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为falsedefine('APP_DEBUG',True);//指定模块控制器和方法$_GET['m']='WexinApi';$_GET['c']='WeixinPay';$_GET['a']='notify';// 定义应用目录define('APP_PATH','./Application/');define("APP_ROOT",dirname(__FILE__));// 引入ThinkPHP入口文件  require './ThinkCore/ThinkCore.php';  // 亲^_^ 后面不需要任何代码了 就是如此简单现在访问[http://serverName/payment.php],就会直接进入到[http://serverName/payment.php/WexinApi/WeixinPay/notify],这样回调验证链接可以写[http://serverName/payment.php],也可以写[http://serverName/payment.php/WexinApi/WeixinPay/notify]。(2)发起支付照样很简单:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566/*** 支付测试* 微信访问:http://daoshi.sdxiaochengxu.com/payment.php/WexinApi/WeixinPay/pay*/public function pay(){$order_sn = getrand_num(true);$openId = '';$jsApiParameters = wxpay($openId,'江南极客',$order_sn,1);$this->assign(array('data' => $jsApiParameters));$this->display();}<html><head>    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>    <meta name="viewport" content="width=device-width, initial-scale=1"/>     <title>小尤支付测试</title>    <script type="text/javascript">//调用微信JS api 支付function jsApiCall(){var data={$data};WeixinJSBridge.invoke('getBrandWCPayRequest', data, function(res){WeixinJSBridge.log(res.err_msg);//alert('err_code:'+res.err_code+'err_desc:'+res.err_desc+'err_msg:'+res.err_msg);//alert(res.err_code+res.err_desc+res.err_msg);//alert(res);    if(res.err_msg == "get_brand_wcpay_request:ok"){      alert("支付成功!");window.location.href="http://m.blog.csdn.net/article/details?id=72765676";    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){      alert("用户取消支付!");      }else{      alert("支付失败!");      }  });}  function callpay(){if (typeof WeixinJSBridge == "undefined"){    if( document.addEventListener ){        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);    }else if (document.attachEvent){        document.attachEvent('WeixinJSBridgeReady', jsApiCall);         document.attachEvent('onWeixinJSBridgeReady', jsApiCall);    }}else{    jsApiCall();}}</script></head><body>    <br/>    <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/><font color="#9ACD32"><b><span style="color:#f00;font-size:50px;margin-left:40%;">1分</span>钱也是爱</b></font><br/><br/><div align="center"><button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" οnclick="callpay()" >果断买买买^_^</button></div></body></html>不过支付页面的URL要注意了,因为支付页面的URL肯定带有不少参数,刚才说了TP中使用的REWRITE模式,你的链接为类似[http://serverName/Home/Blog/read/id/1]这样的,可能带有更多参数,这时候微信支付会认为你的支付授权目录是[http://serverName/Home/Blog/read/id/],但是你真实的授权目录是[http://serverName/Home/Blog/],所以就会报错。处理方法就是,在进入支付页面的时候,重构URL,写成普通模式,即为[http://serverName/Home/Blog/read?id=1],这样就可以了。(3)支持成功回调现在支付完成,就会进入到之前写好的链接对应的方法,即[http://serverName/payment.php/WexinApi/WeixinPay/notify]:12345678910111213141516171819202122232425262728293031323334353637//微信支付回调验证public function notify(){$xml = $GLOBALS['HTTP_RAW_POST_DATA'];// 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了file_put_contents('./Api/wxpay/logs/log.txt',$xml,FILE_APPEND);//将服务器返回的XML数据转化为数组//$data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);$data = xmlToArray($xml);// 保存微信服务器返回的签名sign$data_sign = $data['sign'];// sign不参与签名算法unset($data['sign']);$sign = $this->makeSign($data);// 判断签名是否正确  判断支付状态if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {$result = $data;// 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了file_put_contents('./Api/wxpay/logs/log1.txt',$xml,FILE_APPEND);//获取服务器返回的数据$order_sn = $data['out_trade_no'];//订单单号$order_id = $data['attach'];//附加参数,选择传递订单ID$openid = $data['openid'];//付款人openID$total_fee = $data['total_fee'];//付款金额//更新数据库$this->updateDB($order_id,$order_sn,$openid,$total_fee);}else{$result = false;}// 返回状态给微信服务器if ($result) {$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';}else{$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';}echo $str;return $result;}为了安全起见,对返回过来的签名,要重新验证:1234567891011121314151617181920212223/*** 生成签名* @return 签名,本函数不覆盖sign成员变量*/protected function makeSign($data){//获取微信支付秘钥require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";$key = \WxPayConfig::KEY;// 去空$data=array_filter($data);//签名步骤一:按字典序排序参数ksort($data);$string_a=http_build_query($data);$string_a=urldecode($string_a);//签名步骤二:在string后加入KEY//$config=$this->config;$string_sign_temp=$string_a."&key=".$key;//签名步骤三:MD5加密$sign = md5($string_sign_temp);// 签名步骤四:所有字符转为大写$result=strtoupper($sign);return $result;}至此,TP中微信支付也就搞定了。这是集成了官方的SDK实现的,如果不使用SDK,可以使用更简单的方法,见:PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)以上就是ThinkPHP中实现微信支付(jsapi支付)流程的详细内容
0 0 1375天前
admin
1005
ThinkPHP6.0中间件分为系统中间件和应用中间件,系统中间件为核心框架内置的中间件,应用中间件是在应用里面创建的中间件。中间件的主要应用场景可以包括对HTTP请求的数据过滤、权限检测、请求拦截等行为,使用中间件能够让控制器的定义更加简单,很多额外的非核心业务流程的处理都可以交给中间件执行。从中间件的使用范围来看,可以分为全局中间件、应用中间件、控制器中间件和路由中间件。全局中间件全局中间件是在app\middleware.php中定义的中间件,默认没有启用任何中间件,但对支持的系统中间件做了注释,你只需要取消注释就可以使用相应的系统中间件,默认内容如下:12345678910return [    // 全局请求缓存    // 'think\middleware\CheckRequestCache',    // 多语言加载    // 'think\middleware\LoadLangPack',    // Session初始化    // 'think\middleware\SessionInit',    // 页面Trace调试    // 'think\middleware\TraceDebug',];系统的部分功能交给中间件进行统一管理,包括全局请求缓存、多语言的自动检测和加载、Session初始化和页面Trace调试,也就是说,默认安装后的应用是不支持Session的,你必须全局开启Session初始化中间件后Session才能生效。对于API应用来说,本身就不需要Session功能支持。你可以在全局中间件定义文件中添加你的应用中间件,但尽可能确保系统中间件的优先执行,中间件定义需要使用完整的类名,通过命令行指令可以快速创建一个应用中间件:1php think make:middleware Test会自动生成一个app\middleware\Test中间件类,内容如下:12345678<?phpnamespace app\middleware;class Test{    public function handle($request, \Closure $next)    {    }}也支持通过指定完整命名空间的方式创建中间件类1php think make:middleware app\middleware\Hello我们添加一个测试输出123456789101112<?phpnamespace app\middleware;class Test{    public function handle($request, \Closure $next)    {    echo 'Before Middleware<br/>';    $response = $next($request);    echo 'After Middleware<br/>';    return $response;    }}中间件handle方法的返回值必须是一个Response对象。然后在全局中间件定义中添加123return [\app\middleware\Test::class,];假设我们要访问的控制器方法为123456789<?phpnamespace app\controller;class Index{    public function hello()    {    return 'Hello,ThinkPHP!<br/>';    }}访问该操作方法的输出为123Before MiddlewareHello,ThinkPHP!After Middleware你可以看出中间件的执行过程,从执行流程上可以分为前置中间件和后置中间件,当然,一个中间件可能同时有前置和后置行为,上面的Test中间件就是如此。 $next($request)之前的代码属于前置中间件范畴,之后的代码则属于后置中间件范畴。应用中间件如果是多应用模式的话,应用中间件就是在app\应用名\middleware.php中定义的中间件,只会在该应用下有效,定义格式和全局中间件一致。路由中间件路由中间件则表示仅在路由匹配之后才会执行某个中间件,在路由定义中使用middleware方法定义,例如:12Route::get('hello/:name','index/hello')    ->middleware(\app\middleware\Hello::class);可以给路由分组定义中间件1234Route::group(function(){Route::get('hello/:name','index/hello');//...})->middleware(\app\middleware\Hello::class);如果要执行多个中间件,可以使用1234Route::group(function(){Route::get('hello/:name','index/hello');//...})->middleware([\app\middleware\Hello::class,\app\middleware\Check::class]);对于经常要使用的中间件,我们可以定义一个别名,在config\middleware.php配置文件中,设置1234return ['hello'=>\app\middleware\Hello::class,'check'=>\app\middleware\Check::class,];路由定义可以改为:1234Route::group(function(){Route::get('hello/:name','index/hello');//...})->middleware(['hello','check']);支持给一组中间件定义别名123return ['test'=>[\app\middleware\Hello::class,\app\middleware\Check::class],];路由定义可以改为1234Route::group(function(){Route::get('hello/:name','index/hello');//...})->middleware('test');中间件支持传入一个参数,中间件定义如下:12345678910<?phpnamespace app\middleware;class Hello{    public function handle($request, \Closure $next, string $name = '')    {    echo 'Hello'. $name . '<br/>';    return $next($request);    }}可以在路由中间件的第二个参数传入name参数12Route::get('hello/:name','index/hello')    ->middleware('hello', 'middleware');除了支持参数外,你可以在中间件的handle方法中使用依赖注入。控制器中间件控制器中间件仅当访问某个控制器的时候生效12345678910<?phpnamespace app\controller;class Hello{protected $middleware = ['hello','check'];    public function index()    {    return 'Hello,ThinkPHP!<br/>';    }}由于前面已经定义了中间件别名,所以这里直接使用别名定义,否则你必须使用完整的命名空间定义。默认情况下,控制器中定义的中间件访问控制器的任何操作方法都会执行,有时候并不希望所有的操作都需要执行中间件,有两种方式来定义控制器中间件的执行过滤。1234567891011121314151617<?phpnamespace app\controller;class Index{protected $middleware = ['hello' => ['only'  => ['hello']],'check' => ['except'=> ['hello']],];    public function hello()    {    return 'Hello,ThinkPHP!<br/>';    }    public function check()    {    return 'this action require check!<br/>';    }    }hello中间件仅在执行Index控制器的hello操作的时候才会执行,而check中间件除了hello方法外,都会执行,具体效果你可以实际测试下。中间件传参中间件和控制器之间传参的方式有很多,一个简单的方法是使用Request来进行传参。1234567891011<?phpnamespace app\middleware;class Hello{    public function handle($request, \Closure $next)    {        $request->hello = 'ThinkPHP';                 return $next($request);    }}中间件向控制器传参必须在前置中间件完成,后置中间件向控制器的传参控制器无法接收。然后在控制器的方法里面可以直接使用1234public function index(Request $request){return $request->hello; // ThinkPHP}众多ThinkPHP教程视频,尽在PHP中文网,欢迎在线学习!本文转自:https://www.php.cn/phpkj/thinkphp/以上就是一文了解ThinkPHP6.0之中间件的详细内容
0 0 1375天前
admin
936
在最新的6.0版本中引入了新的事件系统用以替代5.1版本的行为,同时也接管了数据库事件和模型事件。本篇主要描述下新版的事件系统以及查询事件、模型事件的使用。定义事件事件系统的所有操作都通过think\facade\Event类进行静态调用事件系统使用了观察者模式,提供了解耦应用的更好方式。在你需要监听事件的位置,添加如下代码:1Event::trigger('UserLogin');或者使用助手函数1event('UserLogin');这里UserLogin表示一个事件标识,如果你定义了单独的事件类,你可以使用事件类名,甚至可以传入一个事件类实例。1event('app\event\UserLogin');事件类可以通过命令行快速生成1php think make:event UserLogin默认会生成一个app\event\UserLogin事件类,也可以指定完整类名生成。我们可以给事件类添加方法12345678910namespace app\event;use app\model\User;class UserLogin{    public $user;    public function __construct(User $user)    {        $this->user = $user;    }}一般事件类无需继承任何其它类。你可以给事件类绑定一个事件标识1Event::bind('UserLogin', 'app\event\UserLogin');或者在应用的event.php事件定义文件中批量绑定。123456return [    'bind'    =>    [        'UserLogin' => 'app\event\UserLogin',        // 更多事件绑定    ],];如果你没有定义事件类的话,则无需绑定。ThinkPHP的事件系统不依赖事件类,如果没有额外的需求,仅通过事件标识也可以使用。你可以在event方法中传入一个事件参数1event('UserLogin', $user);事件监听你可以手动注册一个事件监听123Event::listen('UserLogin', function($user) {    // });或者使用监听类1Event::listen('UserLogin', 'app\listener\UserLogin');可以通过命令行快速生成一个事件监听类1php think make:listener UserLogin默认会生成一个app\listener\UserLogin事件监听类,也可以指定完整类名生成。事件监听类只需要定义一个handler方法,支持依赖注入。123456789<?phpnamespace app\listener;class UserLogin{    public function handle($user)    {        // 事件监听处理    }   }在handler方法中如果返回了false,则表示监听中止,将不再执行该事件后面的监听。一般建议直接在事件定义文件中定义对应事件的监听。12345678910return [    'bind'    =>    [        'UserLogin' => 'app\event\UserLogin',        // 更多事件绑定    ],    'listen'  =>    [        'UserLogin'    =>    ['\app\listener\UserLogin'],        // 更多事件监听    ],];事件订阅可以通过事件订阅机制,在一个监听器中监听多个事件,例如通过命令行生成一个事件订阅者类,1php think make:subscribe User默认会生成app\subscribe\User类,或者你可以指定完整类名生成。然后你可以在事件订阅类中添加不同事件的监听方法,例如:12345678910111213<?phpnamespace app\subscribe;class User{    public function onUserLogin($user)    {        // 事件响应处理    }    public function onUserLogout($user)    {        // 事件响应处理    }}监听事件的方法命名规范是on+事件标识(驼峰命名),然后注册该事件订阅1Event::subscribe('app\subscribe\User');一般建议直接在事件定义文件中定义1234567891011121314return [    'bind'    =>    [        'UserLogin' => 'app\event\UserLogin',        // 更多事件绑定    ],    'listen'  =>    [        'UserLogin'    =>    ['\app\listener\UserLogin'],        // 更多事件监听    ],    'subscribe'    =>    [       '\app\subscribe\User',        // 更多事件订阅    ],];内置事件内置的系统事件包括:AppInit事件定义必须在全局事件定义文件中定义,其它事件支持在应用的事件定义文件中定义。原来5.1的一些行为标签已经废弃,所有取消的标签都可以使用中间件更好的替代。可以把中间件看成处理请求以及响应输出相关的特殊事件。事实上,中间件的handle方法只是具有特殊的参数以及返回值而已。查询事件数据库操作的回调也称为查询事件,是针对数据库的CURD操作而设计的回调方法,主要包括:使用下面的方法注册数据库查询事件1234\think\facade\Db::event('before_select', function ($query) {    // 事件处理    return $result;});同一个查询事件可以注册多个响应执行。查询事件在新版里面也已经被事件系统接管了,因此如果你注册了一个before_select查询事件监听,底层其实是向标识为db.before_select的事件注册了一个监听。查询事件的方法参数只有一个:当前的查询对象。但你可以通过依赖注入的方式添加额外的参数。模型事件模型事件是指在进行模型的查询和写入操作的时候触发的操作行为。模型事件只在调用模型的方法生效,使用查询构造器操作是无效的。模型支持如下事件:注册的回调方法支持传入一个参数(当前的模型对象实例),但支持依赖注入的方式增加额外参数。如果before_write、before_insert、 before_update 、before_delete事件方法中返回false或者抛出think\exception\ModelEventException异常的话,则不会继续执行后续的操作。模型事件定义最简单的方式是在模型类里面定义静态方法来定义模型的相关事件响应。123456789101112131415161718<?phpnamespace app\index\model;use think\Model;use app\index\model\Profile;class User extends Model{    public static function onBeforeUpdate($user)    {    if ('thinkphp' == $user->name) {        return false;        }    }         public static function onAfterDelete($user)    {Profile::destroy($user->id);    }}参数是当前的模型对象实例,支持使用依赖注入传入更多的参数。模型事件观察者如果希望模型的事件单独管理,可以给模型注册一个事件观察者,例如:1234567<?phpnamespace app\index\model;use think\Model;class User extends Model{    protected $observerClass = 'app\index\observer\User';}User观察者类定义如下:1234567891011121314151617<?phpnamespace app\index\observer;use app\index\model\Profile;class User{    public function onBeforeUpdate($user)    {    if ('thinkphp' == $user->name) {        return false;        }    }         public function onAfterDelete($user)    {Profile::destroy($user->id);    }}观察者类的事件响应方法的第一个参数就是模型对象实例,你依然可以通过依赖注入传入其它的对象参数。PHP中文网,大量的免费ThinkPHP入门教程,欢迎在线学习!本文转自:https://blog.thinkphp.cn/1037387以上就是ThinkPHP6.0:事件系统以及查询事件、模型事件的使用的详细内容
0 0 1375天前
admin
1105
用过5.0的开发者都比较依赖5.0的数组查询方式,但是很无奈5.1的数组查询方式和5.0的区别很大,因此经常听到开发者抱怨5.1的数组查询不好用。首先,出于安全和易用性的原因,官方是不推荐使用数组查询条件的,其次,你也许不知道5.1版本其实提供了一个新的数组对象查询的方式用以替代之前的数组条件。如果你的版本是V5.1.21+的话,那么可以尝试下面提到的数组对象查询方式,一定会有意外的惊喜^_^对于习惯或者重度依赖数组查询条件的用户来说,可以选择数组对象查询,该对象完成了普通数组方式查询和系统的查询表达式之间的桥接,但相较于系统推荐的查询表达式方式而言,需要注意变量的安全性,避免产生SQL注入的情况。要使用数组对象查询,你首先需要引入think\db\Where类。1use think\db\Where;Where对象的用法一般有两种,第一种最简单,你依然和5.0一样使用数组条件进行定义查询条件,例如:123456$map = [    'name' => ['like', 'thinkphp%'],    'title' => ['like', '%think%'],    'id' => ['>', 10],    'status' => 1,];然后,在实际使用where方法的时候改为123Db::name('user')    ->where(new Where($map))    ->select();生成的SQL是:1SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND `title` LIKE '%think%' AND `id` > 10 AND `status` =1这种方式最容易改造,相当于一键切换到5.0的数组查询方式。当然,除了Db查询之外,模型查询也一样可以支持。第二种方式是,直接实例化一个Where对象,然后在where方法查询的时候直接传入该Where对象实例。123456$where = new Where;$where['id'] = ['in', [1, 2, 3]];$where['title'] = ['like', '%php%'];Db::name('user')    ->where($where)    ->select();Where对象实现了ArrayAccess接口,因此可以直接当成数组来赋值。生成的SQL是:1SELECT * FROM `think_user` WHERE   `id` IN (1,2,3) AND `title` LIKE '%php%'使用Where对象查询可以和其它的查询方式混合使用。如果你在混合使用数组查询对象的时候,希望某个数组查询对象的查询条件加上括号,可以使用1234567$where          = new Where;$where['id']    = ['in', [1, 2, 3]];$where['title'] = ['like', '%php%'];Db::name('user')    ->where($where->enclose())    ->where('status', 1)    ->select();生成的SQL是:1SELECT * FROM `think_user` WHERE  ( `id` IN (1,2,3) AND `title` LIKE '%php%' ) AND  `status` =1enclose方法表示该查询条件两边会加上括号包起来。使用数组对象查询的情况请一定要注意做好数据类型检查,尽量避免让用户决定你的数据,从而导致SQL注入的可能。PHP中文网,有大量免费的ThinkPHP入门教程,欢迎大家学习!本文转自:https://blog.thinkphp.cn/778497以上就是ThinkPHP5.1:数组对象查询的使用的详细内容
0 0 1375天前
admin
1136
Thinkphp6.0从2019年10月24日正式发布,相对测试版,有很多变动,目前TP6已经相对比较稳定了,所以php中文网在2020年再次重新录制课程,帮助同学们快速入门,欢迎学习!免费的哦!课程名称:Thinkphp6.0正式版视频教程课程地址:https://www.php.cn/course/1086.html发布时间:2020年元月二日相关推荐:1.《ThinkPHP6.0完全开发手册(注解版) 》2.《ThinkPHP 5.1全球首发视频教程》3.2020年最新的10个thinkphp视频教程推荐以上就是今日新课推荐:《Thinkphp6.0正式版视频教程》的详细内容
0 0 1375天前
admin
1033
下面由ThinkPHP教程栏目给给大家介绍ThinkPHP5+jQuery+MySql实现投票功能的方法,希望对需要的朋友也是帮助!首先效果图如下:然后分享代码如下:前端代码:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>基于THINKPHP5实现红蓝投票功能</title><style type="text/css">    .vote{width:288px; height:300px; margin:40px auto;position:relative}    .votetitle{width:100%;height:62px; background:url(/static/index/images/icon.png) no-repeat 0 30px; font-size:15px}    .red{position:absolute; left:0; top:64px; height:80px;}    .blue{position:absolute; right:0; top:64px; height:80px;}    .red p,.blue p{line-height:22px}    .redhand{position:absolute; left:0;width:36px; height:36px; background:url(/static/index/images/icon.png) no-repeat -1px -38px;cursor:pointer}    .bluehand{position:absolute; right:0;width:36px; height:36px; background:url(/static/index/images/icon.png) no-repeat -41px -38px;cursor:pointer}    .grayhand{width:34px; height:34px; background:url(/static/index/images/icon.png) no-repeat -83px -38px;cursor:pointer}    .redbar{position:absolute; left:42px; margin-top:8px;}    .bluebar{position:absolute; right:42px; margin-top:8px; }    .redbar span{display:block; height:6px; background:red; width:100%;border-radius:4px;}    .bluebar span{display:block; height:6px; background:#09f; width:100%;border-radius:4px; position:absolute; right:0}    .redbar p{line-height:20px; color:red;}    .bluebar p{line-height:20px; color:#09f; text-align:right; margin-top:6px}</style><script type="text/javascript" src="/static/index/js/jquery.js"></script><script type="text/javascript">$(function(){    // 获取初始数据    getdata('',1);         $(".redhand").click(function(){        getdata("red",1);    });    $(".bluehand").click(function(){        getdata("blue",1);    });});function getdata(type,vid){    $.ajax({      url: "{:url('/index/vote/vote')}",      data: {type:type,vid:vid},      type:'POST',      dataType: 'json',      success: function (res) {          console.log(res)          if (res.status == 0) {              alert('投票成功')              var w = 208;            $("#red_num").html(res.msg.rednum);            $("#red").css("width",res.msg.red_percent*100+"%");            var red_bar_w = w*res.msg.red_percent-10;            $("#red_bar").css("width",red_bar_w);            $("#blue_num").html(res.msg.bluenum);            $("#blue").css("width",res.msg.blue_percent*100+"%");            var blue_bar_w = w*res.msg.blue_percent;            $("#blue_bar").css("width",blue_bar_w);          }else{              alert('投票失败');          }      }    });}</script></head><body><div id="main">   <h2 class="top_title"><a href="http://www.jb51.net/article/71504.htm">ThinkPHP5+jQuery+MySql实现红蓝投票功能</a></h2>   <div class="vote">        <div class="votetitle">您对Thinkphp5的看法?</div>        <div class="red" id="red">            <p>非常实用</p>            <div class="redhand"></div>            <div class="redbar" id="red_bar">                <span></span>                <p id="red_num"></p>            </div>        </div>        <div class="blue" id="blue">            <p style="text-align:right">完全不懂</p>            <div class="bluehand"></div>            <div class="bluebar" id="blue_bar">                <span></span>                <p id="blue_num"></p>            </div>        </div>   </div></div></body></html>控制器:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263<?phpnamespace app\index\controller;use think\Controller;/** * 投票 */class Vote extends Controller{    /**     * 首页     */    public function index()    {        return $this->fetch();    }    /**     * 投票     * @param vid type ip     */    public function Vote()    {        $data = input('post.');        if (!empty($data)) {            $data['ip'] = get_ip();    //获取Ip            // 先检测当前ip是否已经投过票            $count = model('Vote')->checkIp($data);            // 检测是否提交了type,提交了即代表点击了按钮,没提交即代表页面初次渲染            if (!empty($data['type'])) {                if ($count == '0') {    //当前还未投过票                     // 更新票数  添加用户ip表                    $res = model('Vote')->postVote($data);                    if ($res) {                                                 // 投票成功  获取当前各自的票数                        $info = $this->getPercent($data);                        return return_succ($info);                    }else{                        return return_error('投票失败');                    }                }else{                    // 已经投过票                    return return_error('您已经投过票了');                }            }else{                // 初次渲染,获取初始数据                $info = $this->getPercent($data);                return return_succ($info);            }        }else{            return return_error('数据不能为空');        }    }    // 计算比例    public function getPercent($data)    {        // 投票成功  获取当前各自的票数        $info = model('Vote')->getInfo($data);        // 计算比例 保留3位小数        $info['red_percent'] = round($info['rednum'] / ($info['rednum'] + $info['bluenum']),3);        $info['blue_percent'] = 1 - $info['red_percent'];        return $info;    }}模型:1234567891011121314151617181920212223242526272829303132333435363738394041424344<?phpnamespace app\index\model;use think\Model;use think\Db;class Vote extends Model{    // 检测当前ip是否已经投过票    public function checkIp($data)    {        $res = Db::table('votes_ip')->where(['vid'=>$data['vid'],'ip'=>$data['ip']])->count();        return $res;    }    // 投票    public function postVote($data)    {        $info = $this->getInfo($data);        if ($info) {            Db::startTrans();            try {                                 if ($data['type'] == "red") {                    // 更新票数表                      Db::table('votes')->where(['id'=>$data['vid']])->update(['rednum'=>$info['rednum']+1]);                }elseif ($data['type'] == "blue") {                    Db::table('votes')->where(['id'=>$data['vid']])->update(['bluenum'=>$info['bluenum']+1]);                }                // 添加用户投票ip                Db::table('votes_ip')->insert(['vid'=>$data['vid'],'ip'=>$data['ip']]);                Db::commit();                return true;            } catch (Exception $e) {                Db::rollback();                return false;            }        }    }    // 获取当前各自的票数    public function getInfo($data)    {        // 获取各自的票数        $info = Db::table('votes')->where(['id'=>$data['vid']])->find();        return $info;    }}以上就是ThinkPHP5+jQuery+MySql实现投票功能的方法的详细内容
0 0 1375天前
admin
1164
1、配置文件目录 tp5\application\database.php通过配置文件来连接。也可以通过方法链接。在控制器里方法链接数据库 ;查询时写法 和使用系统的DB类方法略有差异12345678910111213141516171819202122// 使用方法配置数据库连接public function data1 (){  $DB = Db::connect([    // 数据库类型    'type'      => 'mysql',    // 服务器地址    'hostname'    => '127.0.0.1',    // 数据库名    'database'    => 'user',    // 用户名    'username'    => 'root',    // 密码    'password'    => 'root',    // 端口    'hostport'    => '3306',  ]);  // dump($DB);  // 查询数据,,,,和使用系统的DB类方法略有差异  $data = $DB -> table("uu") -> select();  dump($data);}(推荐学习教程:thinkphp教程)2、基本使用 、 增删改查控制器使用配置文件连接数据库控制器下文件(tp5\application\index\controller\Index.php)写入1234567891011121314151617181920212223<?phpnamespace app\index\controller;use think\Db;use think\Controller;class Index extends Controller{  public function index()  {    // return '上课来';    return $this -> fetch();  }  // 使用配置文件连接数据库  public function data()  {    // 实例化数据库系统类    $DB = new Db;    // 查询数据,表名为uu的所有数据    $data = $DB::table("uu") -> select();    // 使用sql语句    //$data = $DB::query("select * from uu");    dump($data);  }}3、将数据渲染模板页面12345678910111213141516171819202122232425<?phpnamespace app\index\controller;use think\Db;use think\Controller;// 使用model连接数据库要引入moadeluse think\Model;class Index extends Controller{  public function index()  {    // return 's';    $this -> data();    return $this -> fetch();  }// 使用系统配置文件连接数据库  public function data()  {    // 实例化数据库系统类    $DB = new Db;    // 查询数据    $data = $DB::table("uu") -> select();    $this -> assign("user",$data);    // dump($data);  }}4、模板页面即可引用渲染数据tp5\application\index\view\index\index.html12345678910111213<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>s</title></head><body>  <div> s</div>  {volist name="user" id="vo"}    <a href="">{$vo.name}</a>  {/volist}</body></html>更多编程相关内容,请关注php中文网编程入门栏目!以上就是thinkphp5如何连接数据库的详细内容
0 0 1375天前
admin
1111
本篇介绍了使用ThinkPHP接入qq互联实现第三方登录的方法,作为一个小案例来为各位讲解,希望对各位有帮助。ThinkPHP接入QQ互联实现登录的案例分析我的一个二级域名项目想在也想接入QQ第三方登录功能,该项目采用的thinkphp5框架开发的项目,在网上搜了一些接入的案例,个人觉得鱼龙混杂不太适合自己,现在自己重新在thinkphp5框架上开发这个功能,下面是详细的开发步骤。(推荐教程:thinkphp教程)第一步、下载QQ互联SDK,我们是基于thinkphp5框架下的,当然是要用PHP版的SDK,下载下来后的文件目录如下。第二步、将SDK主要目录上传到服务器合适的目录下,先说下SDK的主要的目录是API文件夹里面的class目录,当初为了做配置设置项测试,我上传了install文件夹,然后再开发环境配置了APP ID、APP Key以及callback_url,配置好之后会在API/comm文件夹中多处一个inc.php配置文件,最后再recorder类中会引用这个配置文件。可是在后面的 开发过程中我发现会报这个错The state does not match. You may be a victim of CSRF。后面我把qqlogin方法里面的 state放到session中,对官网的DEMO SDK已经完全失去信心了,不在用QQ互联全部的文件而是挑几个重要的类文件来做开发。后面想想官方给的SDK只是普通的PHP代码格式,我应用到thinkphp那很多东西都已经变了,最后我选择上个类文件,QC.php、URL.php、Oauth.php上传到extend/qqlogin目录下。在thinkphp5的项目中扩展类一般上传到extend文件夹下,如下图所示我上次的目录位置。第三步、改造上述三个类文件,因为QC.php是继承了Oauth.php,我们从后者改起,去掉require_once,加上命名空间如namespace qqlogin,首先看成员属性,类常量是腾讯平台的地址,不用管,原来有三个属性,recorder、error不需要,注释掉或直接删掉。下文同样,因为5个类文件我们只用到3个类文件,一个是报错类一个读取配置相关类。下面看Oauth.php成员属性、qqlogin跳转方法、qqcallback回调方法的,其他两个类文件没有太大的改大,按照上述规则改即可123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778<?php/* PHP SDK * @version 2.0.0 * @author connect@qq.com * @copyright © 2013, Tencent Corporation. All rights reserved. */namespace qqlogin;use qqlogin;class Oauth{    const VERSION = "2.0";    const GET_AUTH_CODE_URL = "https://graph.qq.com/oauth2.0/authorize";    const GET_ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token";    const GET_OPENID_URL = "https://graph.qq.com/oauth2.0/me";    // protected $recorder;    public $urlUtils;    // protected $error;         function __construct(){        // $this->recorder = new Recorder();        $this->urlUtils = new URL();        // $this->error = new ErrorCase();    }    public function qq_login(){        // $appid = $this->recorder->readInc("appid");        // $callback = $this->recorder->readInc("callback");        // $scope = $this->recorder->readInc("scope");        $appid = $this->appid;        $callback = $this->callback;        $scope = $this->scope;        //-------生成唯一随机串防CSRF攻击        $state = md5(uniqid(rand(), TRUE));        // $this->recorder->write('state',$state);        session('state',$state);        //-------构造请求参数列表        $keysArr = array(            "response_type" => "code",            "client_id" => $appid,            "redirect_uri" => $callback,            "state" => $state,            "scope" => $scope        );        $login_url =  $this->urlUtils->combineURL(self::GET_AUTH_CODE_URL, $keysArr);        return $login_url;    }    public function qq_callback(){        // $state = $this->recorder->read("state");        //--------验证state防止CSRF攻击        if(input('state') != session('state')){            // $this->error->showError("30001");            exit('30001');        }        //-------请求参数列表        $keysArr = array(            "grant_type" => "authorization_code",            "client_id" => $this->appid,            "redirect_uri" => urlencode($this->callback),            "client_secret" => $this->appkey,            "code" => $_GET['code']        );        //------构造请求access_token的url        $token_url = $this->urlUtils->combineURL(self::GET_ACCESS_TOKEN_URL, $keysArr);        $response = $this->urlUtils->get_contents($token_url);        if(strpos($response, "callback") !== false){            $lpos = strpos($response, "(");            $rpos = strrpos($response, ")");            $response  = substr($response, $lpos + 1, $rpos - $lpos -1);            $msg = json_decode($response);            // if(isset($msg->error)){            //     $this->error->showError($msg->error, $msg->error_description);            // }        }        $params = array();        parse_str($response, $params);        // $this->recorder->write("access_token", $params["access_token"]);        // return $params["access_token"];        session('access_token',$params["access_token"]);    }}第四步、编写控制器调用函数和回调函数,同时检查回调地址是否正确(回调地址是当你添加QQ第三方登录QQ互联返回跳转的地址,该地址携带重要参数,能获取最后用户的数据),有些时候如果你在QQ互联填写的回调地址与你控制器的不一样,那么最后就会卡在那个QQ互联填写的回调地址那,如www.100txy.com/index.php?code=65B7668A4F1BBB71DD0DF52B55AC1FC1&state=804e921e18e3545ecdf690316639c067。下面是控制器方法12345678910111213141516use qqlogin\QC;// 处理qq登录    public function qqlogin(){        $qq = new QC();        $url = $qq->qq_login();        $this->redirect($url);    }    // qq登录回调函数    public function qqcallback(){        $qq = new QC();        $qq->qq_callback();        $qq->get_openid();        $qq = new QC();        $datas = $qq->get_user_info();        die(var_dump($datas));//为用户数据    }值得注意的是在回调函数里面要实例化两次QC才能拿到用户信息,第二次实例化的时候才有openid和access_token两个参数。更多Thinkphp教程,请关注PHP中文网!以上就是ThinkPHP接入QQ互联实现登录的案例分析的详细内容
0 0 1375天前
admin
993
本篇文章介绍了thinkphp框架实现点击图片刷新验证码的方法,希望对学习thinkphp的朋友有帮助!ThinkPHP实现点击图片刷新验证码本类验证码功能刷新功能,涉及到两个刷新,一个是点击验证码图片刷新,另一个是输错验证码刷新,当然自己刷新那就不要说了,那是肯定会刷新的。(推荐教程:thinkphp教程)thinkPHP框架里面内置了verify.class.php验证类,我们做验证码验证的时候就非常简单了,这里提供两种验证的格式,一个纯数字,一个是系统默认的,其中里面的方法都是写在login控制器中的方法,具体代码如下12345678//第一种默认的验证码public function captcha(){        $config =    array(            'length'      =>    4,     // 验证码位数        );        $Verify = new \Think\Verify($config);        $Verify->entry();    }另外一种12345678910111213141516//第二种默认的验证码  function show_verify($config=''){        if($config==''){            $config=array(                'codeSet'=>'1234567890',                'fontSize'=>30,                'useCurve'=>false,                'imageH'=>60,                'imageW'=>240,                'length'=>4,                'fontttf'=>'4.ttf',                );        }        $verify=new \Think\Verify($config);        return $verify->entry();    }显示验证码图片的HTML代码1234<div class="form-group">   <input type="text" class="form-control" placeholder="验证码" required="" name="verify" >   <img class="verify" src="{:U('Admin/Login/show_verify')}" title="点击更换"  onclick="this.src+='';"> </div>图片onclick事件就能完成验证码的刷新了更多ThinkPHP框架教程,请关注PHP中文网!以上就是ThinkPHP实现点击图片刷新验证码的详细内容
0 0 1375天前
admin
1003
ThinkPHP防止XSS攻击的方法1 如果您的项目没有富文本编辑器 然后就可以使用全局过滤方法 在application下面的config配置文件 加上 htmlspecialchars12// 默认全局过滤方法 用逗号分隔多个'default_filter' => 'htmlspecialchars',如果有富文本编辑器的话 就不适合 使用这种防XSS攻击(推荐教程:thinkphp教程)那么使用 composer 安装插件来处理命令1composer require ezyang/htmlpurifier安装成功以后在application 下面的 common.php 放公共函数的地方添加如下代码1234567891011121314151617181920if (!function_exists('remove_xss')) {    //使用htmlpurifier防范xss攻击    function remove_xss($string){    //composer安装的,不需要此步骤。相对index.php入口文件,引入HTMLPurifier.auto.php核心文件    // require_once './plugins/htmlpurifier/HTMLPurifier.auto.php';    // 生成配置对象    $cfg = HTMLPurifier_Config::createDefault();    // 以下就是配置:    $cfg -> set('Core.Encoding', 'UTF-8');    // 设置允许使用的HTML标签    $cfg -> set('HTML.Allowed','div,b,strong,i,em,a[href|title],ul,ol,li,br,p[style],span[style],img[width|height|alt|src]');    // 设置允许出现的CSS样式属性    $cfg -> set('CSS.AllowedProperties', 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align');    // 设置a标签上是否允许使用target="_blank"    $cfg -> set('HTML.TargetBlank', TRUE);    // 使用配置生成过滤用的对象    $obj = new HTMLPurifier($cfg);    // 过滤字符串    return $obj -> purify($string);}然后在 application目录下的config.php 配置文件把这个过滤方法改成那个方法名即可结合框架的使用 和插件的使用可以使用这个 上面的代码可以可以直接使用的也可以针对某个字段进行xss验证1 修改 command的文件把改成这个 'default_filter' => 'htmlspecialchars',2 然后在你要更改的字段 上面 修改成相关推荐:PHP视频教程,学习地址:https://www.php.cn/course/list/29/type/2.html以上就是ThinkPHP防止XSS攻击的方法的详细内容
0 0 1375天前
admin
959
Thinkphp5模板继承和替换的问题案例同一个模块下的common继承问题,这里于index模块为例在index模块下有自己的common和模块主视图文件夹index,那么我index0里面继承了自己的base.html是这样的(推荐教程:thinkphp教程)123456789101112131415161718192021222324252627282930313233343536373839404142//base.html文件<!DOCTYPE html><html>  <head>    <meta charset="utf-8">    <title>      {block name="title"}        雷小天thinkPHP开发版      {/block}    </title>    <link rel="stylesheet" type="text/css" href="__CSS__/style.css">    <link rel="stylesheet" type="text/css" href="__LAYUI__/css/layui.css">    <script type="text/javascript" src="__LAYUI__/layui.js"></script>  </head>  <body>    <div class="wrap">      <!-- 头部 -->      <div class="header">        {include file="common/nav" /}      </div>      <!-- 中部 -->      <div class="main">        <!-- 边栏 -->        <div class="body">          {block name="body"}          {/block}        </div>        <!-- 内容 -->        <div class="sidebar">          {block name="sidebar"}          {/block}        </div>      </div>      <!-- 尾部 -->      <div class="footer">        {block name="footer"}          默认值footer        {/block}      </div>    </div>  </body></html>下面是index0.html12345678910111213{extend name="common/base" /}{block name="title"}  thinkPHP5 index页{/block}{block name="body"}  <h1>这里是index body</h1>{/block}{block name="sidebar"}  <h1>这里是index sidebar</h1>{/block}{block name="footer"}  index_22{__block__}{/block}我在index0.html文件中有重新定义title,所有最后的title是thimkPHP5 index页,但值得注意的是我footer内容是index_22{__block__},而{__block__}指的是在模板base.html中同位置的默认值footer,所有最后footer的内容是index_22默认值footer。以上是同模块下的继承,还有一种是继承common模块的继承,这里于idnex模块下的view/index.html继承common模块下view下的base.html文件为例不同的模块继承方式也不同了,这里继承common模块下的继承方式为:{extend name="common@base" /},而在同模块下的继承是:{extend name="common/base" /}。而有些需求在base.html文件中还需要继承其他的模板,那么在base.html中可以这样继承: {include file="common@header" /}这个意思就是继承common下的view/header.html文件PHP中文网,大量MySQL视频教程,欢迎学习!以上就是Thinkphp5模板继承和替换的问题案例的详细内容
0 0 1375天前
admin
987
用户登陆功能是PHP程序设计中常见的需求,本文ThinkPHP实例主要完成注册成功后进入首页的代码编写,并告诉你是如何实现登录用户的功能。详解ThinkPHP登录功能实例代码具体步骤:第一步:在config.php文件中加上:1'USER_AUTH_KEY'=>'authId'示例如下:(推荐教程:thinkphp教程)1234567891011121314<?phpif(!defined('THINK_PATH')) exit();return array(// 定义数据库连接信息'DB_TYPE'=> 'mysql',// 指定数据库是mysql'DB_HOST'=> 'localhost','DB_NAME'=>'myuser', // 数据库名'DB_USER'=>'root','DB_PWD'=>'', //您的数据库连接密码'DB_PORT'=>'3306','DB_PREFIX'=>'think_',//数据表前缀'USER_AUTH_KEY'=>'authId');?>第二步:在AdminAction.class.php中的insert()代码中用:1Session::set(C('USER_AUTH_KEY'),$user);保存登录用户名到session。完整实现代码如下:123456789101112131415161718public function insert(){header('Content-Type:text/html; charset=utf-8');//防止出现乱码$user=$_POST['user'];$this->verifyCheck();$Pagemodel = D("user");$vo = $Pagemodel->create(); if(false === $vo) die($Pagemodel->getError());$topicid = $Pagemodel->add(); //add方法会返回新添加的记录的主键值if($topicid){ // www.jbxue.com//$_SESSION[C('USER_AUTH_KEY')]=$user;//不能用此句Session::set(C('USER_AUTH_KEY'),$user);//dump(Session::get('authId')); echo "<script>alert('数据库添加成功');location.href='http://127.0.0.1/zhuce/index.php/index';</script>";}else throw_exception("<script>alert('数据库添加失败');history.back();</script>");}第三步:在IndexAction.class.php文件中用if(!Session::is_set(C('USER_AUTH_KEY')))判断用户登录了没有。1Session::get(C('USER_AUTH_KEY'))是获取登录用户的名。具体代码如下:1234567891011121314public function index(){ //www.jbxue.comif(!Session::is_set(C('USER_AUTH_KEY')))//if(!isset($_SESSION['USER_AUTH_KEY'])||($_SESSION['USER_AUTH_KEY']==0))//不能用此句{$msg="用户没有登录"; }else{$msg=Session::get(C('USER_AUTH_KEY')).'欢迎你回来';}$this->assign('msg',$msg);$this->display(); }第四步:首页显示模板,代码如下:1234<body>{$msg}<br />这是我的首页</body>总结:登录代码都是围绕写session,判断session,读session展开。写session用:Session::set(C('USER_AUTH_KEY'),$user);判断session用:if(!Session::is_set(C('USER_AUTH_KEY')));读session用:Session::get(C('USER_AUTH_KEY'))PHP中文网,大量免费MySQL视频教程,欢迎在线学习!以上就是详解ThinkPHP登录功能实例代码的详细内容
0 0 1375天前
admin
1086
本篇文章介绍了Thinkphp使用join联表查询的方法,具有一定的参考价值,希望对各位学习thinkphp的朋友有帮助!Thinkphp使用join联表查询的方法多表联查:12345678$user = M('user');$b_user = M('b_user');$c_user = M('c_user');$list = $user->alias('user')->where('user.user_type=1')    ->join('b_user as b on b.b_userid = user.user_id')    ->join('c_user as c on c.c_userid = b.b_userid')    ->order('b.user_time')    ->select();$user 表的 user_id 等于$b_user表的b_userid;$c_user表的 c_userid 等于$b_user表的b_userid;推荐学习:thinkphp教程以上就是Thinkphp使用join联表查询的方法的详细内容
0 0 1375天前
快速发帖 高级模式
联系站长 友链申请桂ICP备19000949号-1     桂ICP备19000949号-1
您的IP:44.200.174.157,2024-03-29 19:27:40,Processed in 0.68322 second(s).
免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。
Powered by HadSky 7.12.9
免责声明
1、本站资源,均来自网络,版权归原作者,所有资源和文章仅限用于学习和研究目的 。
2、不得用于商业或非法用途,否则,一切责任由该用户承担 !
如果觉得本文还不错请点个赞或者打赏点轻币哦~
拒绝伸手党,拿走请回复,尊重楼主,尊重你我他~

侵权删除请致信 E-Mail:207882320@qq.com