ThinkPHP之入门讲解

1 ThinkPHP

ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。
ThinkPHP 官网地址

1.1 框架

1.1.1 目录讲解

1.1.1.1 5.x

ThinkPHP 5.x 目录结构如下,默认是支持多模块
以下内容以5.0为基础讲解
project 应用部署目录

├─application 应用目录(可设置)
│ ├─common 公共模块目录(可更改)
│ ├─index 模块目录(可更改)
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ ├─command.php 命令行工具配置文件
│ ├─common.php 应用公共(函数)文件
│ ├─config.php 应用(公共)配置文件
│ ├─database.php 数据库配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─route.php 路由配置文件
├─extend 扩展类库目录(可定义)
├─public WEB 部署目录(对外访问目录)
│ ├─static 静态资源存放目录(css,js,image)
│ ├─index.php 应用入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于 apache 的重写
├─runtime 应用的运行时目录(可写,可设置)
├─vendor 第三方类库目录(Composer)
├─thinkphp 框架系统目录
│ ├─lang 语言包目录
│ ├─library 框架核心类库目录
│ │ ├─think Think 类库包目录
│ │ └─traits 系统 Traits 目录
│ ├─tpl 系统模板目录
│ ├─.htaccess 用于 apache 的重写
│ ├─.travis.yml CI 定义文件
│ ├─base.php 基础定义文件
│ ├─composer.json composer 定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 惯例配置文件
│ ├─helper.php 助手函数文件(可选)
│ ├─LICENSE.txt 授权说明文件
│ ├─phpunit.xml 单元测试配置文件
│ ├─README.md README 文件
│ └─start.php 框架引导文件
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件

1.1.1.2 6.0以上

6.0以上,默认安装后的目录结构就是一个单应用模式,如下结构
www WEB部署目录(或者子目录)

├─app 应用目录
│ ├─controller 控制器目录
│ ├─model 模型目录
│ ├─ ... 更多类库目录
│ │
│ ├─common.php 公共函数文件
│ └─event.php 事件定义文件

├─config 配置目录
│ ├─app.php 应用配置
│ ├─cache.php 缓存配置
│ ├─console.php 控制台配置
│ ├─cookie.php Cookie配置
│ ├─database.php 数据库配置
│ ├─filesystem.php 文件磁盘配置
│ ├─lang.php 多语言配置
│ ├─log.php 日志配置
│ ├─middleware.php 中间件配置
│ ├─route.php URL和路由配置
│ ├─session.php Session配置
│ ├─trace.php Trace配置
│ └─view.php 视图配置

├─view 视图目录
├─route 路由定义目录
│ ├─route.php 路由定义文件
│ └─ ...

├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写

├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor Composer类库目录
├─.example.env 环境变量示例文件
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件

如果需要一个多应用的项目架构,目录结构可以参考下面的结构进行调整,但首先需要安装ThinkPHP的多应用扩展(命令:composer require topthink/think-multi-app),具体可以参考多应用模式

www WEB部署目录(或者子目录)
├─app 应用目录
│ ├─app_name 应用目录
│ │ ├─common.php 函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ ├─config 配置目录
│ │ ├─route 路由目录
│ │ └─ ... 更多类库目录
│ │
│ ├─common.php 公共函数文件
│ └─event.php 事件定义文件

├─config 全局配置目录
│ ├─app.php 应用配置
│ ├─cache.php 缓存配置
│ ├─console.php 控制台配置
│ ├─cookie.php Cookie配置
│ ├─database.php 数据库配置
│ ├─filesystem.php 文件磁盘配置
│ ├─lang.php 多语言配置
│ ├─log.php 日志配置
│ ├─middleware.php 中间件配置
│ ├─route.php URL和路由配置
│ ├─session.php Session配置
│ ├─trace.php Trace配置
│ └─view.php 视图配置

├─public WEB目录(对外访问目录)
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写

├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor Composer类库目录
├─.example.env 环境变量示例文件
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件

注意:多应用模式部署后,记得删除app目录下的controller目录(系统根据该目录作为判断是否单应用的依据)

1.1.2 配置文件

1.1.2.1 5.x

三个层级的配置文件:

  • 框架主配置文件(惯例配置文件) thinkphp/convention.php
  • 应用公共配置文件 application/config.php, application/database.php 对整个应用生效
  • 模块配置文件 application/模块目录/config.php 对当前模块生效

其他说明:

  • 配置文件格式 return array( 键值对 );
  • 加载顺序: 框架主配置文件->应用公共配置文件->模块配置文件
  • 配置文件生效顺序: 后加载的生效(后加载的配置项会覆盖之前配置项)
  • 如果要手动进行配置,一般不要修改框架本身的主配置文件,而是在应用或者模块配置文件中进行配置。

1.1.2.2 6.0以上

在 ThinkPHP 6以上,thinkphp/convention.php 这个配置文件确实已经不再存在了。ThinkPHP 6 相较于之前的版本有了较大的改动,特别是在配置文件的管理方面。具体来说:

  • 在 ThinkPHP 6 中,默认的配置文件被分散到了多个独立的配置文件中,放置在 config 目录下。每个配置文件针对不同的功能模块,例如 app.php、database.php、cache.php 等。这样的设计让配置更加模块化和清晰。
  • convention.php 的去除
    在 ThinkPHP 5.x 及之前的版本中,thinkphp/convention.php 用于存放框架的默认配置,这些配置在未被用户覆盖时会生效。
    从 ThinkPHP 6 开始,这种集中式的默认配置文件被取消,取而代之的是多个配置文件。
  • 配置优先级
    在 ThinkPHP 6 中,用户可以通过 config 目录中的文件来覆盖框架的默认配置。框架提供了一些默认配置,但这些配置是直接通过代码实现的,而不是放在一个单独的文件中。
  • 如何自定义配置
    如果需要自定义配置,可以在 config 目录中创建自己的配置文件,或者直接修改现有的配置文件。或者通过 config() 函数来获取和设置配置项。

1.1.3 函数文件

1.1.3.1 5.x

框架助手函数文件 thinkphp/helper.php,一般不建议直接修改thinkphp/helper.php
应用公共函数文件 application/common.php
模块函数文件 application/模块目录/common.php

1.1.3.1 6.0以上

移除thinkphp/helper.php

  • 在 ThinkPHP 5.x 中,thinkphp/helper.php 文件,主要用于定义一些常用的辅助函数。这些辅助函数在项目开发中可以直接调用,简化了开发工作。
    但是,在 ThinkPHP 6.x 及更高版本中,thinkphp/helper.php 文件被移除了。原因是框架开发团队希望简化核心代码,并且推荐开发者通过引入自己需要的库或工具来实现相应的功能,而不是依赖于框架内置的辅助函数。
    在 ThinkPHP 6.x 中的替代方案:
    • Composer 引入工具包:对于一些常用的功能,可以通过 Composer 引入第三方库来实现。例如,可以使用 symfony/var-dumper 来替代 dump 函数。
    • 自定义辅助函数:如果有一些常用的函数,可以在项目中创建自己的辅助函数文件,然后在项目的入口文件(如 app.php)中引入它。

移除app/模块目录/common.php

  • 在 ThinkPHP 6 中,app/模块目录/common.php 文件被移除是为了简化和灵活化项目结构。如果需要在模块中定义公共函数,可以在 app/common.php 中统一管理
    倡导将公共函数集中管理,通常放在 app/common.php 文件中,这样可以避免每个模块都定义自己的 common.php,从而减少冗余代码,并且使得跨模块调用更加便捷

1.2 控制器

1.2.1 控制器的后缀

打开配置文件application/config.php,有如下配置:'controller_suffix' => false,
表示默认情况下,控制器无特殊后缀。例如 Index控制器,文件名为Index.php
如果需要进行设置,可以设置为(我们不需要这么设置):'controller_suffix' => 'Controller',表示控制器以Controller为后缀。例如Index控制器,文件名为IndexController.php

定义位置及命名规则:

  • 定义位置:application/模块目录/controller/目录下(6.0以上默认是app了)
  • 命名规则:控制器名称(首字母大写) + (控制器后缀,默认没有) + .php
  • 默认:Index控制器 Index.php,User控制器 User.php,UserType控制器 UserType.php,Test控制器 Test.php

编写控制器:

  • 声明命名空间:namespace app\模块目录名\controller
  • 引入控制器基类(可选):use think\Controller;,其中think是命名空间 Controller是基类控制器
  • 定义当前控制器类,继承控制器基类(可选)

1.2.2 框架中的命名空间

命名空间本身是PHP就有的,用来防止命名冲突问题的。
TP框架中的命名空间,通常和目录挂钩。
原因:TP中的自动加载机制,会将类的命名空间作为加载路径的一部分。

TP中命名空间使用:

  • 声明命名空间 使用namespace关键字
  • 引入指定的类 使用use关键字 命名空间\类名称
  • 完全限定式访问 在使用类时,\完整命名空间\类名称(继承和实例化)
  • 如果一个类没有命名空间,使用 \类名

1.2.3 url访问

ThinkPHP5.0框架中,默认使用PATH_INFO方式的url进行访问。
示例:http://www.tpshop.com/index.php/Index/Test/index/page/10
格式:http://域名/入口文件/模块名/控制器名称/操作方法名称/参数名/参数值
隐藏入口文件写法:http://域名/模块名/控制器名称/操作方法名称/参数名/参数值

1.2.4 调试模式

1.2.4.1 5.x

默认情况下,如果代码有误(比如控制器名拼写有误),会出现比较模糊的错误
错误描述比较模糊,不方便进行错误调试。这种模式通常叫做部署模式(生产模式)。
开发阶段可以将框架设置为调试模式,便于进行错误调试:
修改 项目目录\application目录\config.phpapp_debug=>true
开启调试模式后,报错信息格式就会很清晰

1.2.4.2 6.0以上

调试模式配置在 config/app.php 文件中,通过 app_debug => true 设置
如果通过create-project默认安装的话, 会在根目录自带一个.example..env文件,你可以直接更名为.env文件中修改APP_DEBUG = true也可以

1.3 创建模块

1.3.1 创建前台和后台模块

一个典型的应用是由多个模块组成的(通常有前台网站模块和后台管理系统模块),这些模块通常都是应用目录下面的一个子目录,每个模块都有自己独立的配置文件、公共文件和类库文件。

我们给项目创建home(前台)和admin(后台)两个模块
在这里插入图片描述

1.3.2 设置默认访问模块

打开配置文件application/config.php,有如下配置:'default_module' => 'index',表示默认访问模块为index模块,可以更改默认模块为home模块
'default_module' => 'home'

在 6.0以上 中,可以通过修改配置文件来设置默认访问的模块。默认模块的配置通常在 config/app.php 文件中完成:'default_module' => 'admin'

1.4 Request请求类

1.4.1 获取输入变量

要获取当前的请求信息,可以使用\think\Request类

$request = \think\Request::instance();
或者使用助手函数
$request = request();

也可以单独获取get变量或者post变量
Request::instance()->get();
Request::instance()->post();
input('get.');
input('post.');

特殊说明:路由变量与get变量
http://www.tpshop.com/home/test/index/id/100?page=10

  • param:能够获取所有参数(id, page)
  • get:只能获取?后面的请求字符串的参数(page)
  • route:只能获取到?前面的路由中的参数(id)

1.4.2 参数绑定

1.4.2.1 按名称绑定

方法参数绑定是把URL地址(或者路由地址)中的变量作为操作方法的参数直接传入。

<?php
namespace app\index\Controller;

class Blog 
{
    public function read($id)
    {
        return 'id='.$id;
    }
    public function archive($year, $month='01')
    {
        return 'year='.$year.'&month='.$month;
    }
}

注意这里的操作方法并没有具体的业务逻辑,只是简单的示范。
URL的访问地址分别是:

http://serverName/index.php/index/blog/read/id/5
http://serverName/index.php/index/blog/archive/year/2016/month/06

两个URL地址中的id参数和year和month参数会自动和read操作方法以及archive操作方法的同名参数绑定。

1.4.2.1 按顺序绑定(6.0后不支持)

按照URL的参数顺序进行绑定的方式,合理规划URL参数的顺序绑定对简化URL地址可以起到一定的帮助。

还是上面的例子,控制器不变,还是使用:

<?php
namespace app\index\Controller;

class Blog 
{
    public function read($id)
    {
        return 'id='.$id;
    }

    public function archive($year='2016',$month='01')
    {
        return 'year='.$year.'&month='.$month;
    }
}

我们在配置文件中添加配置参数如下:
// URL参数方式改成顺序解析
'url_param_type'         => 1,

接下来,访问下面的URL地址:

http://serverName/index.php/index/blog/read/5
http://serverName/index.php/index/blog/archive/2016/06

注意:按参数顺序绑定的话,参数的顺序不能随意调整,在使用路由定义的情况下不建议使用顺序绑定,而且按 顺序绑定参数的话,操作方法的参数只能使用路由变量或者PATHINFO变量,而不能使用get或者post变量。

1.4.3 依赖注入

依赖注入:简单的说,要在一个类A中使用另一个依赖类B时,不直接在类A中实例化类B,而是先实例化类B后再以参数的形式传入类A.

1.4.3.1 架构方法和方法注入

在控制器的架构方法中会自动注入当前请求对象,例如:

namespace app\index\controller;

use think\Request;

class Index
{
	protected $request;
    
	public function __construct(Request $request)
    {
    	$this->request = $request;
    }
     public function hello(Request $request)
    {
        return 'Hello,' . $request->param('name') . '!';
    }    
}
  • 接收参数 获取请求对象,调用param方法;或者直接调用input函数
  • 参数绑定 在方法上声明形参,自动接收对应同名参数,主要针对id参数
  • 依赖注入 在方法上声明类型形参(Request $request),自动获取请求对象

可以找到任何一种方法 接收请求参数

获取请求对象  
$request = request();
$request = \think\Request::instance();
$request = $this->request; //仅限于继承了底层控制器的情况下
public function save(Request $request)  //依赖注入

接收请求参数 param方法
$params = $request->param();
$params = input();
$params = request()->param();
$id = $request->param('id');
$id = input('id');
public function edit($id)//参数绑定

1.4.3.2 invoke

5.x中 invoke方法自动调用(v5.0.2)
5.0.2版本开始,如果依赖注入的类有定义一个可调用的静态invoke方法,则会自动调用invoke方法完成依赖注入的自动实例化。
invoke方法的参数是当前请求对象实例,例如:

namespace app\index\model;

use think\Model;
class User extends Model
{
	public static function invoke(Request $request)
    {
    	$id = $request->param('id');
        return User::get($id);
    }
}

1.5 视图

1.5.1 视图模板定位

1.5.1.1 5.x

为了对模板文件更加有效的管理,ThinkPHP对模板文件进行目录划分,默认的模板文件定义规则是:视图目录/控制器名(小写)/操作名(小写)+模板后缀
默认的视图目录是模块的view目录,框架的默认视图文件后缀是.html
比如home模块 Index控制器index方法要调用的模板定义为view/index/index.html

渲染模板最常用的是继承系统的控制器基类后调用fetch方法,调用格式:fetch('[模板文件]'[,'模板变量(数组)'])

模板文件的写法支持下面几种:

用法 描述
不带任何参数 自动定位当前操作的模板文件
[模块@][控制器/][操作] 常用写法,支持跨模块
完整的模板文件名 直接使用完整的模板文件名(包括模板后缀)

下面是一个最典型的用法,不带任何参数:

// 不带任何参数 自动定位当前操作的模板文件
return $this->fetch();

表示系统会按照默认规则自动定位模板文件,其规则是:当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html
但是从V5.0.16+版本开始,默认的模板文件名规则改为实际操作方法名的小写+下划线写法。例如,如果操作方法是 showPage,那么模板文件名将变成 show_page.html,但可以配置template.auto_rule的值为2 恢复之前的全小写规则。

如果有更改模板引擎的view_depr设置(假设 'view_depr'=>'_')的话,则上面的自动定位规则变成:
当前模块/默认视图目录/当前控制器(小写)_当前操作(小写).htmlview_depr是用于定义控制器名操作名之间在视图模板中的分隔符

return $this->fetch('edit'); 
表示调用当前控制器下面的edit模板

return $this->fetch('member/read');
表示调用Member控制器下面的read模板。

return $this->fetch('admin@member/edit');
跨模块渲染模板

渲染输出不需要写模板文件的路径和后缀。这里面的控制器和操作并不一定需要有实际对应的控制器和操作,只是一个目录名称和文件名称而已,例如,你的项目里面可能根本没有Public控制器,更没有Public控制器的menu操作,但是一样可以使用

return $this->fetch('public/menu');
输出这个模板文件。理解了这个,模板输出就清晰了。

fetch方法支持在渲染输出的时候传入模板变量,例如:
return $this->fetch('read', ['a'=>'a','b'=>'b']);

V5.0.4+版本开始,支持从视图根目录开始读取模板,例如:
$this->fetch('/menu');
表示读取的模板是:当前模块/默认视图目录/menu.html

如果你的控制器类没有继承系统的控制器基类,请使用系统提供的助手函数view进行渲染输出。

1.5.1.2 6.0以上

默认情况下,框架会自动定位模板文件路径,优先定位应用目录下的view目录,这种方式的视图目录下就是应用的控制器目录。
单应用模式

├─app
│ └─view(视图目录)
│ ├─index index控制器目录
│ │ └─index.html index模板文件
│ └─ ... 更多控制器目录

多应用模式

├─app
│ ├─app1 (应用1)
│ │ └─view(应用视图目录)
│ │ ├─index index控制器目录
│ │ │ └─index.html index模板文件
│ │ └─ ... 更多控制器目录
│ │
│ └─ app2... (更多应用)

第二种方式是视图文件和应用类库文件完全分离,统一放置在根目录下的view目录。
单应用模式

├─view 视图文件目录
│ ├─index index控制器目录
│ │ └─index.html index模板文件
│ └─ ... 更多控制器目录

多应用模式
如果是多应用模式的话,这种方式下view目录下面首先是应用子目录。

├─view 视图文件目录
│ ├─index(应用视图目录)
│ │ ├─index index控制器目录
│ │ │ └─index.html index模板文件
│ │ └─ ... 更多控制器目录

如果需要自定义view目录名称,可以通过设置view_dir_name配置参数:'view_dir_name' => 'template'

模板渲染的最典型用法是直接使用fetch方法,不带任何参数:

<?php
namespace app\index\controller;
use think\facade\View;
class Index
{
    public function index()
    {
        // 不带任何参数 自动定位当前操作的模板文件
        return View::fetch();
    }
}

表示系统会按照默认规则自动定位视图目录下的模板文件,其规则是:控制器名(小写+下划线)/操作名.html
默认的模板文件名规则改为实际操作方法名的小写+下划线写法。但可以配置auto_rule参数的值来改变当前操作的自动渲染规则。
auto_rule配置:

  • 1:操作方法的小写+下划线
  • 2:操作方法全部转换小写
  • 3:保持和操作方法一致
如果没有按照模板定义规则来定义模板文件(或者需要调用其他控制器下面的某个模板),可以使用:
指定模板输出
return View::fetch('edit'); 
表示调用当前控制器下面的edit模板

return View::fetch('member/read');
表示调用Member控制器下面的read模板。

跨应用渲染模板
return View::fetch('admin@member/edit');

支持从视图根目录开始读取模板,例如:
return View::fetch('/menu');
表示读取的模板是 menu.html

如果模板文件位置比较特殊或者需要自定义模板文件的位置,可以采用下面的方式处理。
return View::fetch('../template/public/menu.html');
这种方式需要带模板路径和后缀指定一个完整的模板文件位置,这里的../template/public目录是相对于当前项目入口文件位置。如果是其他的后缀文件,也支持直接输出,例如:

return View::fetch('../template/public/menu.tpl');
只要../template/public/menu.tpl是一个实际存在的模板文件。

1.5.2 模板渲染

在控制器方法中,使用assign方法进行模板赋值,使用fetch方法进行模板渲染。
使用助手函数view(),进行模板渲染并赋值。

注意:模板中输出变量值: {$模板变量名}

posted @ 2024-08-29 15:41  上善若泪  阅读(33)  评论(0编辑  收藏  举报