ThinkPHP最新的6.0版本原计划于国庆左右发布,由于国庆期间本着核心精简的原则对多应用模式做了一些调整,为了避免可能的问题还需要做更充分的测试,加上新版框架的安全审计工作仍然还在继续,所以在计划之外额外发布了一个RC5积累更新版本,正式版本的发布日期推迟到10月24日。

ThinkPHP的应用模式使得开发人员对核心框架进行改造较以往更为得心应手,并且可以让你的应用适应更多的环境和不同的需求。每个应用模式都有自己的模式定义文件,相对于ThinkPHP3.1版本,ThinkPHP3.2版本对应用模式的扩展更加明确和清晰,在ThinkPHP3.1版本中定义了Cli、Lite、Thin、AMF、PHPRPC、REST模式,其定义方式和ThinkPHP3.2版本的方式大同小异,如有需要可以参考修改,其中Cli模式被ThinkPHP框架内置,不用单独定义Cli模式即可正常使用,如需要更细化调整可以参考3.1版编写的Cli运行模式扩展。ThinkPHP同样提供了便捷的开发环境和正式环境的模式切换方式。让我们随着ThinkPHP的运行流程解析其应用模式扩展之谜。

ThinkPHP框架是国内知名度很高应用很广泛的php框架,我们从一些简单的开发示例中来深入了解一下这个框架给我们带来的开发便捷性,以及游刃有余的扩展设计。同时也从源码分析的角度看看框架的一些不足,尽量做全面客观的评价。这里假设大家已经使用过ThinkPHP框架,基本使用方法请参考官方文档。

官方本着认真和严谨的态度对待此次ThinkPHP6.0的发布工作,我们希望交付给开发者的新版是一个更好用而且架构稳定的版本,相信这是一个值得等待的框架。

一、应用模式的使用

一、框架分层及url路由

下面是RC5版本自RC4之后的主要更新,基本上不影响之前版本的升级,并且官方完全开发手册的内容已经同步更新。

在研究应用模式扩展之前,看看如何使用应用模式的吧。一般通过在入口文件定义常量APP_MODE为应用模式名称,但是在分析ThinkPHP框架入口文件时,了解到框架默认采用模式为普通模式(common),而且可以自动识别sae环境,当然前提是没有定义APP_MODE常量时,当然ThinkPHP可以自动识别CLI和CGI模式,并且在CLI和CGI环境下运行ThinkPHP框架在默认模式中自动对这两种环境做了细微调整,当然也可以自己扩展这两种应用模式。

框架的安装非常简单,下载后放入web服务器的目录即可,但是建议大家不要用默认的入口文件位置,而是放入单独的目录,便于保护代码和数据。例如我的入口文件和web服务器配置目录在web目录(外层框架里的index.php没有删除但是没有使用):
澳门新葡萄京官网注册 1

多应用模式调整

鉴于多应用模式的复杂性和扩展性考虑,最新版本把多应用模式独立为框架的一个全局中间件扩展。默认安装后核心框架为单应用模式,如果需要使用多应用模式,可以安装

composer require topthink/think-multi-app

安装后会自动注册一个全局中间件并优先执行,就可以自动支持多应用模式,无需做任何的配置调整。如果需要进行应用映射或者域名绑定的话,仍然设置app_map以及domain_bind即可。

如果你的入口文件是index.php的话,会自动开启自动多应用模式。如果你的入口文件是其它,例如admin.php或者api.php澳门新葡萄京官网注册,则会自动绑定admin或者api应用,当然,如果你在入口文件中已经使用name方法绑定了应用,则优先。

另外,如果是自动多应用模式下,URL里面的应用不存在,会自动处理为单应用解析,也就是说多应用和单应用是可以在新版的架构下共存。举个例子,当我们访问下面的URL:

http://tp.com/think

假设think应用并不存在(也没有定义任何的应用映射),当我们访问上面的地址的时候会自动进行单应用解析,也就是说如果有定义全局路由(例如route/route.php)的话

Route::get('think', function () {
    return 'hello,ThinkPHP!';
});

页面会输出

hello,ThinkPHP!

这样设计的初衷是为了更加方便扩展注册全局路由,避免在开启多应用模式的情况下注册的全局路由失效(比如之前的验证码扩展只能用于单应用模式,多应用模式需要单独注册路由)。

如果你完全不需要单应用模式,也可以设置使用严格的多应用模式

'app_express'    =>    true,
'default_app'    =>    'home',

当我们再次访问

http://tp.com/think

的时候,其实是访问默认(home)应用的think路由。

if(function_exists('saeAutoLoader')){// 自动识别SAE环境
  defined('APP_MODE')   or define('APP_MODE',   'sae');
  defined('STORAGE_TYPE') or define('STORAGE_TYPE', 'Sae');
}else{
  defined('APP_MODE')   or define('APP_MODE',    'common'); // 应用模式 默认为普通模式  
  defined('STORAGE_TYPE') or define('STORAGE_TYPE',  'File'); // 存储类型 默认为File  
}

同大多数MVC框架一样,我们只需要按框架的目录结构,扩展自己的Controller和View,一些页面就开发完成了。ThinkPHP提供Module、Controller、Action三层结构来组织自己的url(3.1版本叫分组、Action和method,3.2更加国际范),目录结构如下:
澳门新葡萄京官网注册 1

中间件机制改进

由于多应用扩展独立后,中间件机制也随之进行了一些优化和调整,现在中间件大致分为四个组,包括全局中间件、应用中间件、路由中间件和控制器中间件,每个中间件组彼此独立按顺序运行。

app/middleware.php文件里面定义的中间件即为全局中间件,执行优先级最高(相对于前置中间件而言),如果使用了多应用模式,并且在应用目录下也定义了middleware.php文件,即为应用中间件,执行优先级仅次于全局中间件。

如果在路由注册的时候定义了中间件即为路由中间件,注意,在路由中间件执行之前是获取不到当前应用的控制器和操作名的(所以,全局中间件和应用中间件执行的过程中是无法获取控制器和操作名的),如果你不想在路由注册的时候定义中间件,还有一个额外的办法,就是在路由配置文件(包括全局路由配置和应用路由配置)中定义middleware参数,无论是否匹配路由都会执行,类似于全局路由中间件的概念。

'middleware'    =>    [
    appmiddlewareAuth::class,
    appmiddlewareCheck::class,
],

二、应用模式定义

这里强烈建议大家:
1、业务单独分层,不用放在Controller和Model里,例如我这里通过扩展函数库Application/Common/Common/function.php强制定义业务层名称为Service:

中间件调度优化

中间件的执行流程改进,thinkmiddleware仅仅负责中间件的管理和调度,增加thinkPipeline类负责中间件的执行。并支持控制中间件的执行顺序。中间件配置文件的格式做了一些调整,除了定义中间件别名外,增加了执行优先级设置。

return [
    // 别名或分组
    'alias'    => [
    ],
    // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
    'priority' => [
    ],
];

在ThinkPHP框架当中除了ThinkPHP框架入口和框架引导类以外,基本所有其他功能都可以通过应用模式进行更改和扩展,如果我们要增加一个应用模式,只需要在ThinkPHPMode目录下面定义一个模式定义文件即可,我们可以通过分析common模式进行学习。该文件的代码如下:

function service($name)
{
    return D($name, 'Service');
}

中间件end回调

中间件增加end回调,如果在中间件类中有定义end方法,则会在请求结束后统一调用。

public function end(Response $response)
{
}
//文件路径:ThinkPHP/Mode/common.php
/**
 * ThinkPHP 普通模式定义
 * 定义一个模式文件,只需要返回一个模式包含文件的数组即可
 * 在数组中主要包含4种扩展文件列表:
 *   config 为默认加载配置文件列表
 *   alias 为核心类库别名配置列表
 *   core 需要加载的核心函数和类文件列表
 *   tags 行为配置列表
 *
 * 如果在应用模式定义中加载一个自定类,那个自定义类的命名空间必须是Think
 */
return array(
  // 配置文件
  'config'  => array(
    THINK_PATH.'Conf/convention.php',  // 系统惯例配置
    CONF_PATH.'config.php',   // 应用公共配置
  ),

  // 别名定义
  'alias'   => array(
    'ThinkLog'        => CORE_PATH . 'Log'.EXT,
    'ThinkLogDriverFile'  => CORE_PATH . 'Log/Driver/File'.EXT,
    'ThinkException'     => CORE_PATH . 'Exception'.EXT,
    'ThinkModel'       => CORE_PATH . 'Model'.EXT,
    'ThinkDb'        => CORE_PATH . 'Db'.EXT,
    'ThinkTemplate'     => CORE_PATH . 'Template'.EXT,
    'ThinkCache'       => CORE_PATH . 'Cache'.EXT,
    'ThinkCacheDriverFile' => CORE_PATH . 'Cache/Driver/File'.EXT,
    'ThinkStorage'      => CORE_PATH . 'Storage'.EXT,
  ),

  // 函数和类文件
  'core'   => array(
    THINK_PATH.'Common/functions.php',
    COMMON_PATH.'Common/function.php',
    CORE_PATH . 'Hook'.EXT,
    CORE_PATH . 'App'.EXT,
    CORE_PATH . 'Dispatcher'.EXT,
    //CORE_PATH . 'Log'.EXT,
    CORE_PATH . 'Route'.EXT,
    CORE_PATH . 'Controller'.EXT,
    CORE_PATH . 'View'.EXT,
    BEHAVIOR_PATH . 'BuildLiteBehavior'.EXT,
    BEHAVIOR_PATH . 'ParseTemplateBehavior'.EXT,
    BEHAVIOR_PATH . 'ContentReplaceBehavior'.EXT,
  ),
  // 行为扩展定义
  'tags' => array(
    'app_init'   => array(
      'BehaviorBuildLiteBehavior', // 生成运行Lite文件
    ),    
    'app_begin'   => array(
      'BehaviorReadHtmlCacheBehavior', // 读取静态缓存
    ),
    'app_end'    => array(
      'BehaviorShowPageTraceBehavior', // 页面Trace显示
    ),
    'view_parse'  => array(
      'BehaviorParseTemplateBehavior', // 模板解析 支持PHP、内置模板引擎和第三方模板引擎
    ),
    'template_filter'=> array(
      'BehaviorContentReplaceBehavior', // 模板输出替换
    ),
    'view_filter'  => array(
      'BehaviorWriteHtmlCacheBehavior', // 写入静态缓存
    ),
  ),
);

好处是复用性好,假如将来要开发wap页面,写了不同的Controller,就可以复用service,假如以后的数据存储变了,比如把数据库从mysql迁移到mongodb之类,那修改Model就可以,service还是不需要任何修改。

中间件执行去重

对于每个分组的中间件,会进行强制去重操作,也就是说在一个分组中的中间件只可能执行一次。

我们看到这个普通应用模式代码之后,有点明了ThinkPHP的应用模式扩展是怎么回事了,但是还是知其然而不知其所以然,定义一个加载文件列表和配置是如何改变框架核心的呢?秘密就在ThinkPHP引导类中,让我们再回顾以下吧!

2、基础模块和业务模块分开,不要相互引用。基础模块(例如用户基本信息)只提供数据接口没有Controller和View。
三层目录已经可以应对一般的web应用,更加复杂的web应用我们可以定义不同的入口文件加载不同的Application来解决。更更复杂的应用?门户和超大规模网站么,那就不是一个php框架能解决所有问题的了,需要自己的中间件和定制框架。

模板目录自动识别

模板目录无需再进行任何的配置,取消了view_base配置,改为自动识别,应用目录下的view目录优先,如果不存在,则会使用应用根目录下的view目录。如果要单独定义某个应用的模板目录,则使用view_path配置参数定义即可。

//判断是否存在core.php配置文件(这是开发环境临时定义的运行模式,我是这么理解的)
     //否者加载APP_MODE定义的模式文件
     $mode  =  include is_file(CONF_PATH.'core.php')?CONF_PATH.'core.php':MODE_PATH.APP_MODE.'.php';
     //加载模式中core定义的核心文件列表
     foreach ($mode['core'] as $file){
       if(is_file($file)) {
        include $file;
        if(!APP_DEBUG) $content  .= compile($file);
       }
     }

     //加载模式中定义的config配置文件列表
     foreach ($mode['config'] as $key=>$file){
       is_numeric($key)?C(include $file):C($key,include $file);
     }

     // 读取当前应用模式对应的配置文件
     if('common' != APP_MODE && is_file(CONF_PATH.'config_'.APP_MODE.'.php'))
       C(include CONF_PATH.'config_'.APP_MODE.'.php'); 

     // 加载模式中alias别名列表定义
     if(isset($mode['alias'])){
       self::addMap(is_array($mode['alias'])?$mode['alias']:include $mode['alias']);
     }

     // 加载应用别名定义文件
     if(is_file(CONF_PATH.'alias.php'))
       self::addMap(include CONF_PATH.'alias.php');

     // 加载模式中tags行为定义
     if(isset($mode['tags'])) {
       Hook::import(is_array($mode['tags'])?$mode['tags']:include $mode['tags']);
     }

     // 加载应用行为定义
     if(is_file(CONF_PATH.'tags.php'))
       // 允许应用增加开发模式配置定义
       Hook::import(include CONF_PATH.'tags.php'); 

     // 加载框架底层语言包
     L(include THINK_PATH.'Lang/'.strtolower(C('DEFAULT_LANG')).'.php');

ThinkPHP的支持4种url访问模式,分别是:

事件智能订阅改进

事件智能订阅的时候不再需要事先注册和定义事件,采用反射机制自动识别订阅事件。

通过ThinkPHP::start()中的这段代码,完美无缝关联的模式定义文件的意义与实现方法。

1、普通模式,传统url模式,所有参数分开,例如

路由参数:m参数表示模块,c表示控制器,a表示访问方法
2、兼容模式
路由参数通过s参数组装,当然数据参数也可以不必放在s参数里
3、pathinfo模式

这种模式把入口文件和真实脚本放在一起,含义明确,也便于SEO
4、rewrite模式

这种模式通过web服务器的rewrite配置隐藏入口文件,显得更加友好
其中pathinfo和rewrite模式需要web服务器支持。ThinkPHP有个配置需要设置为哪种模式,其实是用在U方法里生成url链接的时候用到的,访问的时候只要web服务器支持用哪种方式都可以。
也建议ThinkPHP其实不需要配置,而是记住用户访问的方式,只要第一个访问用的是哪种模式,以后生成的url都用这种方式生成,因为用户都已经访问到了就不存在支不支持的问题了。

应用名获取调整

多应用模式改成扩展后,核心已经完全解耦了多应用相关的方法和属性,所以如果你需要获取当前的应用名,需要改成

app('http')->getName();

对于使用中间件进行权限控制用途的,官方的建议是采用pathinfo地址进行权限判断。

三、定义简单的运行模式

如果正常的url不能达到我们的要求,还可以通过配置路由进一步优化url,例如我们想把url配置的更加简单

我们只需要在模块配置文件中添加如下的路由配置即可,如果用正则表达式则可以更加简化

think-swoole扩展更新

think-swoole扩展也在持续更新和完善,现在已经支持数据库和缓存的连接池功能,以及RPC功能。

手册中有一个模式扩展到的实例,可以拿到这里来分析一下,定义一个lite简洁运行模式,首先在ThinkPHP/Mode目录下新建一个lite.php文件内容定义如下:

'URL_ROUTE_RULES'   =>  array(
        'login/:para' => 'Ucai/User/index',
        'login' => 'Ucai/User/index',
    ),

调试工具更新

原来内置的页面Trace调试工具已经更改为扩展的方式,改成安装think-trace扩展,如果通过composer安装应用的话,默认会安装topthink/think-trace扩展,或者直接安装。

composer require topthink/think-trace

原核心内置的TraceDebug中间件不再使用,请在中间件定义文件中注释掉。

基本用法和之前保持不变,但无需额外配置,默认使用html方式显示,同时仍然支持浏览器控制台显示,并仅在调试模式下有效。

同时增加了一个基于debugbar的调试扩展think-debugbar,需要单独安装后才能使用。

composer require topthink/think-debugbar
return array(  
// 配置文件 
'config'  => array(
        THINK_PATH.'Conf/convention.php',   // 系统惯例配置
        CONF_PATH.'config.php',   // 应用公共配置 
 ),

 // 别名定义  
 'alias'   => array(
       'ThinkException'     => CORE_PATH . 'Exception'.EXT,
       'ThinkModel'       => CORE_PATH . 'Model'.EXT, 
       'ThinkDb'        => CORE_PATH . 'Db'.EXT,
       'ThinkCache'       => CORE_PATH . 'Cache'.EXT,
       'ThinkCacheDriverFile' => CORE_PATH . 'Cache/Driver/File'.EXT,
       'ThinkStorage'      => CORE_PATH . 'Storage'.EXT,
 ),

 // 函数和类文件 
 'core'   => array(
       MODE_PATH.'Lite/functions.php', 
       COMMON_PATH.'Common/function.php',
       MODE_PATH . 'Lite/App'.EXT, 
       MODE_PATH . 'Lite/Dispatcher'.EXT, 
       MODE_PATH . 'Lite/Controller'.EXT,
       MODE_PATH . 'Lite/View'.EXT,
       CORE_PATH . 'Behavior'.EXT,
 ),

 // 行为扩展定义  
 'tags' => array(
       'view_parse'  => array(
           'BehaviorParseTemplate', // 模板解析 支持PHP、内置模板引擎和第三方模板引擎
        ),
        'template_filter'=> array(
           'BehaviorContentReplace', // 模板输出替换
        ),
 ),
);

到这里我们可以看到,ThinkPHP框架支持的层次结构和url配置非常丰富,能满足各种不同的需求。当然我们建议大家不要滥用路由配置,适当少量的配置能带来更好的seo效果,但是大量的配置会给项目的维护和修改带来困难。

关于官网的升级重构

最后一个是关于官网的消息,为了迎接新版的发布,ThinkPHP官网这次终于要更新了。官方计划在本月对旧版(史前)官网进行ThinkPHP6.0的升级重构,同时改进用户体验和手机阅读体验。

(文/开源中国)    

从上面的配置当中我们发现core中的核心文件大多数都被替换了,当然这些需要被替换的程序功能需要我们自己去实现,不过建议大家直接拷贝普通模式中定义的核心文件过来修改。接下来我们来实现以下ThinkPHP应用开发中的核心类库扩展文件App.class.php

二、ThinkPHP扩展

在ThinkPHP/Mode目录下建立一个Lite目录并在lite目录下建立App.class.php文件,以下是程序文件的实现:

ThinkPHP本身含有丰富的组件和驱动,我们以数据库驱动扩展和行为扩展为例来了解一下ThinkPHP的扩展设计。

//模式扩展类库必须是Think命名空间
namespace Think;

/**
 * ThinkPHP 应用程序类 执行应用过程管理 Lite模式扩展类
 * 实现ThinkPHP核心类库扩展时,尽可能仿造原有类库实现(除非对ThinkPHP框架源码特别了解)
 * 因为在其他没有扩展的核心文件中可能会调用扩展的核心类文件中的某个方法,除非你打算全部扩展
 */
class App{
/**
 * 应用程序初始化
 * @access public
 * @return void
 */
static public function init() {
    //具体现实
}

/**
 * 执行应用程序
 * @access public
 * @return void
 */
static public function exec() {
    //具体实现
}

/**
 * 运行应用实例 入口文件使用的快捷方法
 * @access public
 * @return void
 */
static public function run() {
    //具体实现
}

static public function logo(){
    //具体实现
}
}

三、数据库驱动扩展

当文件所有扩展文件的实现后,可以在框架入口文件定义APP_MODE常量为lite

虽然ThinkPHP提供了众多的数据库驱动,但是也并不能满足所有的需求。例如我们的数据很可能不是通过直接访问数据库去实现,而是通过一些中间件(例如C程序)进行转发,从而获得更好的性能,这时就需要扩展数据库驱动来支持。
扩展非常简单,在DB/Driver目录下新建自己的驱动,例如Custom.php,然后实现request和execute方法扩展就算完成了,然后再配置文件里配置DB_TYPE=’custom’,就可以使用了。这里的request表示查询,execute表示更改数据,所有其他操作都会在Model里进行解析,包装成sql语句调用这两个方法执行。
例如我所实现的最简单的query方式,通过shell命令调用sqlite执行sql语句:

另外需要注意一点,手册当中要求定义的MODE_NAME常量来改变运行模式是之前3.1版本中定义运行模式的方法,使用新版本的用户对此需要注意。

public function query($str) {
        $cmd = sprintf('sqlite3 %s "%s"', $this->config['params']['dbfile'], $str);
        exec($cmd, $arr);
}

当然这个只是示例,ThinkPHP本身就支持sqlite3,通过pdo的方式去连接就可以。实际的应用环境可能是通过连接4层协议访问中间层端口获取数据。

四、Behavior行为扩展

Behavior行为设计是ThinkPHP框架的核心,通过行为配置和扩展,为系统的伸缩性和定制性提供了最大的支持。
假如我们要加入登录验证的功能,按照常规我们会设计自己的父类Controller,然后所有其他的Controller都从这里继承。但有了Behavior会变得更加简单和灵活,我们只需要在tags.php(没有的话在配置目录新建)添加一个Behavior就可以了:

return array(
    'action_begin' => array('UcaiBehaviorAuthBehavior'),
    'view_begin' => array('UcaiBehaviorOutputBehavior'),
);

程序在执行到action_begin流程时就会调用这个Behavior,我们可以根据状态进行跳转或终止执行。

namespace UcaiBehavior;
class AuthBehavior {
     // 行为扩展的执行入口必须是run
     public function run(&$return) {
        //不需要验证的action设置为true
         if (!$return['AUTH_PUBLIC']) {
            if (service('User')->checkLogin())
            {
                $return = true;
            }
            else
            {
                header('Content-Type: text/html; charset=utf-8');
                redirect(U('User/index', array('url' => $_SERVER['HTTP_REFERER'])), 5, '需要登录,5秒后跳转。。。');
            }
         }
     }
}

对于不需要登录的页面我们可以在Controller里添加配置,所有不配置的都会要求登录验证。

public $config = array('AUTH_PUBLIC' => true);

这里大家对继承和Behavior实现登录验证做一个对比,可能觉得区别不大。但是在一个复杂的项目里,这种功能会非常多,如果每个功能都放到父类里,就会非常庞大,并且部分子类可能又不需要,这时候用Behavior去定制流程就会显得游刃有余。
在上面的配置中我们还发现了一个配置OutputBehavior更能说明问题,大家有没有猜到,这个Behavior我是用来在view里输出一些共有变量,例如jscss的域名和路径等。在没有Behavior之前,大家是不是需要一个公共方法,然后每个页面都去调用一次,或者改写View的类代码?有了Behavior就显得方便许多。

namespace UcaiBehavior;
class OutputBehavior {
     public function run(&$return) {
        $view = ThinkThink::instance('ThinkView');
        $view->assign('STATIC_URL', 'http://p3.ucai.cn/static');
     }
}

扩展总结:通过Behavior扩展和数据库驱动扩展大家可以看到,ThinkPHP提供了很灵活的扩展和增强机制,能满足众多需求。其他存储、缓存、日志、模板引擎等如果需要也能很方便的扩展。

五、源码分析与不足

首先我们来分析一下框架执行的大致流程:
index.php(入口、调试模式、应用路径)
–> ThinkPHP.php(定义路径与访问模式)
–> ThinkThink(类加载器、异常处理、读取共有配置)
–> ThinkApp(请求url调度解析、执行调度解析结果)
–> exec 执行用户定义的Controller的Action方法
–> ThinkDispatcher(根据url模式解析M、C、A和参数,加载模块配置)
–> ThinkController(调用视图、包装和重定向)
可以看到,框架的内部流程其实比较简单,还有2个很重要的类:
ThinkHook: 监听App、Action、View的各个阶段,执行Behavior
ThinkBehavior: 可配置(配置文件)可增删(代码)

在分析源代码的过程中,我们也看到了一些不足:

1、宏定义过多,难于维护和修改
建议:只在个别文件定义极少数几个宏,其余用类常量包装
2、面向过程代码过多,封装不清晰
建议:用面向对象思想包装
例如:url的解析和包装,现在是在Dispatcher里生成APP宏,然后在U方法里读取宏并生成最终url。其实完全可以定义一个类来包装例如UrlHelper,而类的二个方法parse和generate分别负责解析和生成url,这样代码结构会清晰很多。
3、有的函数和类代码封装过多,复用和改进不方便
建议:用组合来封装独立功能内容
例如:Model的校验功能,完全可以独立成类,也可以用于非Model对象调用。而现在的校验接口是Model的保护性方法,只能在Model的create函数调用,外面必须通过create方法才能校验。
4、代码规范和风格问题
希望代码风格能更加规范和标准,例如DB类作为模板方法的父类,应该用抽象方法或抛出异常形式定义所有Model需用到的方法。事实上有些方法子类是不需要的,而Db类却没有实现。

六、总结

ThinkPHP作为国内热门的php框架,确实给我们的开发带来了便利。框架开发者对web流程理解的很透彻,对php的函数应用炉火纯青。框架定义了灵活的配置和扩展适应各种需求,提供了丰富的组件和模块来加速开发。最后说一点,ThinkPHP的文档和社区支持非常完善,这也是框架流行不可缺少的重要一环。我们也希望ThinkPHP以后能更加完善自身的结构,打造成最优秀的php框架。