使用 ThinkPHP5.1快速开发项目的步骤及实例

使用 ThinkPHP5.1快速开发项目的步骤及实例
编写这篇文章旨在做一个学习笔记。如有错误请批评纠正。
一、前期准备工作
1、编程工具的选择:开发工具:Notepad + 服务器工具:phpStudy(thinkphp5.1运行环境要求PHP5.6+)
2、下载安装thinkphp5.1
(可参考“ThinkPHP5.1完全开发手册”下载ThinkPHP5.1:https://www.kancloud.cn/manual/thinkphp5_1/353948)
Composer安装:在 Windows 中,你需要下载并运行:https://getcomposer.org/Composer-Setup.exe
安装好composer后,打开win系统的命令行窗口cmd(windows用户),并执行如下命令:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
composer create-project topthink/think=5.1.* tp5
这里的tp5目录名你可以任意更改,执行完毕后,会在当前目录下的tp5子目录安装最新版本的ThinkPHP

二、使用 ThinkPHP5.1快速开发项目的完整步骤:
1、创建数据库和数据表
2、配置数据库连接信息
3、创建项目相关文件夹
4、创建控制器类文件
5、创建验证器类文件(选做,一般都会做)
6、创建模型类文件(选做,简单的数据库操作可直接用DB类操作,可不用模型)
7、创建模板视图文件
8、隐藏入口文件index.php(为了网址简短)
9、配置路由文件(为了网址简短)
10、运行应用调试

三、实例
php代码主要写在控制器类文件中,html前端代码主要写在模板视图文件中,下面以一个具体实例加以说明:
1、创建数据库和数据表
可以使用phpstudy中自带的SQLFront连接mysql并手动建个数据库,然后用Notepad写sql脚本并在SQLFront运行可建数据表,例如:
mydb.sql:
DROP TABLE IF EXISTS `blog_article`;
CREATE TABLE `blog_article` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT COMMENT '文章id',
`title` varchar(60) NOT NULL COMMENT '文章标题',
`author` varchar(30) NOT NULL COMMENT '文章作者',
`desc` varchar(255) NOT NULL COMMENT '文章简介',
`keywords` varchar(255) NOT NULL COMMENT '文章关键词',
`content` text NOT NULL COMMENT '文章内容',
`pic` varchar(100) NOT NULL COMMENT '缩略图',
`downhttp` varchar(100) DEFAULT NULL COMMENT '下载网址',
`click` int(10) NOT NULL DEFAULT '0' COMMENT '点击数',
`down` int(11) DEFAULT '0' COMMENT '下载数',
`state` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0:不推荐 1:推荐',
`time` int(10) NOT NULL COMMENT '发布时间',
`cateid` mediumint(9) NOT NULL COMMENT '所属栏目',
`tsort` int(5) DEFAULT '100' COMMENT '文章排序',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

2、配置数据库连接信息
打开config文件夹中的database.php进行数据库连接信息的配置,一般要改动的就是:database(数据库名称),username(数据库用户名),password(数据库密码 ) ,prefix(数据表前缀)

3、创建项目相关文件夹
在application文件夹中创建模块文件夹,在模块文件夹下创建控制器类文件夹、模型类文件夹、模板文件夹、验证器文件夹,例如:
在application文件夹中创建admin(模块文件夹),在admin文件夹建立以下几个文件夹:controller(控制器类文件夹,将放php控制器类文件)、model(模型类文件夹,将放php模型类文件)、view(模板文件夹,将放html模板文件)、validate(验证器文件夹,将放php验证器文件)

4、创建控制器类文件
在controller文件夹下建个控制器类文件Article.php,写入控制器的方法:增删改查等方法,例如:
<?php
namespace app\Admin\controller; //命名空间,即本文件所在位置,该文件位于application\index\controller文件夹中
use think\Controller; //引用控制器类
use think\Db; //引用数据库操作类
class Article extends Controller //创建一个Controller类的子类Article(继承父类),类名头字母要用大写字母,文件名叫做Article.php,名字对应的叫做Article
{
public function lst() //查,方法名叫 lst
{
$list =Db::name('article')->paginate();//查询数据表(前缀_article)的数据并且每页显示10条数据
$this->assign('list',$list);// 把分页数据赋值给模板变量list
return $this->fetch();// 渲染模板输出显示
}

public function add() //增
{
if(request()->isPost()){//如为post过来的数据
$data=[//要新增的数据,以数组形式
'title'=>input('title'),
'author'=>input('author'),
'desc'=>input('desc'),
'keywords'=>str_replace(',', ',', input('keywords')),
'content'=>input('content'),
'cateid'=>input('cateid'),
'downhttp'=>input('downhttp'),
'tsort'=>input('tsort'),
'time'=>time(),
];
if(input('state')=='on'){
$data['state']=1;
}
if($_FILES['pic']['tmp_name']){//上传缩略图图片文件
$file = request()->file('pic');
$info = $file->validate(['ext'=>'jpg,png,gif'])->move(\think\facade\Env::get('ROOT_PATH') .'public'.DIRECTORY_SEPARATOR .'static'.DIRECTORY_SEPARATOR .'uploads',''); //上传图片文件,限制扩展名为jpg,png,gif,DIRECTORY_SEPARATOR表示当前windows系统或linux系统的分隔符(如windows系统为/)
if ($info) {
$data['pic']=DIRECTORY_SEPARATOR .'static'.DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR .$info->getSaveName();
} else {
$this->error($file->getError());
}
}
$validate = new \app\admin\validate\Article; //验证器类
if(!$validate->scene('add')->check($data)){ //提交到validate文件夹中的验证器类Article.php的add场景验证,验证数据是否合法才增加
$this->error($validate->getError()); die;
}
if(Db::name('Article')->insert($data)){ //执行数据库Db类的增加方法
$this->redirect("article/lst");
}else{
show_msg('添加文章失败!');
}
return;
}
$cateres=Db::name('cate')->select();//查询文章栏目数据表
$this->assign('cateres',$cateres);
return $this->fetch();
}

public function edit() //改
{
$id=input('id');
$articles=Db::name('Article')->find($id);
if(request()->isPost()){
$data=[
'id'=>input('id'),
'title'=>input('title'),
'author'=>input('author'),
'desc'=>input('desc'),
'keywords'=>str_replace(',', ',', input('keywords')),
'content'=>input('content'),
'cateid'=>input('cateid'),
'downhttp'=>input('downhttp'),
'tsort'=>input('tsort'),
];
if(input('state')=='on'){
$data['state']=1;
}else{
$data['state']=0;
}
if($_FILES['pic']['tmp_name']){
$file = request()->file('pic');
$info = $file->validate(['ext'=>'jpg,png,gif'])->move(\think\facade\Env::get('ROOT_PATH') .'public'.DIRECTORY_SEPARATOR .'static'.DIRECTORY_SEPARATOR .'uploads','');
if ($info) {
$data['pic']=DIRECTORY_SEPARATOR .'static'.DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR .$info->getSaveName();
} else {
$this->error($file->getError());
}
}
$validate = new \app\admina\validate\Article;
if(!$validate->scene('edit')->check($data)){ //提交到validate文件夹中的验证器类Article.php的edit场景验证,验证数据是否合法才更新
$this->error($validate->getError()); die;
}
$save=Db::name('Article')->update($data); //执行数据库Db类的更新方法
if($save !== false){
$this->redirect("article/lst");
}else{
show_msg('修改文章失败!');
}
return;
}
$this->assign('articles',$articles);
$cateres=Db::name('cate')->select();
$this->assign('cateres',$cateres);
return $this->fetch();
}

public function del() //删
{
$id=input('id');
if(Db::name('Article')->delete(input('id'))){ //执行数据库Db类的删除方法
$this->redirect("article/lst");
}else{
show_msg('删除文章失败!');
}

}
}

5、创建验证器类文件(选做,一般都会做)
在validate文件夹下建个验证器类文件Article.php,写入增加或更新数据时的验证,例如:
<?php
namespace app\admin\validate;
use think\Validate; //引用验证器类
class Article extends Validate //创建一个Validate类的子类Article(继承父类),类名头字母要用大写字母
{
//规则
protected $rule = [
'title' => 'require|max:100',
'cateid' => 'require',
];
//提示信息
protected $message = [
'title.require' => '文章标题必须填写',
'title.max' => '文章标题长度不得大于100位',
'cateid.require' => '请选择文章所属栏目',

];
//场景(增加和修改)
protected $scene = [
'add' => ['title','cateid'],
'edit' => ['title','cateid'],
];
}

6、创建模型类文件(选做,简单的数据库操作可直接用DB类操作,可不用模型)

7、创建模板视图文件
在view文件夹下建立article文件夹(存放Article.php控制器类对应的增改查方法的前端html文件,html文件名要与方法名一致),在article文件夹下建立lst.html,add.html,edit.html模板文件,例如:
lst.html:
<!DOCTYPE html>
<html>
<head>
<title>后台管理</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap-4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="row">
<div class="col-lg-12 col-sm-12 col-xs-12">
<table class="table table-bordered table-hover">
<thead class="table-info">
<tr>
<th class="text-center" width="4%">ID</th>
<th class="text-center">文章标题</th>
<th class="text-center">文章作者</th>
<th class="text-center">是否推荐</th>
<th class="text-center">缩略图</th>
<th class="text-center">所属栏目</th>
<th class="text-center">文章排序</th>
<th class="text-center">点击数</th>
<th class="text-center">下载数</th>
<th class="text-center" width="14%">操作</th>
</tr>
</thead>
<tbody>
{volist name="list" id="vo"}
<tr>
<td align="center">{$vo.id}</td>
<td align="center">{$vo.title}</td>
<td align="center">{$vo.author}</td>
<td align="center">
{if condition="$vo['state'] eq 1 "}
已推荐
{else /}
未推荐
{/if}
</td>
<td align="center">
{if condition="$vo['pic'] neq '' "}
<img src="{$vo.pic}" height="50">
{else /}
暂无缩略图
{/if}
</td>
<th class="text-center">{$vo.cate.catename}</th>
<td align="center">{$vo.tsort}</td>
<td align="center">{$vo.click}</td>
<td align="center">{$vo.down}</td>
<td align="center">
<a href="{:url('article/edit',array('id'=>$vo['id']))}" class="btn btn-primary">
<i class="fa fa-edit"></i> 编辑
</a>
<a href="#" onClick="warning('确实要删除吗', '{:url('article/del',array('id'=>$vo['id']))}')" class="btn btn-danger">
<i class="fa fa-trash-o"></i> 删除
</a>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
</div>
<div class="row justify-content-center"> {$list|raw}</div>
</body>
</html>

add.html:
<!DOCTYPE html>
<html>
<head>
<title>后台管理</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap-4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="row">
<div class="col-lg-12 col-sm-12 col-xs-12">
<div class="p-1 mb-2 bg-success text-white">新增文章</div>
<hr>
<form role="form" action="" enctype="multipart/form-data" method="post">
<div class="form-group row">
<label for="title" class="col-sm-2 col-form-label text-right">文章标题</label>
<div class="col-sm-6">
<input class="form-control" id="title" placeholder="" name="title" type="text" required>
</div>
<p class="col-sm-4 text-danger">* 必填</p>
</div>
<div class="form-group row">
<label for="author" class="col-sm-2 col-form-label text-right">文章作者</label>
<div class="col-sm-6">
<input class="form-control" id="author" placeholder="" name="author" type="text">
</div>
</div>
<div class="form-group row">
<label for="keywords" class="col-sm-2 col-form-label text-right">关键字</label>
<div class="col-sm-6">
<input class="form-control" id="keywords" placeholder="" name="keywords" type="text">
</div>
</div>
<div class="form-group row">
<label for="desc" class="col-sm-2 col-form-label text-right">文章描述</label>
<div class="col-sm-6">
<textarea name="desc" class="form-control" id="desc"></textarea>
</div>
</div>
<div class="form-group row">
<label for="pic" class="col-sm-2 col-form-label text-right">缩略图</label>
<div class="col-sm-6">
<input id="pic" placeholder="" name="pic" type="file" accept=".jpg, .gif, .png">
</div>
</div>
<div class="form-group row">
<label for="downhttp" class="col-sm-2 col-form-label text-right">下载网址</label>
<div class="col-sm-6">
<input class="form-control" id="downhttp" placeholder="" name="downhttp" type="text">
</div>
</div>
<div class="form-group row">
<label for="cateid" class="col-sm-2 col-form-label text-right">所属栏目</label>
<div class="col-sm-2">
<select class="form-control" name="cateid" id="cateid" required>
<option value="">请选择栏目</option>
{volist name="cateres" id="vo"}
<option value="{$vo.id}">{$vo.catename}</option>
{/volist}
</select>
</div>
<p class="col-sm-4 text-danger">* 必填</p>
</div>
<div class="form-group row">
<div class="col-sm-2 text-right">是否推荐</div>
<div class="col-sm-6">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" name="state" id="state">
<label class="custom-control-label" for="state">推荐</label>
</div>
</div>
</div>
<div class="form-group row">
<label for="tsort" class="col-sm-2 col-form-label text-right">文章排序</label>
<div class="col-sm-6">
<input class="form-control" id="tsort" placeholder="" name="tsort" type="text">
</div>
</div>
<div class="form-group row">
<label for="content" class="col-sm-2 col-form-label text-right">文章内容</label>
<div class="col-sm-6">
<label>
<textarea name="content" id="content"></textarea>
</label>
</div>
</div>
<div class="form-group">
<div class="offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存信息</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>

edit.html:
<!DOCTYPE html>
<html>
<head>
<title>后台管理</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap-4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="row">
<div class="col-lg-12 col-sm-12 col-xs-12">
<div class="p-1 mb-2 bg-success text-white">修改文章</div>
<hr>
<form role="form" action="" enctype="multipart/form-data" method="post">
<input type="hidden" name="id" value="{$articles.id}">
<div class="form-group row">
<label for="title" class="col-sm-2 col-form-label text-right">文章标题</label>
<div class="col-sm-6">
<input class="form-control" id="title" placeholder="" name="title" value="{$articles.title}" type="text" required>
</div>
<p class="col-sm-4 text-danger">* 必填</p>
</div>

<div class="form-group row">
<label for="author" class="col-sm-2 col-form-label text-right">文章作者</label>
<div class="col-sm-6">
<input class="form-control" id="author" placeholder="" name="author" value="{$articles.author}" type="text">
</div>
</div>
<div class="form-group row">
<label for="keywords" class="col-sm-2 col-form-label text-right">关键字</label>
<div class="col-sm-6">
<input class="form-control" id="keywords" placeholder="" name="keywords" value="{$articles.keywords}" type="text">
</div>
</div>
<div class="form-group row">
<label for="desc" class="col-sm-2 col-form-label text-right">文章描述</label>
<div class="col-sm-6">
<textarea name="desc" class="form-control" id="desc">{$articles.desc}</textarea>
</div>
</div>
<div class="form-group row">
<label for="pic" class="col-sm-2 col-form-label text-right">缩略图</label>
<div class="col-sm-6">
<input id="pic" placeholder="" name="pic" style="display:inline;" type="file" accept=".jpg, .gif, .png">
{if condition="$articles['pic'] neq ''"}
<img src="{$articles.pic}" height="50">
{else /}
<span>暂无缩略图</span>
{/if}
</div>
</div>
<div class="form-group row">
<label for="downhttp" class="col-sm-2 col-form-label text-right">下载网址</label>
<div class="col-sm-6">
<input class="form-control" id="downhttp" placeholder="" name="downhttp" value="{$articles.downhttp}" type="text">
</div>
</div>
<div class="form-group row">
<label for="cateid" class="col-sm-2 col-form-label text-right">所属栏目</label>
<div class="col-sm-2">
<select class="form-control" name="cateid" id="cateid" required>
<option value="">请选择栏目</option>
{volist name="cateres" id="vo"}
<option {if condition="$vo['id'] eq $articles['cateid']"}selected="selected"{/if} value="{$vo.id}">{$vo.catename}</option>
{/volist}
</select>
</div>
<p class="col-sm-4 text-danger">* 必填</p>
</div>
<div class="form-group row">
<div class="col-sm-2 text-right">是否推荐</div>
<div class="col-sm-6">
<div class="custom-control custom-checkbox">
<input {if condition="$articles['state'] eq 1"}checked="checked"{/if} type="checkbox" class="custom-control-input" name="state" id="state">
<label class="custom-control-label" for="state">推荐</label>
</div>
</div>
</div>
<div class="form-group row">
<label for="tsort" class="col-sm-2 col-form-label text-right">文章排序</label>
<div class="col-sm-6">
<input class="form-control" id="tsort" placeholder="" name="tsort" value="{$articles.tsort}" type="text">
</div>
</div>
<div class="form-group row">
<label for="content" class="col-sm-2 col-form-label text-right">文章内容</label>
<div class="col-sm-6">
<label>
<textarea name="content" id="content">{$articles.content}</textarea>
</label>
</div>
</div>
<div class="form-group">
<div class="offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存信息</button>
</div>
</div>
</form>
</div>
</div>
</body>
</html>

8、隐藏入口文件index.php(为了网址简短)
以 Apache 为例,需要在入口文件的同级添加 .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>
如果用的 phpstudy ,规则如下:
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
</IfModule>
如果你使用的 apache 版本使用上面的方式无法正常隐藏 index.php ,可以尝试使用下面的方式配置 .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>
如果是 Nginx 环境的话,可以在 Nginx.conf 中添加:
(找到nginx的配置文件 nginx.conf, 在里面的 server{ } 里增加以下内容)
location / {//…..省略部分代码
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=/$1 last;
break;} }
thinkphp5 IIS7.5 隐藏index.php的方法:
web.config文件里:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="WPurls" enabled="true" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
根据不同的空间,请将上面的伪静态规则,保存为.htaccesss文件或Httpd.ini或web.config文件,并放到ThinkPHP项目入口文件同级目录下。
附:伪静态配置
Apache Rewrite的配置:Apache下的Rewrite配置主要有两种,一种是针对整个apache服务器的配置,此种配置的Rewrite规则是直接在httpd.conf下书写。另一种是针对apache服务器下的某一目录的配置,此种配置的Rewrite规则需在此目录下建立一个.htaccess文件来书写。
IIS 服务器:web.config 主要应用在iis7/iis7.5的服务器上,httpd.ini 主要应用在iis以及iis6 的服务器上,跟.htaccess的规则比较接近。
NGINX服务器:nginx里使用伪静态是直接在配置文件nginx.conf 中写规则的,在里面的 server{ } 中写需要的规则即可。

9、配置路由文件(为了网址简短)
打开route文件夹中的route.php,配置如下:
Route::rule('/', 'admin/article/lst');//相当于用http://127.0.0.1/ 则访问到admin模块下的article控制器的lst方法
Route::rule('add', 'admin/article/add');//相当于用http://127.0.0.1/add 则访问到admin模块下的article控制器的add方法
Route::rule('edit', 'admin/article/edit');

10. 运行应用调试
为了在开发过程中调试,可以打开config文件夹中database.php中的'debug'=>true(数据库调试模式)和app.php中的'app_debug' =>true( 应用调试模式)、'app_trace'=>true(应用跟踪Trace调试)
我们在浏览器里面输入:http://localhost/ 就可以看到页面的输出了
由于我们开启了调试模式,所以在页面的最下面还会看到一些额外的调试信息,并且可以很清楚的看到当前页面的请求信息和执行时间、 SQL 日志,最后还有加载的文件列表,事实上,页面 Trace 信息的显示完全是可以定制的,而这些内容不需要在模板里面定义。在 ThinkPHP 中,我们称之为页面 Trace 信息,这是为了在开发过程中调试用的,关闭调试模式后,这些信息会自动消失。另外在调试模式下面,由于开启了日志记录,并且关闭了所有缓存,所以执行效率会有一定影响,但是关闭调试模式后,效率会有非常显著的提高。

到目前为止,我们已经完成了一个完整的数据操作应用了。

猜你喜欢

转载自www.cnblogs.com/cmwjr/p/12764699.html