从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解


Posted in PHP onApril 03, 2019

本文实例讲述了从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记。分享给大家供大家参考,具体如下:

用tp3.2.3做了不少项目,但是毕竟要与时代接轨,学习一些新的框架,比如tp5

以下记录一些学习中遇到的问题及解决办法,还有tp3.2和tp5.0的一些区别,适合给用过tp3没用过tp5的童鞋做个参考。

随着学习不断更新......

+++++++++++++++++++++++分割线总是要有的+++++++++++++++++++++++

首先到tp官网下载了一个最新的ThinkPHP5.0.22完整版:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

直接扔到了服务器上,解压后目录结构如下:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

目录结构整体与tp3.2大同小异,文件夹首字母小写了,应用入口文件 在根目录下 public/index.php,官方文档对public文件夹定义为WEB部署目录(对外访问目录):

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

配置服务器域名解析的时候需要把项目根目录指向/public:

<VirtualHost *:80>
 ServerAdmin 1977629361@qq.com
 DocumentRoot /var/www/tp/public
 ServerName tp.oyhdo.com
 ServerAlias tp.oyhdo.com
 DirectoryIndex index.php index.html index.htm 
</VirtualHost>

根目录下 application/config.php 为应用(公共)配置文件,设置一些常用的配置,以下简称为“配置文件”:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

访问网址如下:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

访问tp.oyhdo.com等同于访问tp.oyhdo.com/index.php/index/Index/index(默认不区分大小写)

即默认模块index,默认控制器Index,默认操作index

配置文件修改分别为default_moduledefault_controllerdefault_action

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

如果需要强制区分url大小写,修改 url_convert false

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

配置文件中设置 app_debug true,打开应用调试模式,以便开发调试:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

【隐藏url中的index.php入口文件】

以Apache服务器为例,首先确认Apache配置文件httpd.conf中开启了mod_rewrite.so模块:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

然后把所有【AllowOverride】设为All:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

 最后修改根目录下 public/.htaccess 文件内容为:

<IfModule mod_rewrite.c>
 Options +FollowSymlinks -Multiviews
 RewriteEngine on
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>
去掉index.php也可访问:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

【隐藏前台url模块名】 

把index模块作为前台,在前台新建了一个User控制器:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

<?php
namespace app\index\controller;

class User
{
 public function user()
 {
 return '这是User控制器的user操作';
 }
}

 正常需要这样访问User控制器的user操作:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

 为了前台url显示简洁一些,要去掉模块名index,然后就崩了:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

如果只有一个模块,可以在 /application/common.php 中添加:

// 绑定当前访问到index模块
define('BIND_MODULE','index');

亲测访问成功:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

但是项目通常会有前后台的区分,至少两个模块, 用上面的方法绑定index模块后,再访问其它模块就会报错:

(新建了一个admin模块作为后台)

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

<?php
namespace app\admin\controller;

class Index
{
 public function index()
 {
 return '这是后台首页';
 }
}

 从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

对于多模块的情况,可以在 /application/route.php 中绑定默认模块路由(去掉上面的单模块绑定):

use think\Route;
Route::bind('index');

前台访问成功:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

 然后在/public/下新建一个入口文件admin.php,绑定后台模块admin,来访问后台:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

<?php
// [ 应用入口文件 ]
namespace think;
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/base.php';
// 绑定当前入口文件到admin模块
Route::bind('admin');
// 关闭admin模块的路由
App::route(false);
// 执行应用
App::run()->send();

后台访问成功:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

(修改后台地址只需修改这个文件名即可)
 

【返回数据】

配置文件中默认输出类型 default_return_type 为html:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

 直接打印输出字符串、数组,没什么特殊:

public function index()
{
 $str = 'hello,world!';
 $arr = array('state'=>1,'msg'=>'success');

 //打印字符串
 echo $str;

 //打印数组
 var_dump($arr);
}

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

返回json格式数据:

public function index()
{
 $arr = array('state'=>1,'msg'=>'success');
 return json($arr);
 
 //返回其它状态码或响应头信息
 //return json($arr, 201, ['Cache-control' => 'no-cache,must-revalidate']);

 //xml格式
 //return xml($arr);
}

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

(对于只做API开发的情况,可以设置default_return_type为json,直接return $arr即可返回json格式数据)
 

【渲染模板、分配数据】

如图建立视图层,index.html作为前台首页(内容为“这是首页”):

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

tp3渲染模板直接在控制器里$this->display(),tp5并不支持。

tp5渲染模板,在控制器中继承think\Controller类,使用 return $this->fetch() 或者使用助手函数 return view()

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
 public function index()
 {
 return $this->fetch();
 //return view();
 }
}

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

tp5分配数据的方式依旧使用 $this->assign()

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
 public function index()
 {
 	$name = 'lws';
 $this->assign('name',$name);
 return $this->fetch();
 }
}

index.html页面读取数据:

{$name}

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

(修改模板引擎标签 配置文件【tpl_begin】、【tpl_end】)

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

【继承父类控制器】

写一个栗子,新建一个Base控制器作为父类控制器,Index控制器继承Base控制器

在父类控制器中初始化分配数据,子类控制器渲染模板:

Base.php:

<?php
namespace app\index\controller;
use think\Controller;
class Base extends Controller
{ 
 //初始化方法
 public function _initialize()
 {	
 	$haha = '快下班了';
 $this->assign('haha',$haha);
 }
}

Index.php:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Base
{
 public function index()
 {
 return $this->fetch();
 }
}

index.html:

{$haha}

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

(与tp3.2相比,父类控制器不能是Public控制器) 

【配置参数】

tp3.2里面使用C方法设置、获取配置参数

tp5使用助手函数 config() 设置、获取配置参数:

//配置一个参数
config('name','lws');

//批量配置参数
config([
 'info'=>['sex'=>'nan','aihao'=>'nv']
]);

//获取一个配置参数
echo config('name');

//获取一组配置参数
dump(config('info'));

//获取一个二级配置参数
echo config('info.sex');

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

【get传参】

tp5废除了url/参数名1/参数值1/参数名2/参数值2......这样的方式传参,还是老老实实用url?参数名1=参数值1&参数名2=参数值2......这样传吧。

控制器里打印$_GET

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
 public function index()
 {
 $getdate = $_GET;
 dump($getdate);	
 }
}

 这样是不对滴:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

这样就好使:

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

【安全获取变量】 

tp3.2可以使用I方法安全获取get、post等系统输入变量

tp5中使用助手函数 input()

//获取get变量
$data1 = input('get.name');

//获取post变量
$data2 = input('post.name');

//获取当前请求变量
$data3 = input('param.name');

//获取request变量
$data4 = input('request.name');

//获取cookie变量
$data5 = input('cookie.name');

//获取session变量
$data6 = input('session.name');

//获取上传文件信息
$data7 = input('file.image');

(注意:获取的数据为数组,要加上 /a 修饰符才能获取到)

$arr = input('post.arr/a');

可以在配置文件中设置全局过滤方法:

// 默认全局过滤方法 用逗号分隔多个
'default_filter'  => 'htmlspecialchars',

【数据库操作】

tp5的数据库配置文件在根目录 /application/database.php:(也可在模块下单独配置)

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

连接数据库:tp3.2支持M方法连接数据库,tp5使用 Db类 或 助手函数db()

查询数据:依旧使用 find()select() 方法,查询一个字段使用 value() 方法代替getField()

//查询一条
$artinfo = db('article')->find();

//查询全部
$artinfo = db('article')->select();

//查询一个字段
$artinfo = db('article')->value('article_title');

添加数据:tp3.2使用add(),tp5使用 insert():返回插入条数  或  save():返回id

//添加一条数据
$data['article_title'] = 'PHP是世界上最好的语言';
$data['article_content'] = '如题';
db('article')->insert($data);
//或 db('article')->save($data);
//添加多条数据
$data = [
 ['article_title' => '标题1', 'article_content' => '内容1'],
 ['article_title' => '标题2', 'article_content' => '内容2'],
 ['article_title' => '标题3', 'article_content' => '内容3']
];
db('article')->insertAll($data);

修改数据:tp3.2使用save(),tp5使用 update()

//修改数据
$whe['article_id'] = 1;
$data['article_title'] = '修改后的标题';
db('article')->where($whe)->update($data);

删除数据:没错还是 delete()

//删除数据
$whe['article_id'] = 1;
db('article')->where($whe)->delete();

db()助手使用起来比较方便,但每次都会重新连接数据库,因此应当尽量避免多次调用,建议还是使用Db类操作数据库。

Db类操作原生SQL:

<?php
namespace app\index\controller;
use think\Db;
class Index {
 public function index() {
 // 插入记录
 $res = Db::execute('insert into lws_article (title ,content) values ("标题", "内容")');
	
 // 删除数据
 $res = Db::execute('delete from lws_article where art_id = 1 ');

 // 更新记录
 $res = Db::execute('update lws_article set title = "修改标题" where art_id = 1 ');

 // 查询数据
 $res = Db::query('select * from lws_article where art_id = 1');

 // 显示数据库列表
 $res = Db::query('show tables from blog');

 // 清空数据表
 $res = Db::execute('TRUNCATE table lws_article');
 }
}

Db类操作查询构造器:

<?php
namespace app\index\controller;
use think\Db;
class Index {
 public function index() {
	// 查询数据(数据库没有配置表前缀)
	$res = Db::table('lws_article')
	 ->where('art_id', 1)
	 ->select();

	//以下为数据库配置了表前缀	

	// 插入记录
	$res = Db::name('article')
		->insert(['title' => '标题', 'content' => '内容']);

	// 更新记录
	$res = Db::name('article')
		->where('art_id', 1)
		->update(['title' => "修改标题"]);

	// 查询数据
	$res = Db::name('article')
		->where('art_id', 1)
		->select();

	// 删除数据
	$res = Db::name('article')
		->where('art_id', 1)
		->delete();
 
 //链式操作举例
 $artlist = Db::name('article')
	 ->where('is_del', 'N')
	 ->field('id,title,content')
	 ->order('post_time', 'desc')
	 ->limit(10)
	 ->select();
 } 
}

【切换数据库】

首先在数据库配置中配置多个数据库:

// 数据库配置1
'db1' => [
	// 数据库类型
	'type' => 'mysql',
	// 服务器地址
	'hostname' => '127.0.0.1',
	// 数据库名
	'database' => 'blog1',
	// 数据库用户名
	'username' => 'root',
	// 数据库密码
	'password' => '123456',
	// 数据库连接端口
	'hostport' => '',
	// 数据库连接参数
	'params' => [],
	// 数据库编码默认采用utf8
	'charset' => 'utf8',
	// 数据库表前缀
	'prefix' => 'lws_',
],
// 数据库配置2
'db2' => [
	// 数据库类型
	'type' => 'mysql',
	// 服务器地址
	'hostname' => '127.0.0.1',
	// 数据库名
	'database' => 'blog2',
	// 数据库用户名
	'username' => 'root',
	// 数据库密码
	'password' => '',
	// 数据库连接端口
	'hostport' => '',
	// 数据库连接参数
	'params' => [],
	// 数据库编码默认采用utf8
	'charset' => 'utf8',
	// 数据库表前缀
	'prefix' => 'lws_',
],

使用connect方法切换数据库:

<?php
namespace app\index\controller;
use think\Db;
class Index {
 public function index() {
 $db1 = Db::connect('db1');
 $db2 = Db::connect('db2');
 $db1->query('select * from lws_article where art_id = 1');
 $db2->query('select * from lws_article where art_id = 2');
 }
}

【系统常量】

tp5废除了一大堆常量:

REQUEST_METHOD IS_GET 
IS_POST  IS_PUT 
IS_DELETE IS_AJAX 
__EXT__  COMMON_MODULE 
MODULE_NAME CONTROLLER_NAME 
ACTION_NAME APP_NAMESPACE 
APP_DEBUG MODULE_PATH等

需要使用的常量可以自己定义,例如IS_GET、IS_POST

我在父类的初始化方法中定义了这两个常量:

<?php
namespace app\index\controller;
use think\Controller;
class Base extends Controller
{
 public function _initialize()
 {	
 	define('IS_GET',request()->isGet());
 define('IS_POST',request()->isPost());
 }
}

然后在子类控制器中就可以使用这个常量做一些判断:

<?php
namespace app\index\controller;
class Index extends Base
{
 public function index()
 { 
 if(IS_POST){
  echo 111;
 }else{
  echo 222;
 }
 }
}

【定义路由】

例如一篇博客详情页,原来的网址为:http://oyhdo.com/home/article/detial?id=50,即home模块下的article控制器下的detial操作方法,传递参数id。

在路由配置文件 application/route.php 中添加路由规则:

return [
 'article/:id' => 'home/article/detial',
];

或者使用 Route 类,效果一样: 

use think\Route;
Route::rule('article/:id','home/article/detial');

定义路由规则之后访问http://oyhdo.com/article/50即可

从ThinkPHP3.2.3过渡到ThinkPHP5.0学习笔记图文详解

 【url分隔符的修改】

修改 application/config.php 中的 pathinfo_depr :

// pathinfo分隔符
 'pathinfo_depr'  => '-',

访问网址变为:http://oyhdo.com/article-50

【跳转、重定向】

tp3里面的正确跳转:$this->success()、错误跳转:$this->error()、重定向:$this->redirect(),在tp5里面同样适用(继承\think\Controller

tp5新增 redirect() 助手函数用于重定向:

return redirect('https://www.oyhdo.com');

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。

PHP 相关文章推荐
一个php作的文本留言本的例子(五)
Oct 09 PHP
PHP 函数学习简单小结
Jul 08 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
May 07 PHP
PHP中数组的三种排序方法分享
May 07 PHP
php 中的4种标记风格介绍
May 10 PHP
PHP仿博客园 个人博客(1) 数据库与界面设计
Jul 05 PHP
php实现12306余票查询、价格查询示例
Apr 17 PHP
php自定义函数实现JS的escape的方法示例
Jul 07 PHP
thinkphp表单上传文件并将文件路径保存到数据库中
Jul 28 PHP
基于Codeigniter框架实现的student信息系统站点动态发布功能详解
Mar 23 PHP
PHP使用Session实现上传进度功能详解
Aug 06 PHP
laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
Oct 08 PHP
PHP快速排序算法实现的原理及代码详解
Apr 03 #PHP
Laravel5.7框架安装与使用学习笔记图文详解
Apr 02 #PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
Apr 02 #PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
Apr 02 #PHP
Swoole实现异步投递task任务案例详解
Apr 02 #PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
Apr 02 #PHP
Linux下源码包安装Swoole及基本使用操作图文详解
Apr 02 #PHP
You might like
建立文件交换功能的脚本(三)
2006/10/09 PHP
攻克CakePHP系列一 连接MySQL数据库
2008/10/22 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
php中sql注入漏洞示例 sql注入漏洞修复
2014/01/24 PHP
js+php实现静态页面实时调用用户登陆状态的方法
2015/01/04 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
JqGrid web打印实现代码
2011/05/31 Javascript
基于datagrid框架的查询
2013/04/08 Javascript
JavaScript中switch判断容易犯错的一个细节
2014/08/27 Javascript
javascript限制用户只能输汉字中文的方法
2014/11/20 Javascript
jquery让指定的元素闪烁显示的方法
2015/03/17 Javascript
纯javascript移动优先的幻灯片效果
2015/11/02 Javascript
JS实现动态增加和删除li标签行的实例代码
2016/10/16 Javascript
微信小程序中顶部导航栏的实现代码
2017/03/30 Javascript
关于使用js算总价的问题
2017/06/23 Javascript
EasyUI的DataGrid每行数据添加操作按钮的实现代码
2017/08/22 Javascript
JS实现碰撞检测的方法分析
2018/01/19 Javascript
尝试自己动手用react来写一个分页组件(小结)
2018/02/09 Javascript
vue 中url 链接左边的小图标更改问题
2019/12/30 Javascript
javascript+css实现俄罗斯方块小游戏
2020/06/28 Javascript
[07:27]DOTA2卡尔工作室 英雄介绍水晶室女篇
2013/06/21 DOTA
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
Python的Django框架安装全攻略
2015/07/15 Python
Python命令行解析模块详解
2018/02/01 Python
python3.4实现邮件发送功能
2018/05/28 Python
Python for循环中的陷阱详解
2018/07/13 Python
Django Serializer HiddenField隐藏字段实例
2020/03/31 Python
Python matplotlib实时画图案例
2020/04/23 Python
详解Python的爬虫框架 Scrapy
2020/08/03 Python
基于python爬取链家二手房信息代码示例
2020/10/21 Python
HTML5实践-图片设置成灰度图
2012/11/12 HTML / CSS
使用canvas压缩图片上传的方法示例
2020/02/07 HTML / CSS
佳能德国网上商店:Canon德国
2017/03/18 全球购物
普通大学毕业生自荐信
2013/11/04 职场文书
幼儿园教师教育随笔
2015/08/14 职场文书
军训决心书范文
2015/09/22 职场文书