手上带的一个项目,后端用的是PHP的TP5框架。

去年对其因为了解不够深入,开发时没用成前后端分离的模式,踩了很多坑。前后端不分离意味着:

  1. 不能使用Webpack对Vue页面进行打包压缩和混淆,安全性和开发效率都大大降低。
  2. 负责前端的同学得和负责PHP的同学在同一个HTML上操作,你编辑的时候TA就不能写,TA编辑的时候你就不能写。不然你俩各自写完先后保存,前一个保存的人写的代码会被覆盖,那不大冤种吗。

所以今年探索了一下TP5框架如何在宝塔面板进行配置,使之能访问Vue单页面应用。

TP5目录结构

先来了解下TP5框架的目录结构,方便对其大致有个了解。

  • 一共有6个重要目录:

    1. application:应用目录,用户大部分代码都写在这个里边
    2. public:对外可访问web目录
    3. config:框架配置目录,每个文件对应着一级配置
    4. runtime:运行目录,存放临时生成的缓存文件或编译脚本文件
    5. route:路由目录,存放用户自定义的路由定义
    6. thinkphp:框架核心目录(尽可能不要修改,以方便框架升级)
  • 两个其他目录:

    1. extend:扩展类库目录,用来存放不便归类模块和扩展框架功能
    2. vender:由Composer加载并管理的第三类库目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//站点文件夹
|-application //应用目录(几乎整个项目的内容都写在这里,这里面的文件夹在tp5中叫做模块)
|-index //index一般是前台模块,也可以根据需要需求修改成其他(例如:home),需要修改配置文件,修改默认模块、控制器、操作) 【注】:TP5默认只有一个index文件(模块)和一个控制层(conrroller),我们在写代码的时候会自己新建一个model和view,这样就组成了这个Index模块儿的MVC(controller控制层,model模型层,view视图层),如需后台(一般来说都需要),则需要新建一个后台模块(admin)
|-controller //(控制层)
|-model //(模型层)
|-view //(视图层)
|-admin //后台模块,其他模块同理,随意添加
|-controller //(控制层)
|-model //(模型层)
|-view //(视图层)
|- command.php //是控制台的配置文件,当我们用命令行执行thinkphp的时候,它会读取command.php的配置
|- common.php //它是项目的公共文件,当我们编写一些通用函数的时候,比如我们写一个函数,想在所有的模块儿中都能调用,那么我们就可以把函数写在改文件中,它就可以注册到全局,在任何地方都可以调用
|- config.php //它是应用的配置文件,整个用用都读取这个配置,也就是admin模块儿和index模块儿会通用这个配置
|- database.php //它是数据库配置文件,如果我们需要连接数据库,那么我们只需要修改database.php的配置就可以了
|- route.php //它是路由文件,当我们想对URL进行美化,那么我们就可以修改此文件,对其增加一些路由配置,就可以达到美化的效果
|- tags.php //它是应用行为扩展文件,在thinkphp中,它为我们埋下了很多钩子,我们可以对框架进行扩展,而不需要修改框架本身的源码,我们需要在某一个钩子上注册某些函数,或者是注册某些行为,来通过行为来改变框架的执行流程
|-extend //目录,这个目录是我们下载第三方库时候使用的,当然我们不是通过composer来下载的,比如说我们有一个第三方库,我们用着比较好用,但是它没有composer包,我们就可以将类库下载到extend目录,之后我们修改一下命名空间,就可以直接在我们的应用中使用
|-publiic //我们网站的根目录,也就是说我们网站根目录下所有的这些文件都是允许访问的
|-static //主要用来放静态文件,比如说css,js,图片等等
|-index.php //整个网站或整个应用的入口文件,所有的请求都会经过index.php之后再去转发
|-router.php //它是框架快速启动的测试文件,比如你本地没有安装Apache,只安装了PHP,那么我们可以通过PHP内置的workserver来启动,通过这个文件,我们就可以启动这个框架
|-runtime //它是网站运行中的缓存文件,它包括日志,缓存和编译文件等等。
|-thinkphp //它是框架文件,也就是说thinkphp5的框架都在里边
|-lang //里边是语言包
|-library //目录是框架的核心,它里边有think(它是整个框架的核心文件)和traits(它是类库的扩展)两个目录
|-think Thin //类库包目录
|-traits 系统 //Traits 目录
|-tpl //是我们框架默认的一些模板(了解知识)
|-default_index.tpl //它是我们自动生成的控制器模板文件
|-dispatch_jump.tpl //它是我们网站发出成功或失败的中间跳转文件
|-page_trace.tpl //它是我们调试时显示的模板文件
|-think_exception.tpl //它是我们抛出异常时页面展示的文件
|-base.php //定义一些常量
|-console.php //它是控制台的入口文件
|-convention.php //是框架惯例配置文件
|-help.php //助手函数
|-start.php //是框架启动文件
|-vendor //是composer安装过程中生成的目录,通过composer安装的所有类库都被安装在了这个目录中

应用目录介绍

  • TP5学习的重点是框架的MVC设计模式,将全部在application应用目录中体现。我们几乎全部的代码都写在了应用目录对应模块中:

    1. common:公共模块目录,存放被其它模块所共享的代码,外部禁止URL访问
    2. module:模块目录,可以有多个例如index,admin
  • application应用目录细节如下,对于每一个模块,我们最关心的是modelviewcontroller目录,即MVC架构:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    |--index        //index模块
    | |--controller //控制器类库目录
    | | |--Index.php //Index控制器类
    | | |--User.php //User控制器类
    | |--model //模型类库目录
    | | |--User.php //User模型类,通常对应user数据表
    | | |--Goods.php //Goods模型类,通常对应goods数据表
    | |--view //视图目录
    | | |--index //index目录通常对应着Index控制器
    | | | |--index.php //与Index控制器类中的index操作对应
    | | |--user //user目录通常对应着 User 控制器
    | | | |--add.php //与User控制器类中的add操作对应
    | |--config //模块配置目录(可选)
    | |--common.php //模块公共函数库(可选)
    |
    |--config //应用配置目录(可选)
    |--common.php //应用公共函数库(可选)

在宝塔面板部署

1. 站点初始化

  • 添加站点,创建数据库,选择PHP版本

  • 域名解析就省略不说了,别忘了解析后访问一下通不通

2. TP5框架初始化

  • 找个TP5空框架上传到网站目录

  • 打开站点设置,将网站目录中的运行目录从/修改为/public。因为这是TP5对外可访问web目录,将来这里放前端Vue打包的文件,修改后浏览器通过域名直接可以访问到这里的index.html前端页面

  • 修改application应用目录下的database.php数据库配置文件,添上数据库名称、用户名和密码

3. 创建Web页面

  • 在TP5对外提供访问的web目录public下创建一个index.html页面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>12345</title>
    <style>
    .container {
    width: 60%;
    margin: 10% auto 0;
    background-color: #f0f0f0;
    padding: 2% 5%;
    border-radius: 10px
    }

    ul {
    padding-left: 20px;
    }

    ul li {
    line-height: 2.3
    }

    a {
    color: #20a53a
    }
    </style>
    </head>
    <body>
    <div class="container">
    <h1>Hello!</h1>
    <h3>此页面是TP5框架public文件夹下的index.html</h3>
    </div>
    </body>
    </html>
  • 通过域名http://网站域名.com/打开站点,正常的话就能看到该页面了

将来前端写好Vue页面后,将打包出来的index.html页面,以及其他资源文件夹如cssjsimgfonts等前端的东西,统统放进public目录下即可。换句话说,整个public可以看做分给前端的地盘,存放页面和静态资源。

那如果前端不是用Vue写的单页面应用,除了index.html之外还有其他页面目录,那怎么访问?那不简单嘛,按正常目录结构呗,我整理了一下几种情况(当然真实开发肯定不这么写,仅用来演示访问的几种情况):

1
2
3
4
5
6
7
8
9
//TP5对外访问的web目录
|--public
| |--index.html //访问网址 http://网站域名.com
| |--login
| | |--index.html //访问网址 http://网站域名.com/login
| |--home
| | |--index.html //访问网址 http://网站域名.com/home
| |--register.html //访问网址 http://网站域名.com/register.html
| |--我是一个文档.pdf //访问网址 http://网站域名.com/我是一个文档.pdf

重定义应用入口路径

在我接手的之前的旧项目中,我发现页面其实并没有写到/public下,而是写到了/application/index/view/中,目录结构大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//TP5应用目录
|--application
|--index //index模块
| |--controller
| | |--Index.php
| | |--Home.php
| |--model
| | |--略
| |--view
| | |--index //index页面目录
| | | |--index.html //访问网址 http://网站域名.com
| | |--home //home页面目录
| | | |--home.html //访问网址 http://网站域名.com/index/home
|--config
|--common.php

究其原因,我发现/public中有两个PHP文件,一个是index.php,另一个是router.php,应该是它俩的作用效果。

定义到application

我们已经知道,TP5之前的外部访问入口路径是/public,那现在打开站点设置,查看默认文档

1
2
3
4
5
6
index.php
index.html
index.htm
default.php
default.htm
default.html

会发现站点的默认入口文件里index.php的优先级高于index.html,这就意味着如果在TP5的对外访问目录public下同时存在index.phpindex.html两个文件,网站会选择听index.php的而不是index.html的。(你现在知道谁是老大了吼!这个index.html就是逊啦!)

现在我们在public下创建如下index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

// [ 应用入口文件 ]

// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

可以看到它重新定义了对外访问的应用目录,从原来的/public修改为了/../application/

也就是说,你通过http://网站域名.com访问站点的话,它先根据站点配置文件去/public找。一看里面同时存在index.phpindex.html两个文件,它会只听前者的。再继续,index.php让它去找TP5框架application应用目录,于是它就会去找application目录下index模块的view视图目录,如果在里面有index/index.html,它就显示出来,如果没有,它就会报错:模板文件不存在:/www/wwwroot/网站域名.com/public/../application/index/view/index/index.html

那要是按如上修改了,怎么访问其他页面?

那就把/applicationindex模块的视图层view当成根目录呗,依旧很简单,我整理一下(假如有index和login两个页面):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//TP5应用目录
|--application
|--index //index模块
| |--controller //控制器类库目录
| | |--Index.php
| | |--Home.php
| |--model //模型类库目录
| | |--略
| |--view //视图目录
| | |--index //index页面目录
| | | |--index.html //访问网址 http://网站域名.com
| | |--home //home页面目录
| | | |--home.html //访问网址 http://网站域名.com/index/home
| |--config //模块配置目录(可选)
| |--common.php //模块公共函数库(可选)
|
|--config //应用配置目录(可选)
|--common.php //应用公共函数库(可选)

然后旧项目中/public目录下的router.php我没看懂是干什么的,我知道是路由,但删掉也没见影响页面显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$

if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
return false;
} else {
if (!isset($_SERVER['PATH_INFO'])) {
$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
}
require __DIR__ . "/index.php";
}

定义到站点根目录

在搜相关知识的过程中,发现还能将TP5的首页定位到根目录下。但其实没必要,下方内容不看也罢。

  • 将public目录下的index.php移动到根目录。

  • 将index.php文件内容进行修改。

    • 修改前
      1
      2
      3
      4
      // 定义应用目录
      define('APP_PATH', __DIR__ . '/../application/');
      // 加载框架引导文件
      require __DIR__ . '/../thinkphp/start.php';
    • 修改后(每行删了一个英文点)
      1
      2
      3
      4
      // 定义应用目录
      define('APP_PATH', __DIR__ . '/./application/');
      // 加载框架引导文件
      require __DIR__ . '/./thinkphp/start.php';
  • 将public目录下的.htaccess移动到根目录,这个是Apache用户配置文件(伪静态)

  • 修改public目录下的router.php文件

    • 修改前
      1
      2
      3
      4
      5
      6
      7
      8
      if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
      return false;
      } else {
      if (!isset($_SERVER['PATH_INFO'])) {
      $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
      }
      require __DIR__ . "/index.php";
      }
    • 修改后(最后一行加了一个英文点)
      1
      2
      3
      4
      5
      6
      7
      8
      if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
      return false;
      } else {
      if (!isset($_SERVER['PATH_INFO'])) {
      $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
      }
      require __DIR__ .. "/index.php";
      }
  • 修改后就可以通过类似http://网站域名.com/admin访问页面了,由于html在/application里,访问静态资源需要在资源文件路径前添加/public/


参考内容:

[1] 司文秦瘦. tp5目录结构. CSDN博客. 2019.
[2] GP_宣泄笔记. TP5目录结构. CSDN博客. 2018.
[2] tp5将首页定位到根目录下的解决方法