百搜论坛欢迎您的加入!
adimg adimg
 
昨日:篇  今日:篇   总帖:篇   会员:
今日:0    总帖:89
admin
1095
PHP资源分享PHP框架之ThinkPHP项目开发CMS内容管理系统链接: https://pan.baidu.com/s/1c144J40 密码: mbcd北风网PHP第一季视频教程链接: https://pan.baidu.com/s/1c24eY7e 密码: q5wi[精品教程]黑客基地php特训班链接: https://pan.baidu.com/s/1eSEQnlC 密码: 2htwphp100李炎恢老师XHTML视频教程链接: https://pan.baidu.com/s/1slFjNGD 密码: 4ucfPHP程序设计高级教程链接: https://pan.baidu.com/s/1mikRQZY 密码: tt1g前端到后台ThinkPHP开发整站链接: https://pan.baidu.com/s/1bpIudER 密码: zm5k
0 0 1362天前
baby
1248
德州wepoker透视辅助挂【V亻言15OO5O638】▊无需打开▊直接添加微信▊软件功能:▊1.看牌功能,所有玩家的牌都能浏览▊2.修改作弊,支持全天24小时自动智能挂机 更加人性化▊3.牌面记忆功能,已打的牌可以显示出来▊4.透视显牌▊5.自动挂机智能打牌▊6.提高每局得好牌概率,提高胜率等▊7.房间密码超强破解,任何房间随意进出,不受限制▊与其听非专业人士随便说,影响了你对一个事物的认知和判断,莫不如实事求是,找个你信得过的专业团队或者加我聊聊,专业的事交给专业的人去做,会让你省时、省力、省心且一本万利。爱国、进步、科学、自强不息,厚德载物。求是创新。博学而笃志,切问而近思。自强、弘毅、求是、拓新。真理!
0 0 1363天前
admin
1412
THINKPHP5是一个很好的PHP框架,简称TP5,如果你会PHP,可以很容易的掌握这个框架,针对于想要学习tp5的同学,我们简单对TP5的安装和配置,及文件结构做一下介绍。安装配置官网下载TP5完整版(初学者学习用的)解压到本地的开发环境phpstudy中,默认的入口文件是public,访问public会看到TP5成功页面。目录介绍一般开发中,代码都是写在application这个文件夹中开发一个项目的时候,通常分为前台和后台,前台一般放在index模块中,后台一般放在admin模块中。也可以自己新建一个模块模块内部,都遵循着MVC架构controller、model、view都可以自己在模块中创建下面对application文件夹中的文件做一些介绍;image.pngcommand.php    命令行启动TP5框架需要读取的文件common.php    常用的函数,都写在这个文件中config.php    配置文件,开启什么,关闭什么,都在这设置database.php    连接数据库时候读取的文件,比如用户名route.php    路由文件,美化url的tags.php    扩展框架的时候用到下载的第三方库都放在这里入口文件static    这里放的是css、html之类的静态文件favicon.ico    这个是网站图标,在标签栏显示的index.php    网站入口文件,所有的请求都会经过这里robots.txt    禁止搜索引擎爬取页面的设置router.php    在没有部署网站环境的情况下,配置这个文件可以让网站运行开发规范(命名规范)目录    只是小写字母和下划线构成类的文件名以命名空间定义,并且命名空间和类库文件所在路径一致。类的文件采用驼峰,并且首字母大写,其余文件为小写加下划线。类名和类文件名保持一致,采用驼峰命名,首字母大写。函数使用驼峰命名,首字母小写。属性名采用驼峰,首字母小写以双下划线开头的函数或方法为魔术方法。常量以大写字母和下划线命名表和字段必须以小写字母和下划线命名方式,不能以下划线开头。模块设计自己创建的common模块可以自己创建common模块,然后里面写一些其他模块会常用的控制器,或者其他模块依赖的控制器,让他们继承。image.png惯例配置与应用配置与扩展配置所谓应用位置,就是对app文件夹中文件都起作用的配置。定义配置文件路径创建了配置文件后,必须要在入口文件出定义配置文件的路径,并且要将配置文件命名为config.php才可以。通常是不允许修改TP5框架的惯例配置的,这样不安全也不规范,只要定义了应用配置,那么应用配置文件中的配置的值会代替惯例配置中相同的配置,若是没有相同的值,那么就会新添加应用配置中的值。(惯例配置不会遭到修改)image.png如果项目比较大,配置信息也就多,放在一个配置文件中不合适,所以就有了扩展配置。优先级是扩展配置会覆盖conf/config.php配置,会覆盖TP5惯例配置。另外,扩展配置文件夹必须叫做extra文件夹,同时TP5为了人性化,允许与conf/config.php同级创建database.php,但是,这个database.php是属于extra扩展配置的,拥有扩展配置的优先级覆盖。场景切换配置在惯例配置中,有'app_statues'参数,默认为空,但是可以在应用配置conf/config.php中设置该参数的值为场景名称,然后再创建该场景名称的配置文件,在里面写入想配置的参数就可以了。只要想切换场景,就修改conf/config.php这个应用配置文件中'app_status'的值即可。惯例配置参数展示在conf/config.php中,只要调整'app_status'的值为home,那么就会调用conf/home.php中的配置。应用配置实例不过,由于TP5的BUG,必须要在conf/home.php中将完整的database.php中的代码复制过来,否则,修改完一处参数后,整个应用配置只有修改后的这个参数,原来的database.php中的其他参数就默认没有了。以上内容的配置,都是对整个应用起作用的,针对模块的单独的配置,下面会有。模块配置与动态配置模块配置只要像上方那样做修改就可以了。而动态配置,指的就是在控制器中进行配置,或者在控制器的方法中进行配置。说的再直白点,就是在类中用构造方法配合config()函数进行配置,这种配置,对整个类都有作用。若想对指定方法配置,那么就在那个方法中用config()函数进行配置就可以了。image.png我上面只是在方法中没有输出config()配置罢了,不然只要访问方法,就可以看到。环境配置环境配置结合场景配置,先在根目录创建.env文件,然后在应用配置的config文件中利用 think\Env 这个类中的 Env::get()函数获取.env文件中的值,来对场景进行选择。这样就不用修改场景,只需要修改.env中的配置的值就可以了。绑定入口文件绑定入口文件之后,就可以直接加控制器和方法来访问了,如果绑定了控制器,那么只要输入方法就可以了。绑定入口文件通常用于接口使用,比如让第三方接入的时候,不希望第三方访问我们的index模块或者admin模块,那么就用这个绑定入口文件来解决。另外,一旦进行了入口文件的绑定,比如我上面绑定了index,那么我也无法访问admin模块下的页面了。只能访问index模块中的页面api的应用路由若要使用路由,那么首先要开启路由,在convention.php文件中默认开启路由。不过,因为要用到我们的app中,所以需要将开启语句复制到conf/config.php中。开启路由一旦设置好路由的规则后并且开启了url_route_must=true,那么访问原来的index/Index/info/id/5就会报错,只能访问news/5。所以,要想原来访问的地址也能访问,就将url_route_must=falseinfo方法需要传入形参id这里输出的是news/10,因为这里之前定义了index/index/info的路由为news/:id,如果没有定义过,那么输出就是原来的路径,而不是路由的路径路由助手函数的输出请求对象的获取重点是Request类的使用,以及里面的方法实际上,可以仔细参考一下这个框架的编写风格,感觉能学到不少编程思想。由于上面返回的基本上都是关键数组,所以,如果想获取某个返回的数组中参数的值,可以直接在方法中加上参数名。其他获取的一些内容上面的param方法,会返回get,post,pathinfo这几个的值image.png上图第三个参数,是用来过滤获取到的值的,之所以是用intval,是对获取到的值进行整数强制转换。推荐自己写代码不用助手函数input,用request类那样的写法,这样代码的可读性更高,但是input还是要了解,因为每个人的代码不同。控制器中不建议使用die函数,可以用return来结束。返回对象上面用到了Config类,但是却忘记 use think/Config;了返回对象一般都是动态配置,因为不能保证每个控制器的返回对象都相同。视图和模板控制器渲染视图控制器中,可以使用view()函数来将与controller同一层的view模块中的与控制器同名的index文件夹中的与index()方法同名的intex.html渲染出来。这个是一个对应关系。Index控制器对应的是view/index文件夹只要做到view文件夹路径后的文件名对应模块名就可以了,控制器中的view()方法可以指定参数。view()对应的路径就是view文件夹view('./html/index.html')函数里面传入这样的参数,代表是从入口文件进去了,而不是像view('index')这样代表view/index.htmlview()函数的参数不同,路径也不同return view('index',['email'=>'123456@qq.com','name'=>'xxx'])类似这样的用法,是view()函数向指定要渲染的html页面传输变量emali和变量name的值。只需要在显示的位置{$email}或者{$name}就可以了。渲染变量要渲染的页面,只要输入大写的STATAC,那么就会被下面这个view函数的第三个参数的值所替换,通俗点看就是渲染了常量。第三个参数,渲染常量STATAC不过,上面的方法还是不推荐使用,代码可读性不高。实际开发中,最好是继承think\Controller,然后,使用$this->fetch()来渲染。用法和view()一样。推荐使用$this->fethc()也可以直接使用$this->assign('a','a的值')来给要渲染的页面上的a变量赋值。$this->assign()的用法当view文件夹中没有任何要渲染的模板的时候,就用到了下面这个函数同时也比较有用的一个方法是$this->display('只显示我这个字符串内容'),这是只传入一个参数的时候。传入两个参数的用法在渲染页面的时候,TP5框架让html页面中用的是花括号来表示变量的,但是,这个也可以在tp5中进行修改,让其他的符号或者其他的值来代替花括号的作用。几种渲染模板时候赋值的方式赋值方法还挺多的在配置文件中,可以设置下面这个参数的值,来全局替换某个关键词为某个值设置全局值替换常用的有一些系统默认设置的字符串替换:这几个很常用上面这些修改指定字符串值的方法,最神奇的使用地方就是,假如我们修改了某个文件的位置,那么只要设置指定字符串的值,就可以了,否则还得一个代码一个代码的进行修改。先看看下面能输出哪些值,然后理解在tp5中,模板是如何获取这些值的输出查看$_SERVER有哪些值$_SERVER的值模板获取$_SERVER中指定的值获取其他的值获取更多的值上面这个错了,是获取app的路径,不是当前页面的路径在模板中进行变量计算的时候,可以用#进行占位,之所以要占位,是因为{$email|md5}是把email这个参数传入md5这个函数中,而有的函数,有好几个参数传入,也有传入的顺序,所以就需要用到#来进行占位。模板中进行变量的计算还可以同时叠加好几个函数变量遇到js下面这样的注释,更加安全,因为html代码中看不到。如果用html的注释,那么就会在前端的网页源码中找到更安全的注释模板循环标签循环标签的使用在模板中,用{volist name="list" id="data"} {/volist}这一对标签来将控制器中的数组list进行循环,上图中会循环输出二维数组list中全部的name值,还附带<p>标签。list数组offset参数代表从数组的几个元素开始遍历,length参数代表遍历的长度,mod代表对当前循环次数取余。其他参数foreach迭代for循环for在模板中的其他参数比较标签比较标签,eq和equal相等的不相等的比较标签大于、小于标签大于等于、小于等于image.png条件判断标签Think.get.level这里的level是get传的参数image.png还有notbetween这样的参数几个常用标签上面的 if 标签内部还可以用AND和OR这样的逻辑语句模板的布局包含和继承当在block中嵌套使用block的时候,就可以向下方这样使用{__block__}是使用被继承薄板中的值这部分知识,主要就是include,extend,block的灵活运用。下面可以尝试做ThinkPHP5开发的项目来进行实战了。实战中再多记录一些笔记。本文地址:http://www.hnzzwz.com/blog/post/49.html版权声明:本文为原创文章,版权归 ll2l 所有,欢迎分享本文,转载请保留出处!
0 0 1365天前
admin
1179
在写SQL时,经常灵活运用一些SQL语句编写的技巧,可以大大简化程序逻辑。减少程序与数据库的交互次数,有利于数据库高可用性,同时也能显得你的SQL很牛B,让同事们眼前一亮。实用的SQL1.插入或替换如果我们想插入一条新记录(INSERT),但如果记录已经存在,就先删除原记录,再插入新记录。情景示例:这张表存的每个客户最近一次交易订单信息,要求保证单个用户数据不重复录入,且执行效率最高,与数据库交互最少,支撑数据库的高可用。此时,可以使用"REPLACE INTO"语句,这样就不必先查询,再决定是否先删除再插入。"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。"REPLACE INTO"语句是基于唯一索引或主键来判断唯一(是否存在)的。注意事项:如下SQL所示,需要在username字段上建立唯一索引(Unique),transId设置自增即可。1234567-- 20点充值REPLACE INTO last_transaction (transId,username,amount,trans_time,remark)    VALUES(null, 'chenhaha', 30, '2020-06-11 20:00:20', '会员充值'); -- 21点买皮肤REPLACE INTO last_transaction (transId,username,amount,trans_time,remark) VALUES(null, 'chenhaha', 100, '2020-06-11 21:00:00', '购买盲僧至高之拳皮肤');若username='chenhaha'的记录不存在,REPLACE语句将插入新记录(首次充值),否则,当前username='chenhaha'的记录将被删除,然后再插入新记录。id不要给具体值,不然会影响SQL执行,业务有特殊需求除外。2.插入或更新如果我们希望插入一条新记录(INSERT),但如果记录已经存在,就更新该记录,此时,可以使用"INSERT INTO ... ON DUPLICATE KEY UPDATE ..."语句:情景示例:这张表存了用户历史充值金额,如果第一次充值就新增一条数据,如果该用户充值过就累加历史充值金额,需要保证单个用户数据不重复录入。这时可以使用"INSERT INTO ... ON DUPLICATE KEY UPDATE ..."语句。注意事项:同上,"INSERT INTO ... ON DUPLICATE KEY UPDATE ..."语句是基于唯一索引或主键来判断唯一(是否存在)的。如下SQL所示,需要在username字段上建立唯一索引(Unique),transId设置自增即可。123456789-- 用户陈哈哈充值了30元买会员INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark) VALUES(null, 'chenhaha', 30, '2020-06-11 20:00:20', '充会员')    ON DUPLICATE KEY UPDATE total_amount=total_amount + 30, last_transTime='2020-06-11 20:00:20', last_remark ='充会员';  -- 用户陈哈哈充值了100元买瞎子至高之拳皮肤INSERT INTO total_transaction (t_transId,username,total_amount,last_transTime,last_remark)    VALUES(null, 'chenhaha', 100, '2020-06-11 20:00:20', '购买盲僧至高之拳皮肤')    ON DUPLICATE KEY UPDATE total_amount=total_amount + 100, last_transTime='2020-06-11 21:00:00', last_remark ='购买盲僧至高之拳皮肤';若username='chenhaha'的记录不存在,INSERT语句将插入新记录,否则,当前username='chenhaha'的记录将被更新,更新的字段由UPDATE指定。3.插入或忽略如果我们希望插入一条新记录(INSERT),但如果记录已经存在,就啥事也不干直接忽略,此时,可以使用INSERT IGNORE INTO ...语句:情景很多,不再举例赘述。注意事项:同上,"INSERT IGNORE INTO ..."语句是基于唯一索引或主键来判断唯一(是否存在)的,需要在username字段上建立唯一索引(Unique),transId设置自增即可。1234567-- 用户首次添加INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time)    VALUES(null, 'chenhaha', '男', 12, 0, '2020-06-11 20:00:20'); -- 二次添加,直接忽略INSERT IGNORE INTO users_info (id, username, sex, age ,balance, create_time)    VALUES(null, 'chenhaha', '男', 12, 0, '2020-06-11 21:00:20');若username='chenhaha'的记录不存在,INSERT语句将插入新记录,否则,不执行任何操作。4.SQL中的if-else判断语句众所周知,if-else判断在任何地方都很有用,在SQL语句中,"CASE WHEN ... THEN ... ELSE ... END"语句可以用在增删改查各类语句中。给个情景:妇女节大回馈,2020年注册的新用户,所有成年女性账号送10元红包,其他用户送5元红包,自动充值。示例语句如下:12345-- 送红包语句UPDATE users_info u     SET u.balance = CASE WHEN u.sex ='女' and u.age > 18 THEN u.balance + 10                          ELSE u.balance + 5 end                         WHERE u.create_time >= '2020-01-01'* 情景2:有个学生高考分数表,需要将等级列出来,650分以上是重点大学,600-650是一本,500-600分是二本,400-500是三本,400以下大专;原测试数据如下:查询语句:123456SELECT *,case when total_score >= 650  THEN '重点大学'              when total_score >= 600 and total_score <650 THEN '一本'              when total_score >= 500 and total_score <600 THEN '二本'              when total_score >= 400 and total_score <500 THEN '三本'                     else '大专' end as status_student               from student_score;5.指定数据快照或备份如果想要对一个表进行快照,即复制一份当前表的数据到一个新表,可以结合CREATE TABLE和SELECT:12-- 对class_id=1(一班)的记录进行快照,并存储为新表students_of_class1:CREATE TABLE students_of_class1 SELECT * FROM student WHERE class_id=1;新创建的表结构和SELECT使用的表结构完全一致。6.写入查询结果集如果查询结果集需要写入到表中,可以结合INSERT和SELECT,将SELECT语句的结果集直接插入到指定表中。例如,创建一个统计成绩的表statistics,记录各班的平均成绩:123456CREATE TABLE statistics(    id BIGINT NOT NULL AUTO_INCREMENT,    class_id BIGINT NOT NULL,    average DOUBLE NOT NULL,    PRIMARY KEY (id));然后,我们就可以用一条语句写入各班的平均成绩:1INSERT INTO statistics (class_id, average) SELECT class_id, AVG(score) FROM students GROUP BY class_id;确保INSERT语句的列和SELECT语句的列能一一对应,就可以在statistics表中直接保存查询的结果:1SELECT * FROM statistics;12345678+----+----------+--------------+| id | class_id | average      |+----+----------+--------------+|  1 |        1 |        475.5 ||  2 |        2 | 473.33333333 ||  3 |        3 | 488.66666666 |+----+----------+--------------+3 rows in set (0.00 sec)7.强制使用指定索引在查询的时候,数据库系统会自动分析查询语句,并选择一个最合适的索引。但是很多时候,数据库系统的查询优化器并不一定总是能使用最优索引。如果我们知道如何选择索引,可以使用FORCE INDEX强制查询使用指定的索引。例如:1SELECT * FROM students FORCE INDEX (idx_class_id) WHERE class_id = 1 ORDER BY id DESC;指定索引的前提是索引idx_class_id必须存在。心得体会:MySQL路漫漫,其修远兮。永远不要眼高手低,一起加油,希望本文能对你有所帮助。推荐教程: 《mysql教程》以上就是分享MySQL中实用的几种SQL语句的详细内容
0 1 1396天前
admin
1181
我们可以在创建表时设置外键约束。在 CREATE TABLE 语句中,通过 FOREIGN KEY 关键字来指定外键,具体的语法格式如下:12[CONSTRAINT <外键名>] FOREIGN KEY 字段名 [,字段名2,…]REFERENCES <主表名> 主键列1 [,主键列2,…]举例:现在在 test_db 数据库中创建一个部门表 tb_dept1,表结构如下图所示:创建 tb_dept1 的 SQL 语句和运行结果如下所示。1234567mysql> CREATE TABLE tb_dept1    -> (    -> id INT(11) PRIMARY KEY,    -> name VARCHAR(22) NOT NULL,    -> location VARCHAR(50)    -> );Query OK, 0 rows affected (0.37 sec)创建数据表 tb_emp6,并在表 tb_emp6 上创建外键约束,让它的键 deptId 作为外键关联到表 tb_dept1 的主键 id,SQL 语句和运行结果如下所示。123456789101112131415161718192021mysql> CREATE TABLE tb_emp6    -> (    -> id INT(11) PRIMARY KEY,    -> name VARCHAR(25),    -> deptId INT(11),    -> salary FLOAT,    -> CONSTRAINT fk_emp_dept1    -> FOREIGN KEY(deptId) REFERENCES tb_dept1(id)    -> );Query OK, 0 rows affected (0.37 sec) mysql> DESC tb_emp6;+--------+-------------+------+-----+---------+-------+| Field  | Type        | Null | Key | Default | Extra |+--------+-------------+------+-----+---------+-------+| id     | int(11)     | NO   | PRI | NULL    |       || name   | varchar(25) | YES  |     | NULL    |       || deptId | int(11)     | YES  | MUL | NULL    |       || salary | float       | YES  |     | NULL    |       |+--------+-------------+------+-----+---------+-------+4 rows in set (1.33 sec)以上语句执行成功之后,在表 tb_emp6 上添加了名称为 fk_emp_dept1 的外键约束,外键名称为 deptId,其依赖于表 tb_dept1 的主键 id。注意:从表的外键关联的必须是主表的主键,且主键和外键的数据类型必须一致。例如,两者都是 INT 类型,或者都是 CHAR 类型。如果不满足这样的要求,在创建从表时,就会出现“ERROR 1005(HY000): Can't create table”错误。推荐教程:mysql教程以上就是mysql外键约束怎么创建的详细内容
0 0 1396天前
admin
1324
sql语句批量添加数据的方法是什么?方法1:逐条执行,速度慢。123INSERT INTO testimport (name, message)VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd');INSERT INTO testimport (name, message)VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd');INSERT INTO testimport (name, message)VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd');方法2:批量执行,适用于 SQL Server。1234INSERT INTO testimport (name, message)  VALUES('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd'),('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd'),('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd');方法3:批量执行,适用于Oracle。123456INSERT ALL     INTO A (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd')        INTO A (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd')        INTO A (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdlafjdaslkfjasfd')SELECT 1FROM DUAL;推荐教程: 《sql教程》以上就是sql语句批量添加数据的方法是什么的详细内容
0 0 1396天前
admin
1171
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 1396天前
admin
1084
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 1396天前
admin
1051
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 1396天前
admin
1086
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 1396天前
admin
1085
首先,介绍一下什么是模型(model)、视图(view)、控制器(controller)。模型(model)——负责存储系统的中心数据;视图(view)——将信息显示给用户;控制器(controller)——处理用户输入的信息,负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中处理用户交互的部分。负责管理与用户交互交互控制;视图和控制器共同构成了用户接口。且每个视图都有一个相关的控制器组件。控制器接受输入,通常作为将鼠标移动、鼠标按钮的活动或键盘输入编码的时间。时间被翻译成模型或试图的服务器请求。用户仅仅通过控制器与系统交互。结构:模型组件包含应用程序的功能内核,他封装了相应的数据并输出执行特定应用程序处理的过程;模型也提供访问数据的函数,这些数据有获得待显示的数据的视图组件使用。控制器代表用户调用所有这些过程。目的:实现一种动态的程序设计,是后序对程序的修改和扩展简化,并且使程序某一部分的重复利用称为可能。通过对复杂度的简化,使程序结构更加直观。将信息的内部表示与信息的呈现方式分离开来,并接受用户的请求。它分离了组件,并允许有效的代码重用。即,将模型和视图的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保模型和视图的同步,一旦模型改变,视图应该同步更新。以上内容仅供参考!推荐教程:ThinkPHP教程以上就是thinkphp的模型,控制器,视图,是什么的详细内容
0 0 1396天前
admin
1233
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 1396天前
admin
1034
日志记录\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 1396天前
admin
1013
之前写过一篇文章讲了 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 1396天前
admin
1022
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 1396天前
admin
952
在最新的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 1396天前
admin
1121
用过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 1396天前
admin
1152
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 1396天前
admin
1048
下面由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 1396天前
admin
1176
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 1396天前
快速发帖 高级模式
联系站长 友链申请桂ICP备19000949号-1     桂ICP备19000949号-1
您的IP:3.133.144.217,2024-04-20 06:02:16,Processed in 0.26251 second(s).
免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。
Powered by HadSky 7.12.9
免责声明
1、本站资源,均来自网络,版权归原作者,所有资源和文章仅限用于学习和研究目的 。
2、不得用于商业或非法用途,否则,一切责任由该用户承担 !
如果觉得本文还不错请点个赞或者打赏点轻币哦~
拒绝伸手党,拿走请回复,尊重楼主,尊重你我他~

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