3建立个人项目,ThinkPHP框架系统源码解析
分类:www.澳门新萄京赌场

1、Windows下ThinkPHP3.1.3基本配置及相关介绍

ThinkPHP是国内非常火的一个轻量级框架,采用MVC模式,结构写的非常好,今天 大象 带大家走一下ThinkPHP框架系统运行流程,我将跟随ThinkPHP的执行进行代码讲解,第一课,先讲解URL路由解析

一、ThinkPHP的认识:

一、ThinkPHP框架目录
/test/index.php //项目入口文件
/ThinkPHP/ThinkPHP.php //框架入口文件
 
Common 框架公共文件目录(函数库)
ThinkPHP/Common/runtime.php //框架初次运行文件
ThinkPHP/Common/common.php //框架基础函数库
ThinkPHP/Common/functions.php //标准模式公共函数库
 
Conf 框架配置文件目录
ThinkPHP/Conf/convention.php  //惯例配置文件,系统默认配置小于项目配置
ThinkPHP/Conf/debug.php //默认的调试模式配置文件
 
Lang 框架系统语言目录
 
Lib 系统核心基类库目录
ThinkPHP/Core/Think.class.php //入口文件(设置异常和错误处理机制、注册系统自动加载机制、预编译当前项目、加载框架惯例配置文件)
ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类
ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类
ThinkPHP/Lib/Core/App.class.php,   // 应用程序类
ThinkPHP/Lib/Core/Action.class.php, // 控制器类
ThinkPHP/Lib/Core/View.class.php,  // 视图类
 
Tpl 系统模板目录
ThinkPHP/Tpl/default_index.tpl //测试模块的模板
ThinkPHP/Tpl/dispatch_jump.tpl //页面提示的模板
ThinkPHP/Tpl/page_trace.tpl //页面Trace信息的模板
ThinkPHP/Tpl/think_exception.tpl //系统错误信息的模板
 
Extend 框架扩展目录  

Smile Huang

 

tp5

├─application     应用目录

├─extend          扩展类库目录(可定义)

├─public          网站对外访问目录

├─runtime         运行时目录(可定义)

├─vendor          第三方类库目录(Composer)

├─thinkphp        框架核心目录

├─build.php       自动生成定义文件(参考)

├─composer.json   Composer定义文件

├─LICENSE.txt     授权说明文件

├─README.md       README 文件

├─think           命令行工具入口

ThinkPHP是一个快速、简单的基于MVC和面向对象的轻量级PHP开发框架。

<?php
/*
 * 1、用户访问网站URL地址 
 * /test/Index.php 项目入口文件
 */
require ('../ThinkPHP/ThinkPHP.php');//引入框架文件

China University of GeoSciences , Wuhan

一、ThinkPHP框架目录

注意:


如果在linux环境下面的话,需要给runtime目录755权限。

二、下载后的目录结构:

/*
 * 2、载入系统入口文件ThinkPHP.php 
 * ThinkPHP/ThinkPHP.php框架入口文件
 * 判断系统常量,如果没有定义则自动生成
 */
$GLOBALS['_beginTime'] = microtime(TRUE); //记录运行时的时间

Email : SmileHuang94 AT yahoo DOT com

/test/index.php //项目入口文件

 

├─ThinkPHP.php     框架入口文件

define('MEMORY_LIMIT_ON',function_exists('memory_get_usage'));//php中用echo memory_get_usage() 获取当前的内存消耗量 

一、前言

/ThinkPHP/ThinkPHP.php //框架入口文件

有几个关键的路径先了解下:

 ├─Common 框架公共文件

if(MEMORY_LIMIT_ON) $GLOBALS['_startUseMems'] = memory_get_usage();//如果支持内存使用量函数则全局变量$GLOBALS['_startUseMems']等于内存使用量,这里相当于记录下内存初始使用的量

本篇博客主要是用来介绍ThinkPHP3.1.3版本的一些基本配置及如何建立个人项目。

 

目录 说明 常量
tp5 项目根目录 ROOT_PATH
tp5/application 应用目录 APP_PATH
tp5/thinkphp 框架核心目录 THINK_PATH
tp5/exend 应用扩展目录 EXTEND_PATH
tp5/vendor Composer扩展目录 VENDOR_PATH

 ├─Conf 框架配置文件

defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');//设置当前的项目路径

二、ThinkPHP3.1.3基本配置

Common 框架公共文件目录(函数库)

核心框架目录的结构如下:

 ├─Extend 框架扩展目录

defined('RUNTIME_PATH') or define('RUNTIME_PATH',APP_PATH.'Runtime/');//设置runtime的路径

由于ThinkPHP是通过单入口的形式访问的,所以配置ThinkPHP的过程也就是我们创建我们应用的过程,主要分为一下几步:

ThinkPHP/Common/runtime.php //框架初次运行文件

├─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          框架引导文件

 ├─Lang 核心语言包目录

defined('APP_DEBUG') or define('APP_DEBUG',false); // 是否调试模式,默认false

创建应用名称 -- 定义应用路径 -- 指定runtime文件夹路径 -- 引入ThinkPHP核心文件

ThinkPHP/Common/common.php //框架基础函数库

运行环境

ThinkPHP5的环境要求如下:

  • PHP >= 5.4.0 (完美支持PHP7)PDO PHP ExtensionMBstring PHP ExtensionCURL PHP Extension

在开始之前,你需要一个Web服务器和PHP5.4 运行环境,如果你暂时还没有,我们推荐使用集成开发环境WAMPServer(Windows系统下集成Apache、PHP和MySQL的服务套件)来使用ThinkPHP进行本地开发和测试,最新版本的WAMP在这里下载。

如果你不想安装任何WEB服务器,也可以直接使用PHP自带的WebServer,并且运行router.php来运行测试。

我们进入命令行,进入tp5/public目录后,输入如下命令:

php -S localhost:8888 router.php

接下来可以直接访问

http://localhost:8888

注意: S 一定要大写,端口号可以随意设置,只要和已有的不冲突,如果要停止服务,直接在命令行下面按CTRL C即可退出。

 ├─Lib 核心类库目录

$runtime = defined('MODE_NAME')?'~'.strtolower(MODE_NAME).'_runtime.php':'~runtime.php';//如果设置了其它运行模式则~ruturn.php就变化为 ~模式ruturn.php,(例如,采用命令行模式运行),那么在入口文件中定义MODE_NAME如下define('MODE_NAME','cli');  那么这里的缓存文件就为~cliruturn.php

下面以创建Index应用为例展示如何进行相关配置:

ThinkPHP/Common/functions.php //标准模式公共函数库

入口文件

ThinkPHP5.0版本的默认自带的入口文件位于public/index.php(实际部署的时候public目录为你的应用对外访问目录),入口文件内容如下:

// 定义应用目录

define('APP_PATH', __DIR__ . '/../application/');

// 加载框架引导文件

require __DIR__ . '/../thinkphp/start.php';

这段代码的作用就是定义应用目录APP_PATH和加载ThinkPHP框架的入口文件,这是所有基于ThinkPHP开发应用的第一步。

我们可以在浏览器中访问入口文件

http://localhost/tp5/public/

运行后我们会看到欢迎页面:

图片 1

 

官方提供的默认应用的实际目录结构和说明如下:

├─application           应用目录(可设置)

│  ├─index              模块目录(可更改)

│  │  ├─config.php      模块配置文件

│  │  ├─common.php      模块公共文件

│  │  ├─controller      控制器目录

│  │  ├─model           模型目录

│  │  └─view            视图目录

│  │

│  ├─command.php        命令行工具配置文件

│  ├─common.php         应用公共文件

│  ├─config.php         应用配置文件

│  ├─tags.php           应用行为扩展定义文件

│  ├─database.php       数据库配置文件

│  └─route.php          路由配置文件

5.0版本采用模块化的设计架构,默认的应用目录下面只有一个index模块目录,如果我要添加新的模块可以使用控制台命令来生成。

切换到命令行模式下,进入到应用根目录并执行如下指令:

php think build --module demo

就会生成一个默认的demo模块,包括如下目录结构:

├─demo   

│  ├─controller      控制器目录

│  ├─model           模型目录

│  ├─view            视图目录

│  ├─config.php      模块配置文件

│  └─common.php      模块公共文件

同时也会生成一个默认的Index控制器文件。

注意:这只是一个初始默认的目录结构,在实际的开发过程中可能需要创建更多的目录和文件。

在后面的示例中,为了方便访问,我们设置vhost访问,以apache为例的话定义如下:

    DocumentRoot "/home/www/tp5/public"

    ServerName tp5.com

把DocumentRoot修改为你本机tp5/public所在目录,并注意修改本机的hosts文件把tp5.com指向本地127.0.0.1。

如果你暂时不想设置vhost或者还不是特别了解如何设置,可以先把入口文件移动到框架的ROOT_PATH目录,并更改入口文件中的APP_PATH和框架入口文件的位置(这里顺便展示下如何更改相关目录名称),index.php文件内容如下:

// 定义应用目录为apps

define('APP_PATH', __DIR__ . '/apps/');

// 加载框架引导文件

require __DIR__ . '/think/start.php';

这样最终的应用目录结构如下:

tp5

├─index.php       应用入口文件

├─apps            应用目录

├─public          资源文件目录

├─runtime         运行时目录

└─think           框架目录

实际的访问URL变成了

http://localhost/tp5/

提示:


如非特别说明,我们后面的示例均以tp5.com进行访问,如果你使用了其它的方式请自行修改。

 │  ├─Behavior 核心行为类库

defined('RUNTIME_FILE') or define('RUNTIME_FILE',RUNTIME_PATH.$runtime);//设置~runtime.php的路径;

创建一个项目文件夹,此处我的项目文件夹为think,将下好的ThinkPHP解压到think目录下,如图1所示:

 

调试模式

ThinkPHP支持调试模式,默认情况下是开启状态。调试模式以除错方便优先,而且在异常的时候可以显示尽可能多的信息,所以对性能有一定的影响。

我们强烈建议开发者在使用ThinkPHP开发的过程中使用调试模式,5.0默认情况下可以捕获到任何细微的错误并抛出异常,这样可以更好的获取错误提示和避免一些问题和隐患。

开发完成后,我们实际进行项目部署的时候,修改应用配置文件(application/config.php)中的app_debug配置参数:

// 关闭调试模式

'app_debug' =>  false,

为了安全考虑,避免泄露你的服务器WEB目录信息等资料,一定记得正式部署的时候关闭调试模式。

 │  ├─Core 核心基类库

if(!APP_DEBUG && is_file(RUNTIME_FILE)) {
    // 部署模式直接载入运行缓存
    require RUNTIME_FILE;
}else{//高度模式下加载框架下的Common/runtime.php文件;我们就模拟程序第一次运行,从下面开始进入
    // 系统目录定义
    defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/');
    // 加载运行时文件,载入系统运行时文件runtime.php并定义项目路径常量
    require THINK_PATH.'Common/runtime.php';
}

图片 2
图1

Conf 框架配置文件目录

控制器

我们找到index模块的Index控制器(文件位于application/index/controller/Index.php注意大小写),我们把Index控制器类的index方法修改为Hello,World!。

提示:


根据类的命名空间可以快速定位文件位置,在ThinkPHP5.0的规范里面,命名空间其实对应了文件的所在目录,app命名空间通常代表了文件的起始目录为application,而think命名空间则代表了文件的其实目录为thinkphp/library/think,后面的命名空间则表示从起始目录开始的子目录。

我们访问URL地址

http://tp5.com

就会看到Hello,World!的输出结果。

如果要继承一个公共的控制器类,可以使用:

可以为操作方法定义参数,例如:

当我们带name参数访问入口文件地址(例如

Hello,ThinkPHP!

控制器类可以包括多个操作方法,但如果你的操作方法是protected或者private类型的话,是无法直接通过URL访问到该操作的,也就是说只有public类型的操作才是可以通过URL访问的。

我们来验证下,把Index控制器类的方法修改为:

当我们访问如下URL地址的时候,前面两个是正常访问,后面两个则会显示异常。

http://tp5.com/index.php/index/index/hello

http://tp5.com/index.php/index/index/test

http://tp5.com/index.php/index/index/hello2

http://tp5.com/index.php/index/index/hello3

当我们访问hello2和hello3操作方法后的结果都会显示类似的异常信息:
图片 3

异常页面包含了详细的错误信息,是因为开启了调试模式,如果关闭调试模式的话,看到的默认信息如下:

图片 4

 │  ├─Driver 内置驱动

/*
 * 3、载入系统运行时文件runtime.php并定义项目路径常量
 * ThinkPHP/Common/runtime.php 系统运行时文件
 * ThinkPHP 运行时文件 编译后不再加
 */

1)在think目录下创建Index.php,内容如下:

ThinkPHP/Conf/convention.php  //惯例配置文件,系统默认配置小于项目配置

视图

现在我们在给控制器添加视图文件功能,我们在application/index目录下面创建一个view目录,然后添加模板文件view/index/hello.html,我们添加模板内容如下:

hello, {$name}!

要输出视图,必须在控制器方法中进行模板渲染输出操作,现在修改控制器类如下:

assign('name', $name);

        return $this->fetch();

    }

}

[ 新手须知 ]


这里使用了use来导入一个命名空间的类库,然后可以在当前文件中直接使用该别名而不需要使用完整的命名空间路径访问类库。也就说,如果没有使用

use thinkController;

就必须使用

class Index extends thinkController

这种完整命名空间方式。

在后面的内容中,如果我们直接调用系统的某个类的话,都会假设已经在类的开头使用use进行了别名导入。

注意,Index控制器类继承了thinkController类之后,我们可以直接使用封装好的assign和fetch方法进行模板变量赋值和渲染输出。

fetch方法中我们没有指定任何模板,所以按照系统默认的规则(视图目录/控制器/操作方法)输出了view/index/hello.html模板文件。

接下来,我们在浏览器访问

http://tp5.com/index.php/index/index/hello

输出:

hello,thinkphp!

 │  │  ├─Cache 内置缓存驱动

//从18——81行定义了程序中要用到的各种常量

<?php  define('APP_NAME' , 'Index');  define('APP_PATH' , './Index/');  define('RUNTIME_PATH' , APP_PATH . 'Runtime/');  define('APP_DEBUG' , true);   include './ThinkPHP/ThinkPHP.php'; //or require './ThinkPHP/ThinkPHP.php' ?>

ThinkPHP/Conf/debug.php //默认的调试模式配置文件

读取数据

在开始之前,我们首先在数据库demo中创建一个think_data数据表(这里以mysql数据库为例):

CREATE TABLE IF NOT EXISTS `think_data`(

    `id` int(8) unsigned NOT NULL AUTO_INCREMENT,

    `data` varchar(255) NOT NULL,

    PRIMARY KEY (`id`)

) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;



INSERT INTO `think_data`(`id`,`data`) VALUES

(1,'thinkphp'),

(2,'php'),

(3,'framework');

首先我们需要在应用的数据库配置文件application/database.php中添加数据库的连接信息如下:

return [

    // 数据库类型

    'type'        => 'mysql',

    // 服务器地址

    'hostname'    => '127.0.0.1',

    // 数据库名

    'database'    => 'demo',

    // 数据库用户名

    'username'    => 'root',

    // 数据库密码

    'password'    => '',

    // 数据库连接端口

    'hostport'    => '',

    // 数据库连接参数

    'params'      => [],

    // 数据库编码默认采用utf8

    'charset'     => 'utf8',

    // 数据库表前缀

    'prefix'      => 'think_',

    // 数据库调试模式

    'debug'       => true,

];

接下来,我们修改下控制器方法,添加读取数据的代码:

find();

        $this->assign('result', $data);

        return $this->fetch();

    }

}

定义好控制器后,我们修改模板文件,添加数据输出标签如下:

{$result.id}--{$result.data}

模板标签的用法和Smarty类似,就是用于输出数据的字段,这里就表示输出think_data表的id和data字段的值。

我们访问会输出:

1--thinkphp

 │  │  ├─Db 内置数据库驱动

//#84行  为了方便导入第三方类库 设置Vendor目录到include_path
set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);//这一句将/ThinkPHP/Extend/Vendor/ 加入了include_path目录中

各行代码的说明如下:

 

总结

本章我们学习了如何安装ThinkPHP和框架的目录结构,如何创建项目的入口文件和开启调试模式,并通过一个Hello,Name例子说明了如何定义控制器和模板,以及如何读取数据库的数据并在模板渲染输出。

 │  │  ├─TagLib 内置标签驱动

//#87-114行 加载运行时所需要的文件 并负责自动目录生成
function load_runtime_file() {
//引入/ThinkPHP/Lib/Core/Think.class.php
//引入/ThinkPHP/Lib/Core/ThinkException.class.php,  // 异常处理类
//引入/ThinkPHP/Lib/Core/Behavior.class.php,
// 检查项目目录结构 如果不存在则自动创建   build_app_dir();check_runtime();

2:定义我们的应用名字,由于我们是创建一个前台部分,所以取名为Index;

Lang 框架系统语言目录

 │  │  └─Template 内置模板引擎驱动

}

3:定义我们在第2行创建的应用的存放路径,存放在当前路径下的Index文件夹下(系统会自动创建该文件夹);

 

 │  └─Template 内置模板引擎

//#118-130行 // 检查缓存目录(Runtime) 如果不存在则自动创建
function check_runtime() {
// 在load_runtime_file()中被引用
}

4:定义我们runtime文件夹的路径,在3.1.3版本中一定要定义runtime文件夹路径,不然系统会将该文件夹存放在该磁盘的顶级目录下;

Lib 系统核心基类库目录

 └─Tpl 系统模板目录

//#133-163行 //创建编译缓存
function build_runtime_cache($append='') {
//没仔细研究,是把程序中用到的代码都压入到~return.php缓存文件中
}

5:开启调试模式,在我们编写代码时开启此模式便于调试,在应用开发完成后可删除或者注释掉该句话;

ThinkPHP/Core/Think.class.php //入口文件(设置异常和错误处理机制、注册系统自动加载机制、预编译当前项目、加载框架惯例配置文件)

 

//#164-174 //// 编译系统行为扩展类库
function build_tags_cache() {
//编译系统行为扩展类库 compile($filename)此函数
}

(为什么要开启调试模式?当我们不调试模式时,当我们的应用完成时系统会生成runtime.php保存我们的运行流程,那么我们在调试代码之后就不会显示最新的结果,依然是旧的结果,所以我们需要开启调试模式)

ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类

注意,框架的公共入口文件ThinkPHP.php是不能直接执行的,该文件只能在项目入口文件中调用才能正常运行。

//117-224 // 创建项目目录结构
function build_app_dir(){
//创建项目目录结构
}

7:引入ThinkPHP核心文件,可以通过include或者require两种方式来引入。(include和require的区别就是使用include方式引入文件时,当系统遇到错误会直接调过错误继续运行,而require方式引入的文件遇到错误则会停止)

ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类

三、入口文件:

//227-230 // 创建测试Action
function build_first_action(){
// /ThinkPHP/Tpl/default_index.tpl模板
}

写完之后在浏览器下打开index.php就可以看到图2的结果:

ThinkPHP/Lib/Core/App.class.php,   // 应用程序类

默认入口:public/index.php(实际部署的时候public目录为你的应用对外访问目录)。

//#233 加载运行时所需文件
load_runtime_file();

图片 5
图2

ThinkPHP/Lib/Core/Action.class.php, // 控制器类

引入入口文件:

//#235 记录加载文件时间
G('loadTime');

同时,在来看看think文件夹下,发现系统自动生成了Index文件夹,如下图所示:

ThinkPHP/Lib/Core/View.class.php,  // 视图类

<?php

// 执行入口
Think::Start();

图片 6
图3

 

require ‘/ThinkPHP框架所在目录/ThinkPHP.php’;

/*
* 执行入口
* /ThinkPHP/Lib/Core/Think.class.php
* 程序的入口(设置异常和错误处理机制、注册系统自动加载机制、预编译当前项目、加载框架惯例配置文件)
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

Tpl 系统模板目录

?>

//#37-49 应用程序初始化
static public function Start() {
        // 设定错误和异常处理
        set_error_handler(array('Think','appError')); //将this->appError()注册为错误处理方法
        set_exception_handler(array('Think','appException')); //将$this->appException()注册为异常处理函数
        // 注册AUTOLOAD方法
        spl_autoload_register(array('Think', 'autoload'));//将$this->autoload()注册为__autoload()方法
        //[RUNTIME]
        Think::buildApp();         // 读取配置信息 预编译项目
        //[/RUNTIME]
        // 运行应用
        App::run();
        return ;
}


ThinkPHP/Tpl/default_index.tpl //测试模块的模板

访问路径:http://localhost/app/

//#61-124 读取配置信息 预编译项目
static private function buildApp() {
    // /ThinkPHP/Conf/convention.php 读取系统配置,读取项目配置 /项目/Conf/conf.php 合并配置 
    //加载语言包(可能是支持多语言的,目前没用到过)
    //加载模式系统行为定义(没看明白)
    //读取核心编译文件列表 (使用compile()函数,将所有核心类及函数、自定义类库压入到$compile变量中,等待编译~runtime.php)
    (
        ThinkPHP/Common/functions.php, // 标准模式函数库
        ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类
        ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类
        ThinkPHP/Lib/Core/App.class.php,   // 应用程序类
        ThinkPHP/Lib/Core/Action.class.php, // 控制器类
        ThinkPHP/Lib/Core/View.class.php,  // 视图类
    );
    // ThinkPHP/Common/common.php //加载项目公共文件(函数库)
    // 项目/Conf/alias.php 加载项目别名定义(项目自定义类库,用别名导入的方式引入的自定义类库)
    // 如果是调试模式,加载系统默认的配置文件ThinkPHP/Conf/debug.php的默认调试配置,如果项目自己定义了 项目/Conf/debug.php则读取项目调试配置
    // 最后如果是部署模式 使用build_runtime_cache($compile); 创建编译缓存,将$compile变量写入到项目/Runtime/~runtime.php文件中
    // 欧克至此该引入的文件全部引入完成,下面讲解控制器篇
    // 最后的最后我们来回顾一下我们加载了些什么东西到程序中来
    /*
    * 1、ThinkPHP/Common/functions.php, // 标准模式函数库
    * 2、ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类
    * 3、ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类
    * 4、ThinkPHP/Lib/Core/App.class.php,   // 应用程序类
    * 5、ThinkPHP/Lib/Core/Action.class.php, // 控制器类
3建立个人项目,ThinkPHP框架系统源码解析。    * 6、ThinkPHP/Lib/Core/View.class.php,  // 视图类
    * 7、ThinkPHP/Common/common.php //加载项目公共文件(函数库)
    * 8、项目/Conf/alias.php 加载项目别名定义(项目自定义类库,用别名导入的方式引入的自定义类库)
    * 9、ThinkPHP/Conf/debug.php的默认调试配置
    */
}

ThinkPHP/Tpl/dispatch_jump.tpl //页面提示的模板

自动生成项目目录,目录结构如下:

/*
* 加载了半天文件再在来真的了,正式进入程序运行 App::run();
* /ThinkPHP/lib/Core/App.class.php //应用程序类 执行应用过程管理
* 这里是整个程序的入口,我们要跳着读,首先跳入App::init();
* 最后一步跳入App::exec();
*/

ThinkPHP/Tpl/page_trace.tpl //页面Trace信息的模板

├─index.php     项目入口文件

// #148-164 运行应用实例 入口文件使用的快捷方法

ThinkPHP/Tpl/think_exception.tpl //系统错误信息的模板

 ├─Common 项目公共文件目录

    static public function run() {
        // 项目初始化标签
        tag('app_init');
        App::init();
        // 项目开始标签
        tag('app_begin');
        // Session初始化
        session(C('SESSION_OPTIONS'));
        G('initTime');
        //执行应用程序
        App::exec();
        // 项目结束标签
        tag('app_end');
        // 保存日志记录
        if(C('LOG_RECORD')) Log::save();
        return ;
    }

 

 ├─Conf 项目配置目录

// #36-76 应用程序初始化
 static public function init() {
    // load_ext_file(); 加载动态项目公共文件和配置
    // URL调度 Dispatcher::dispatch(); //进入Thinkphp/lib/Core/Dispatcher.class.php dispatch()方法,进行URL参数常量赋值
    // 如果有分组,include 分组配置与函数文件
    // 获取模板主题名称 $templateSet = C('DEFAULT_THEME'); 
    // 定义模板路径常量 define('THEME_PATH',   TMPL_PATH.$group.(THEME_NAME?THEME_NAME.'/':''));
    // 定义模板路径常量 define('APP_TMPL_PATH',__ROOT__.'/'.APP_NAME.(APP_NAME?'/':'').basename(TMPL_PATH).'/'.$group.(THEME_NAME?THEME_NAME.'/':''));
    // 定义模板文件的位置 C('TEMPLATE_NAME',THEME_PATH.MODULE_NAME.(defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/').ACTION_NAME.C('TMPL_TEMPLATE_SUFFIX'));
    // 定义模板文件缓存的位置 C('CACHE_PATH',CACHE_PATH.$group);
 }

Extend 框架扩展目录

 ├─Lang 项目语言目录

// #89-138 执行应用程序
 static public function exec() {
    // 安全检测,模块名必须是英文和数字组成,且英文为首
    // 检测通过 实例化 控制器 $module  =  A($group.MODULE_NAME);
    // 检测如果定义了__hack_module()扩展,则遇到当前模块不存在时会被接管,优先级大于空模块EmptyAction
    // 检测如果否定义空模块EmptyAction,则遇到不存在模块时调用EmptyAction模块
    // 检测前置后置方法(_before_、_after_) method_exists($module,'_before_'.$action),如果有则执行 call_user_func(array(&$module,'_before_'.$action));
    // 亮点在这里,至此URL解析完成了,跳转到 某某模块下的某某方法 执行当前操作 call_user_func(array(&$module,$action));
 }

 

 ├─Lib 项目类库目录

/*
* 接上一步,跳入App::init();后,我们发现需要跳入Dispatcher::dispatch();URL调度类中进行URL参数常量赋值,下面带你进入Disppatcher::dispatch方法中进行常量赋值
* ThinkPHP内置的Dispatcher类 只提供了一个公共的静态方法dispatch()方法作为接口,本方法将路由变量压入到常量中,供后面的action类使用
* 完成URL解析、路由和调度
* ThinkPHP/lib/Core/Dispatcher.class.php
* 完成后跳回到App::init(); 
*/

 

 │  ├─Action Action类库目录

//#36-153 URL映射到控制器
static public function dispatch() {
    //C('URL_MODEL');读取URL模式
    //将模块提取到MODULE_NAME全局变量中,将动作提取到ACTION_NAME全局变量中,将参数
    // $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));//解析path_info
    //$var[C('VAR_MODULE')]  =   array_shift($paths);//提取模块
    // $var[C('VAR_ACTION')]  =   array_shift($paths);//提取方法
    // $_GET   =  array_merge($var,$_GET);//重写$_GET
    // pathinfo常量 __INFO__
    // 控制器常量 define('MODULE_NAME',self::getModule(C('VAR_MODULE')));
    // 方法常量 define('ACTION_NAME',self::getAction(C('VAR_ACTION')));
    // URL常量 define('__SELF__',strip_tags($_SERVER['REQUEST_URI']));
    // 当前项目地址常量 define('__APP__',strip_tags(PHP_FILE));
    // 当前操作地址常量 define('__ACTION__',__URL__.$depr.ACTION_NAME);
    // $_REQUEST = array_merge($_POST,$_GET); $_REQUEST重写
}

 

 │  ├─Behavior 行为类库目录

//注:获取系统配置用C()方法,此方法写得很巧妙,建议大家看一下

 

 │  ├─Model 模型类库目录


 

 │  └─Widget Widget类库目录

 

 ├─Runtime 项目运行时目录

<?php

 │  ├─Cache 模板缓存目录

/*

 │  ├─Data 数据缓存目录

 * 1、用户访问网站URL地址 

 │  ├─Logs 日志文件目录

 * /test/Index.php 项目入口文件

 │  └─Temp 临时缓存目录

 */

 └─Tpl 项目模板目录

require ('../ThinkPHP/ThinkPHP.php');//引入框架文件

移动修改目录入口文件的路径:

 

 

 

<?php

/*

define(‘APP_NAME’,’app’);

 * 2、载入系统入口文件ThinkPHP.php 

define(‘APP_PATH’,’./app/’);

 * ThinkPHP/ThinkPHP.php框架入口文件

require ’/ThinkPHP框架所在目录/ThinkPHP.php’;

 * 判断系统常量,如果没有定义则自动生成

?>

 */

APP_NAME和APP_PATH分部用于定义项目名和项目目录,项目名通常就是指项目的目录名称。

$GLOBALS['_beginTime'] = microtime(TRUE); //记录运行时的时间

四、调试模式:

 

ThinkPHP的运行模式包括调试模式和部署模式,默认情况下是运行在部署模式下面。部署模式下面性能优先,并且尽可能少地抛出错误信息,调试模式则以除错方便优先,关闭任何缓存,而且尽可能多的抛出错误信息,所以对性能有一定的影响。

define('MEMORY_LIMIT_ON',function_exists('memory_get_usage'));//php中用echo memory_get_usage() 获取当前的内存消耗量 

开启调试模式(开发完后关闭):

 

<?php

if(MEMORY_LIMIT_ON) $GLOBALS['_startUseMems'] = memory_get_usage();//如果支持内存使用量函数则全局变量$GLOBALS['_startUseMems']等于内存使用量,这里相当于记录下内存初始使用的量

define(‘APP_DEBUG’,TRUE);//开启调试模式

 

require ‘/ThinkPHP框架所在目录/ThinkPHP.php’;

defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');//设置当前的项目路径

?>

 

关闭调试模式:

defined('RUNTIME_PATH') or define('RUNTIME_PATH',APP_PATH.'Runtime/');//设置runtime的路径

define(‘APP_DEBUG’,false);

 

 

defined('APP_DEBUG') or define('APP_DEBUG',false); // 是否调试模式,默认false

五、配置文件:

 

配置文件位于每个项目目录的Conf/config.php,采用定义格式为php返回数组的方式。

$runtime = defined('MODE_NAME')?'~'.strtolower(MODE_NAME).'_runtime.php':'~runtime.php';//如果设置了其它运行模式则~ruturn.php就变化为 ~模式ruturn.php,(例如,采用命令行模式运行),那么在入口文件中定义MODE_NAME如下define('MODE_NAME','cli');  那么这里的缓存文件就为~cliruturn.php

//项目配置文件

 

return array{

defined('RUNTIME_FILE') or define('RUNTIME_FILE',RUNTIME_PATH.$runtime);//设置~runtime.php的路径;

‘配置参数’ => ‘配置值’,

 

//更多配置参数

if(!APP_DEBUG && is_file(RUNTIME_FILE)) {

//...

    // 部署模式直接载入运行缓存

};

    require RUNTIME_FILE;

注意:

}else{//高度模式下加载框架下的Common/runtime.php文件;我们就模拟程序第一次运行,从下面开始进入

配置值可以支持包括字符串、数字、布尔值和数组在内的数据,通常我们建议配置参数均使用大写定义。如果有需要,我们还可以为项目定义其他的配置文件。

    // 系统目录定义

六、使用控制器:

    defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__).'/');

控制器类的命名规范:模块名 Action.class.php(模块名采用驼峰法并且首字母大写)系统的默认模块是Index,对应的控制器就是项目目录下面的Lib/Action/IndexAction.class.php,类名和文件名一致。默认操作是index的一个public方法。

    // 加载运行时文件,载入系统运行时文件runtime.php并定义项目路径常量

初次生成项目目录结构的时候,系统已经默认生成了一个默认控制器。

    require THINK_PATH.'Common/runtime.php';

示例代码:

}

class IndexAction extends Action {

 

Public function index(){

 

Echo ‘hello,world’;

/*

3建立个人项目,ThinkPHP框架系统源码解析。}

 * 3、载入系统运行时文件runtime.php并定义项目路径常量

}

 * ThinkPHP/Common/runtime.php 系统运行时文件

注意:

 * ThinkPHP 运行时文件 编译后不再加

控制器必须继承Action类,一个模块可以包括多个操作方法。如果你的操作方法是protected或者private类型的话,是无法直接通过URL访问到该操作的。

 */

 

 

七、URL请求

//从18——81行定义了程序中要用到的各种常量

入口文件是项目的单一入口,对项目的所有请求都定向到项目的入口文件,系统会从URL参数中解析当前请求的模块和操作,我们之前访问的URL地址是没有任何参数,因此系统会访问默认模块(Index)的默认操作(index),因此下面的访问和之前是等效的:

 

http://localhost/app/index.php/Index/index

//#84行  为了方便导入第三方类库 设置Vendor目录到include_path

这种URL模式就是系统默认的PATHINFO模式,不同的URL模式获取模块和操作的方法不同。

set_include_path(get_include_path() . PATH_SEPARATOR . VENDOR_PATH);//这一句将/ThinkPHP/Extend/Vendor/ 加入了include_path目录中

 

 

普通模式:也就是传统的GET传参方式来指定当前访问的模块和操作,例如:http://localhost/app/?m=module&a=action&var=value

//#87-114行 加载运行时所需要的文件 并负责自动目录生成

M参数表示模块

function load_runtime_file() {

A操作表示操作(模块和操作的URL参数名称是可以配置的),后面的表示其他GET参数。

//引入/ThinkPHP/Lib/Core/Think.class.php

PATHINFO模式:

//引入/ThinkPHP/Lib/Core/ThinkException.class.php,  // 异常处理类

是系统的默认URL模式,提供了最好的SEO支持,

//引入/ThinkPHP/Lib/Core/Behavior.class.php,

系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境。

// 检查项目目录结构 如果不存在则自动创建   build_app_dir();check_runtime();

对应上面的URL模式,PATHINFO模式下面的URL访问地址是:

 

http://localhost/app/index.php/module/action/var/value/

}

Module(第一参数)表示模块,

 

Action(第二参数)表示操作,

//#118-130行 // 检查缓存目录(Runtime) 如果不存在则自动创建

 

function check_runtime() {

可定制方式:例如通过下面的配置:

// 在load_runtime_file()中被引用

'URL_PATHINFO_DEPR'=>'-', // 更改PATHINFO参数分隔符

}

还可支持

 

http://localhost/app/index.php/module-action-var-value/

//#133-163行 //创建编译缓存

的URL访问。

function build_runtime_cache($append='') {

 

//没仔细研究,是把程序中用到的代码都压入到~return.php缓存文件中

REWRITE模式:

}

是在PATHINFO模式的基础上添加了重写规则的支持,可以去掉URL地址里面的入口文件index.php,但是需要额外配置WEB服务器的重写规则。

 

如果是Apache则需要在入口文件的同级添加.htaccess文件,内容如下:

//#164-174 //// 编译系统行为扩展类库

<IfModule mod_rewrite.c>

function build_tags_cache() {

RewriteEngine on

//编译系统行为扩展类库 compile($filename)此函数

RewriteCond %{REQUEST_FILENAME} !-d

}

REwriteRule ^(.*)$ index.php/$1 [QSA,PT,L]

 

</IfModule>

//117-224 // 创建项目目录结构

下面的URL地址访问了:

function build_app_dir(){

http://localhost/app/module/action/var/value/

//创建项目目录结构

 

}

兼容模式:

 

是用于不支持PATHINFO的特殊环境,URL地址是:

//227-230 // 创建测试Action

http://localhost/app/?s=/module/action/var/value/

function build_first_action(){

兼容模式配合Web服务器重写规则的定义,可以达到和REWRITE模式一样的URL效果。

// /ThinkPHP/Tpl/default_index.tpl模板

 

}

八、视图

 

ThinkPHP内置了一个编译型模板引擎,也支持原生的PHP模板,并且还提供了包括Smarty在内的模板引擎驱动。

//#233 加载运行时所需文件

和Smarty不同,ThinkPHP在渲染模板的时候如果不指定模板,则会采用系统默认的定位规则,其定义规范是TPL/模块名/操作名.html,所以,Index模块的index操作的默认模板文件位于项目目录下面的Tpl/Index/index.html。

load_runtime_file();

例如:

 

<html>

//#235 记录加载文件时间

<head>

G('loadTime');

<title>hello {$name}</title>

 

</head>

// 执行入口

<body>

Think::Start();

Hello,{$name}!

 

</body>

/*

</html>

* 执行入口

要输出视图,必须在控制器方法中进行模板渲染输出操作,例如:

* /ThinkPHP/Lib/Core/Think.class.php

Class IndexAction extends Action {

* 程序的入口(设置异常和错误处理机制、注册系统自动加载机制、预编译当前项目、加载框架惯例配置文件)

public function index(){

*/

$this->name = ‘thinkphp’;//进行模板变量赋值

 

$this->display();

//#37-49 应用程序初始化

}

static public function Start() {

}

        // 设定错误和异常处理

display方法中我们没有指定任何模板,所以按照系统默认的规则输出Index/index,html模板文件。

        set_error_handler(array('Think','appError')); //将this->appError()注册为错误处理方法

接下来,我们在浏览器中输入:http://localhost/app/

        set_exception_handler(array('Think','appException')); //将$this->appException()注册为异常处理函数

浏览器中会输出: hello,thinkPHP!

        // 注册AUTOLOAD方法

九、读取数据

        spl_autoload_register(array('Think', 'autoload'));//将$this->autoload()注册为__autoload()方法

在开始之前,首先需在数据库thinkphp中创建一个think_data数据表(以mysql数据库为例):

        //[RUNTIME]

建表:

        Think::buildApp();         // 读取配置信息 预编译项目

CREATE TABLE IF NOT EXISTS ‘think_data’(

        //[/RUNTIME]

‘id’ int(8) unsigned NOT NULL AUTO_INCREMENT,

        // 运行应用

‘data’ varchar(255) NOT NULL,

        App::run();

PRIMARY KEY (‘id’) //主键

        return ;

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

}

 

 

插入记录:

//#61-124 读取配置信息 预编译项目

INSERT INTO ‘think_data’(‘id’,’data’) VALUES

static private function buildApp() {

(1,’thinkphp’),

    // /ThinkPHP/Conf/convention.php 读取系统配置,读取项目配置 /项目/Conf/conf.php 合并配置 

(2,’php’),

    //加载语言包(可能是支持多语言的,目前没用到过)

(3,’framework’);

    //加载模式系统行为定义(没看明白)

 

    //读取核心编译文件列表 (使用compile()函数,将所有核心类及函数、自定义类库压入到$compile变量中,等待编译~runtime.php)

配置连接数据库相关信息:

    (

 

        ThinkPHP/Common/functions.php, // 标准模式函数库

//添加数据库配置信息

        ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类

‘DB_TYPE’     => ‘mysql’,        //数据库类型

        ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类

‘DB_HOST’     => ‘localhost’,   //服务器地址

        ThinkPHP/Lib/Core/App.class.php,   // 应用程序类

‘DB_NAME’     => ‘thinkphp’,   //数据名

        ThinkPHP/Lib/Core/Action.class.php, // 控制器类

‘DB_USER’     => ‘root’,   //用户名

        ThinkPHP/Lib/Core/View.class.php,  // 视图类

‘DB_PWD’      => ‘’,   //密码

    );

‘DB_PORT’     => 3306,   //端口

    // ThinkPHP/Common/common.php //加载项目公共文件(函数库)

‘DB_PREFIX’ => ‘think_’,   //数据表前缀

    // 项目/Conf/alias.php 加载项目别名定义(项目自定义类库,用别名导入的方式引入的自定义类库)

 

    // 如果是调试模式,加载系统默认的配置文件ThinkPHP/Conf/debug.php的默认调试配置,如果项目自己定义了 项目/Conf/debug.php则读取项目调试配置

或采用如下配置:

    // 最后如果是部署模式 使用build_runtime_cache($compile); 创建编译缓存,将$compile变量写入到项目/Runtime/~runtime.php文件中

 

    // 欧克至此该引入的文件全部引入完成,下面讲解控制器篇

‘DB_DSN’ => ‘mysql://root@localhost:3306/thinkphp’

    // 最后的最后我们来回顾一下我们加载了些什么东西到程序中来

 

    /*

注意:

    * 1、ThinkPHP/Common/functions.php, // 标准模式函数库

使用DB_DSN方式定义可以简化配置参数,DSN参数格式为:

    * 2、ThinkPHP/Lib/Core/Log.class.php,    // 日志处理类

数据库类型://用户名:密码@数据库地址:数据库端口/数据库名

    * 3、ThinkPHP/Lib/Core/Dispatcher.class.php, // URL调度类

 

    * 4、ThinkPHP/Lib/Core/App.class.php,   // 应用程序类

如果两种配置参数同时存在的话,DB_DSN配置参数优先。

    * 5、ThinkPHP/Lib/Core/Action.class.php, // 控制器类

 

    * 6、ThinkPHP/Lib/Core/View.class.php,  // 视图类

修改控制器方法进行添加读取数据:

    * 7、ThinkPHP/Common/common.php //加载项目公共文件(函数库)

Class IndexAction extends Action {

    * 8、项目/Conf/alias.php 加载项目别名定义(项目自定义类库,用别名导入的方式引入的自定义类库)

public function index(){

    * 9、ThinkPHP/Conf/debug.php的默认调试配置

 

    */

$Data = M(‘Data’); //实例化Data数据模型

}

$this -> data = $data -> select();

 

$this -> display();

/*

}

* 加载了半天文件再在来真的了,正式进入程序运行 App::run();

}

* /ThinkPHP/lib/Core/App.class.php //应用程序类 执行应用过程管理

这里用到了M函数,是ThinkPHP内置的实例化模型的方法,

* 这里是整个程序的入口,我们要跳着读,首先跳入App::init();

使用M方法实例化模型不需要创建对应的模型类。

* 最后一步跳入App::exec();

可理解为:

*/

M();是直接操作底层的Model类,而Model类具备基本的CURD操作方法。

 

M(‘Data’)实例化后,就可以对think_data数据表(think_是我们在项目配置文件中定义的数据表前缀)进行操作(包括CURD)了。

// #148-164 运行应用实例 入口文件使用的快捷方法

定义好控制器后,我们修改模板文件,添加数据输出标签如下:

 

<html>

    static public function run() {

<head>

        // 项目初始化标签

<title>Select Data</title>

        tag('app_init');

</head>

        App::init();

<body>

        // 项目开始标签

<volist name=”data” id=”vo”>

        tag('app_begin');

{$vo.id}--{$vo.data}<br/>

        // Session初始化

</volist>

        session(C('SESSION_OPTIONS'));

</body>

        G('initTime');

</html>

        //执行应用程序

Volist标签是内置模板引擎用于输出数据集的标签。

        App::exec();

{$vo.id}和{$vo.data}的用法和Smarty类似,就是用于输出数据的字段,这里就表示输出think_data表的id和data字段的值。

        // 项目结束标签

访问路径:

        tag('app_end');

显示输出:

        // 保存日志记录

    Thinkphp

        if(C('LOG_RECORD')) Log::save();

  php

        return ;

  Framework

    }

注意:

 

如果发生错误,请检查你是否开启了调试模式或者清空Runtime目录下面的缓存文件。

// #36-76 应用程序初始化

总结:

 static public function init() {

在本篇我们学习了ThinkPHP的目录结构、URL模式,如何创建项目的入口文件和开启调试模式,以及控制器、模板和模型的基础认识。

    // load_ext_file(); 加载动态项目公共文件和配置

    // URL调度 Dispatcher::dispatch(); //进入Thinkphp/lib/Core/Dispatcher.class.php dispatch()方法,进行URL参数常量赋值

    // 如果有分组,include 分组配置与函数文件

    // 获取模板主题名称 $templateSet = C('DEFAULT_THEME'); 

    // 定义模板路径常量 define('THEME_PATH',   TMPL_PATH.$group.(THEME_NAME?THEME_NAME.'/':''));

    // 定义模板路径常量 define('APP_TMPL_PATH',__ROOT__.'/'.APP_NAME.(APP_NAME?'/':'').basename(TMPL_PATH).'/'.$group.(THEME_NAME?THEME_NAME.'/':''));

    // 定义模板文件的位置 C('TEMPLATE_NAME',THEME_PATH.MODULE_NAME.(defined('GROUP_NAME')?C('TMPL_FILE_DEPR'):'/').ACTION_NAME.C('TMPL_TEMPLATE_SUFFIX'));

    // 定义模板文件缓存的位置 C('CACHE_PATH',CACHE_PATH.$group);

 }

 

// #89-138 执行应用程序

 static public function exec() {

    // 安全检测,模块名必须是英文和数字组成,且英文为首

    // 检测通过 实例化 控制器 $module  =  A($group.MODULE_NAME);

    // 检测如果定义了__hack_module()扩展,则遇到当前模块不存在时会被接管,优先级大于空模块EmptyAction

    // 检测如果否定义空模块EmptyAction,则遇到不存在模块时调用EmptyAction模块

    // 检测前置后置方法(_before_、_after_) method_exists($module,'_before_'.$action),如果有则执行 call_user_func(array(&$module,'_before_'.$action));

    // 亮点在这里,至此URL解析完成了,跳转到 某某模块下的某某方法 执行当前操作 call_user_func(array(&$module,$action));

 }

 

 

 

 

/*

* 接上一步,跳入App::init();后,我们发现需要跳入Dispatcher::dispatch();URL调度类中进行URL参数常量赋值,下面带你进入Disppatcher::dispatch方法中进行常量赋值

* ThinkPHP内置的Dispatcher类 只提供了一个公共的静态方法dispatch()方法作为接口,本方法将路由变量压入到常量中,供后面的action类使用

* 完成URL解析、路由和调度

* ThinkPHP/lib/Core/Dispatcher.class.php

* 完成后跳回到App::init(); 

*/

 

//#36-153 URL映射到控制器

static public function dispatch() {

    //C('URL_MODEL');读取URL模式

    //将模块提取到MODULE_NAME全局变量中,将动作提取到ACTION_NAME全局变量中,将参数

    // $paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));//解析path_info

    //$var[C('VAR_MODULE')]  =   array_shift($paths);//提取模块

    // $var[C('VAR_ACTION')]  =   array_shift($paths);//提取方法

    // $_GET   =  array_merge($var,$_GET);//重写$_GET

    // pathinfo常量 __INFO__

    // 控制器常量 define('MODULE_NAME',self::getModule(C('VAR_MODULE')));

    // 方法常量 define('ACTION_NAME',self::getAction(C('VAR_ACTION')));

    // URL常量 define('__SELF__',strip_tags($_SERVER['REQUEST_URI']));

    // 当前项目地址常量 define('__APP__',strip_tags(PHP_FILE));

    // 当前操作地址常量 define('__ACTION__',__URL__.$depr.ACTION_NAME);

    // $_REQUEST = array_merge($_POST,$_GET); $_REQUEST重写

}

 

//注:获取系统配置用C()方法,此方法写得很巧妙,建议大家看一下


本文由澳门新萄京发布于www.澳门新萄京赌场,转载请注明出处:3建立个人项目,ThinkPHP框架系统源码解析

上一篇:澳门新萄京1快速入门,thinkphp框架的相关总结 下一篇:没有了
猜你喜欢
热门排行
精彩图文