关闭

学习ThinkPHP开源框架整理(一)

标签: phpThinkPHPserver
5017人阅读 评论(0) 收藏 举报
分类:
一、概况
        thinkphp是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。thinkphpPHP的界面简洁实用,在保持   出色的性能和至简的代码同时,也注重易用性,并且拥有众多功能原创功能和特性。

二、对整个框架进行分步了解

    1、从基础 配置 架构 路由 控制器 模型 视图 模板 调试 缓存 安全方面全方位的去了解THinkPHP3.2.3

①、基础篇:
        ThinkPHP最新版本可以在官方网站(http://thinkphp.cn/down/framework.html)或者Github(https://github.com/liu21st/thinkphp/downloads)下载。
        把下载后的压缩文件解压到你的WEB目录(或者任何目录都可以),框架的目录结构为:
    1. ├─ThinkPHP.php     框架入口文件
    2. ├─Common 框架公共文件
    3. ├─Conf 框架配置文件
    4. ├─Extend 框架扩展目录
    5. ├─Lang 核心语言包目录
    6. ├─Lib 核心类库目录
    7. │  ├─Behavior 核心行为类库
    8. │  ├─Core 核心基类库
    9. │  ├─Driver 内置驱动
    10. │  │  ├─Cache 内置缓存驱动
    11. │  │  ├─Db 内置数据库驱动
    12. │  │  ├─TagLib 内置标签驱动
    13. │  │  └─Template 内置模板引擎驱动
    14. │  └─Template 内置模板引擎
    15. └─Tpl 系统模板目录

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

    在开始之前,你需要一个Web服务器和PHP运行环境,如果你暂时还没有,推荐使用集成开发环境WAMPServer(是一个集成了ApachePHPMySQL的开    发套件,而且支持多个PHP版本、MySQL版本和Apache版本的切换)来使用ThinkPHP进行本地开发和测试。
    接下来我们先在WEB根目录下面创建一个app子目录(这个app就是我们的项目名),然后在该目录下面创建一个index.php文件,添加一行简单的代码:
  1. <?php
  2. require '/ThinkPHP框架所在目录/ThinkPHP.php';
        
   在浏览器内运行:http://localhost/app/  就可以直接进入ThinkPHP的欢迎页面了,并且,框架为自动生成项目运行的基本目录,如缓存目录,模板目录等:
    1. ├─index.php     项目入口文件
    2. ├─Common 项目公共文件目录
    3. ├─Conf 项目配置目录
    4. ├─Lang 项目语言目录
    5. ├─Lib 项目类库目录
    6. │  ├─Action Action类库目录
    7. │  ├─Behavior 行为类库目录
    8. │  ├─Model 模型类库目录
    9. │  └─Widget Widget类库目录
    10. ├─Runtime 项目运行时目录
    11. │  ├─Cache 模板缓存目录
    12. │  ├─Data 数据缓存目录
    13. │  ├─Logs 日志文件目录
    14. │  └─Temp 临时缓存目录
    15. └─Tpl 项目模板目录

        入口文件内相关参数说明:
        
    1. <?php
    2. define('APP_NAME','app');   //定义项目的名称  APP_NAME
    3. define('APP_PATH','./app/');    //定义项目的入口目录 APP_PATH
    4. define('APP_DEBUG',TRUE); // 开启调试模式 开启调试模式后,调试模式则以除错方便优先,关闭任何缓存,而且尽可能多的抛出错误信息,所以对性能有一定的影响(开发阶段适合打开,方便开发者发现一些隐藏的bug
    5. require '/ThinkPHP框架所在目录/ThinkPHP.php';
        


    ②、配置
        每个项目都有一个独立的配置文件(位于项目目录的Conf/config.php),配置文件的定义格式均采用PHP返回数组的方式,例如:
        
    1. // 项目配置文件
    2. return array(
    3.     '配置参数'     => '配置值', 
    4.     // 更多配置参数
    5.     //...
    6. );
    注意:配置值可以支持包括字符串、数字、布尔值和数组在内的数据,通常我们建议配置参数均使用大写定义。如果有需要,我们还可以为项目定义其他的配置文件。
<?php
defined('THINK_PATH') or exit();
return array(
/* 项目设定 */
'APP_STATUS' => 'debug', // 应用调试模式状态 调试模式开启后有效 默认为debug 可扩展 并自动加载对应的配置文件
'APP_FILE_CASE' => true, // 是否检查文件的大小写 对Windows平台有效
'APP_AUTOLOAD_PATH' => '',// 自动加载机制的自动搜索路径,注意搜索顺序
'APP_TAGS_ON' => true, // 系统标签扩展开关
'APP_SUB_DOMAIN_DEPLOY' => false, // 是否开启子域名部署
'APP_SUB_DOMAIN_RULES' => array(), // 子域名部署规则
'APP_SUB_DOMAIN_DENY' => array(), // 子域名禁用列表
'APP_GROUP_LIST' => 'Home,System,User,Wap,Chat', // 项目分组设定,多个组之间用逗号分隔,例如'Home,Admin'
'ACTION_SUFFIX' => '', // 操作方法后缀

/* Cookie设置 */
'COOKIE_EXPIRE' => 0, // Coodie有效期
'COOKIE_DOMAIN' => '', // Cookie有效域名
'COOKIE_PATH' => '/', // Cookie路径
'COOKIE_PREFIX' => '', // Cookie前缀 避免冲突

/* 默认设定 */
'DEFAULT_M_LAYER' => 'Model', // 默认的模型层名称
'DEFAULT_C_LAYER' => 'Action', // 默认的控制器层名称
'DEFAULT_APP' => '@', // 默认项目名称,@表示当前项目
'DEFAULT_LANG' => 'zh-cn', // 默认语言
'DEFAULT_THEME' => '', // 默认模板主题名称
'DEFAULT_GROUP' => 'Home', // 默认分组
'DEFAULT_MODULE' => 'Index', // 默认模块名称
'DEFAULT_ACTION' => 'index', // 默认操作名称
'DEFAULT_CHARSET' => 'utf-8', // 默认输出编码
'DEFAULT_TIMEZONE' => 'PRC', // 默认时区
'DEFAULT_AJAX_RETURN' => 'JSON', // 默认AJAX 数据返回格式,可选JSON XML ...
'DEFAULT_FILTER' => 'htmlspecialchars', // 默认参数过滤方法 用于 $this->_get('变量名');$this->_post('变量名')...

/* 数据库设置 */
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => '', // 数据库名
'DB_USER' => 'root', // 用户名
'DB_PWD' => '', // 密码
'DB_PORT' => '', // 端口
'DB_PREFIX' => 'think_', // 数据库表前缀
'DB_FIELDTYPE_CHECK' => false, // 是否进行字段类型检查
'DB_FIELDS_CACHE' => true, // 启用字段缓存
'DB_CHARSET' => 'utf8', // 数据库编码默认采用utf8
'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'DB_RW_SEPARATE' => false, // 数据库读写是否分离 主从式有效
'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量
'DB_SLAVE_NO' => '', // 指定从服务器序号
'DB_SQL_BUILD_CACHE' => false, // 数据库查询的SQL创建缓存
'DB_SQL_BUILD_QUEUE' => 'file', // SQL缓存队列的缓存方式 支持 file xcacheapc
'DB_SQL_BUILD_LENGTH' => 20, // SQL缓存的队列长度
'DB_SQL_LOG' => false, // SQL执行日志记录

/* 数据缓存设置 */
'DATA_CACHE_TIME' => 0, // 数据缓存有效期 0表示永久缓存
'DATA_CACHE_COMPRESS' => false, // 数据缓存是否压缩缓存
'DATA_CACHE_CHECK' => false, // 数据缓存是否校验缓存
'DATA_CACHE_PREFIX' => '', // 缓存前缀
'DATA_CACHE_TYPE' => 'File', // 数据缓存类型,支持:File|Db|Apc|Memcache|Shmop|Sqlite|Xcache|Apachenote|Eaccelerator
'DATA_CACHE_PATH' => TEMP_PATH,// 缓存路径设置 (仅对File方式缓存有效)
'DATA_CACHE_SUBDIR' => false, // 使用子目录缓存 (自动根据缓存标识的哈希创建子目录)
'DATA_PATH_LEVEL' => 1, // 子目录缓存级别

/* 错误设置 */
'ERROR_MESSAGE' => '页面错误!请稍后再试~',//错误显示信息,非调试模式有效
'ERROR_PAGE' => '', // 错误定向页面
'SHOW_ERROR_MSG' => false, // 显示错误信息

/* 日志设置 */
'LOG_RECORD' => false, // 默认不记录日志
'LOG_TYPE' => 3, // 日志记录类型 0 系统 1 邮件 3 文件 4 SAPI 默认为文件方式
'LOG_DEST' => '', // 日志记录目标
'LOG_EXTRA' => '', // 日志记录额外信息
'LOG_LEVEL' => 'EMERG,ALERT,CRIT,ERR',// 允许记录的日志级别
'LOG_FILE_SIZE' => 2097152, // 日志文件大小限制
'LOG_EXCEPTION_RECORD' => false, // 是否记录异常信息日志

/* SESSION设置 */
'SESSION_AUTO_START' => true, // 是否自动开启Session
'SESSION_OPTIONS' => array(), // session 配置数组 支持type name id path expire domian 等参数
'SESSION_TYPE' => '', // session hander类型 默认无需设置 除非扩展了session hander驱动
'SESSION_PREFIX' => '', // session 前缀
//'VAR_SESSION_ID' => 'session_id', //sessionID的提交变量

/* 模板引擎设置 */
'TMPL_CONTENT_TYPE' => 'text/html', // 默认模板输出类型
'TMPL_ACTION_ERROR' => THINK_PATH.'tpl/dispatch_jump.tpl', // 默认错误跳转对应的模板文件
'TMPL_ACTION_SUCCESS' => THINK_PATH.'tpl/dispatch_jump.tpl', // 默认成功跳转对应的模板文件
'TMPL_EXCEPTION_FILE' => THINK_PATH.'tpl/think_exception.tpl',// 异常页面的模板文件
'TMPL_DETECT_THEME' => false, // 自动侦测模板主题
'TMPL_TEMPLATE_SUFFIX' => '.html', // 默认模板文件后缀
'TMPL_FILE_DEPR' => '/', //模板文件MODULE_NAMEACTION_NAME之间的分割符,只对项目分组部署有效

/* URL设置 */
'URL_CASE_INSENSITIVE' => false, // 默认false 表示URL区分大小写 true则表示不区分大小写
'URL_MODEL' => 0, // URL访问模式,可选参数0123,代表以下四种模式:
// 0 (普通模式); 1 (PATHINFO 模式); 2 (REWRITE 模式); 3 (兼容模式) 默认为PATHINFO 模式,提供最好的用户体验和SEO支持
'URL_PATHINFO_DEPR' => '/', // PATHINFO模式下,各参数之间的分割符号
'URL_PATHINFO_FETCH' => 'ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL', // 用于兼容判断PATH_INFO 参数的SERVER替代变量列表
'URL_HTML_SUFFIX' => '', // URL伪静态后缀设置
'URL_PARAMS_BIND' => true, // URL变量绑定到Action方法参数

/* 系统变量名称设置 */
'VAR_GROUP' => 'g', // 默认分组获取变量
'VAR_MODULE' => 'm', // 默认模块获取变量
'VAR_ACTION' => 'a', // 默认操作获取变量
'VAR_AJAX_SUBMIT' => 'ajax', // 默认的AJAX提交变量
'VAR_PATHINFO' => 's', // PATHINFO 兼容模式获取变量例如 ?s=/module/action/id/1 后面的参数取决于URL_PATHINFO_DEPR
'VAR_URL_PARAMS' => '_URL_', // PATHINFO URL参数变量
'VAR_TEMPLATE' => 't', // 默认模板切换变量
'VAR_FILTERS' => '', // 全局系统变量的默认过滤方法 多个用逗号分割

'OUTPUT_ENCODE' => true, // 页面压缩输出
'HTTP_CACHE_CONTROL' => 'private', // 网页缓存控制

);


    ③、控制器(Controller)

        命名:模块名+Controller

        PATHINFO模式:是系统的默认URL模式,提供了最好的SEO支持,系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境。

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

    http://localhost/app/index.php/module/action/var/value/
  //module为模块名称(控制器名称)、不带Controller
  //action为操作名称(控制器中的方法名称)、不带Model
  //var为参数名
  //value为参数值
  //var与value成对出现

        我的:

    http://localhost/app/index.php/Index/index
  调用IndexController下的index()方法  
  如果该方法不存在,将直接调用Tpl/Index/index.html页面

 



    ④、模型(Model)

    1、命名:模块名字+Model

    在ThinkPHP的模型里面,有几个关于数据表名称的属性定义,在对应的Model中声明为属性字段(或者叫成员变量):

   
属性 说明
tableName 不包含表前缀的数据表名称,一般情况下默认和模型名称相同,只有当你的表名和当前的模型类的名称不同的时候才需要定义。
trueTableName 包含前缀的数据表名称,也就是数据库中的实际表名,该名称无需设置,只有当上面的规则都不适用的情况或者特殊情况下才需要设置。
dbName 定义模型当前对应的数据库名称,只有当你当前的模型类对应的数据库名称和配置文件不同的时候才需要定义。

 

只要命名规范,ThinkPHP会根据Model名字找到你要调用的数据库表,当然,前提你得建立。

规则:

1)表名为tp_categories(tp_为表前缀,在配置文件中配置)

protected$tableName = 'categories';  

2)表名为top_depts,top_不是系统配置的表前缀,需要使用表的全名

protected$trueTableName = 'top_depts'; 

3)可设置数据库

protected$dbName = 'top';
    


⑤、路由
    要使用路由功能,前提是你的URL支持PATH_INFO(或者兼容URL模式也可以,采用普通URL模式的情况下不支持路由功能),并且在应用(或者模块)配置文件中开启路由:
  1. // 开启路由
  2. 'URL_ROUTER_ON' => true,

3.2的路由功能是针对模块设置的,所以URL中的模块名不能被路由,路由定义也通常是放在模块配置文件中。 3.2.3版本开始增加全局路由定义支持,可以在项目的公共配置文件中定义路由。

然后就是配置路由规则了,在模块的配置文件中使用URL_ROUTE_RULES参数进行配置,配置格式是一个数组,每个元素都代表一个路由规则,例如:

  1. 'URL_ROUTE_RULES'=>array(
  2. 'news/:year/:month/:day' => array('News/archive', 'status=1'),
  3. 'news/:id' => 'News/read',
  4. 'news/read/:id' => '/news/:1',
  5. ),

系统会按定义的顺序依次匹配路由规则,一旦匹配到的话,就会定位到路由定义中的控制器和操作方法去执行(可以传入其他的参数),并且后面的规则不会继续匹配。

            
路由规则的定义格式为: '路由表达式'=>'路由地址和传入参数'   如:‘new/:year/:month/:day' => array('News/archive','status = 1')

路由地址

路由地址(可以支持传入额外参数)表示前面的路由表达式需要路由到的地址(包括内部地址和外部地址),并且允许隐式传入URL里面没有的一些参数,这里允许使用字符串或者数组方式定义,特殊情况下还可以采用闭包函数定义路由功能,支持下面6种方式定义:

定义方式 定义格式
方式1:路由到内部地址(字符串) '[控制器/操作]?额外参数1=值1&额外参数2=值2...'
方式2:路由到内部地址(数组)参数采用字符串方式 array('[控制器/操作]','额外参数1=值1&额外参数2=值2...')
方式3:路由到内部地址(数组)参数采用数组方式 array('[控制器/操作]',array('额外参数1'=>'值1','额外参数2'=>'值2'...)[,路由参数])
方式4:路由到外部地址(字符串)301重定向 '外部地址'
方式5:路由到外部地址(数组)可以指定重定向代码 array('外部地址','重定向代码'[,路由参数])
方式6:闭包函数 function($name){ echo 'Hello,'.$name;}

扩展:什么是闭包函数呢?
    提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:
        $func = function() {

            }; //带结束符
 例一
//在函数里定义一个匿名函数,并且调用它
function printStr() {
    $func = function( $str ) {
        echo $str;
    };
    $func( 'some string' );
}

printStr();

 

//例二
//在函数中把匿名函数返回,并且调用它
function getPrintStrFunc() {
    $func = function( $str ) {
        echo $str;
    };
    return $func;
}

$printStrFunc = getPrintStrFunc();
$printStrFunc( 'some string' );

 


//例三
//把匿名函数当做参数传递,并且调用它
function callFunc( $func ) {
    $func( 'some string' );
}

$printStrFunc = function( $str ) {
    echo $str;
};
callFunc( $printStrFunc );

//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉
callFunc( function( $str ) {
    echo $str;
} );

连接闭包和外界变量的关键字:USE
闭包可以保存所在代码块上下文的一些变量和值。PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。


public function index(){
function getMoney() {
$rmb = 1;
$dollar = 6;
$func = function() use ( $dollar , $rmb) {//可以输出16 利用关键字use调用外部变量
echo $rmb;
echo $dollar;//闭包不可以使用外部变量,若想使用可以使用use关键字
};
$func();
}

getMoney();

//输出:
//1
//报错,找不到dorllar}
public function index(){
function getMoney() {
$rmb = 1;
$dollar = 6;
$func = function() use ( $dollar , &$rmb) {
$rmb = 23;//闭包内修改变量值
echo $rmb;
echo $dollar;//闭包不可以使用外部变量,若想使用可以使用use关键字
};

$func();
echo $rmb; //输出后结构仍然是1 说明use所引用的只是变量的一个副本而已,并不能直接改变变量的值,若想改变变量的值在变量前加一个 & 符号就可以了 输出结果23
}

getMoney();

//原来use所引用的也只不过是变量的一个副本而已。但是我想要完全引用变量,而不是复制。

}
/*
* 总结
* PHP闭包的特性并没有太大惊喜,其实用CLASS就可以实现类似甚至强大得多的功能,
* 更不能和js的闭包相提并论,只能期待PHP以后对闭包支持的改进。不过匿名函数还是挺有用的,
* 比如在使用preg_replace_callback等之类的函数可以不用在外部声明回调函数了。
* */

3.2.3版本开始支持全局路由定义,如果你定义的是全局路由,那么路由地址的定义格式中需要增加模块名,例如:

  1. 'blog/:id'=>'Home/blog/read' // 表示路由到Home模块的blog控制器的read操作方法

如果路由地址以“/”或者“http”开头则会认为是一个重定向地址或者外部地址,例如:

  1. 'blog/:id'=>'/blog/read/id/:1'

  1. 'blog/:id'=>'blog/read'

虽然都是路由到同一个地址,但是前者采用的是301重定向的方式路由跳转,这种方式的好处是URL可以比较随意(包括可以在URL里面传入更多的非标准格式的参数),而后者只是支持模块和操作地址。

举个例子,如果我们希望 avatar/123 重定向到 /member/avatar/id/123_small 的话,只能使用:

  1. 'avatar/:id'=>'/member/avatar/id/:1_small'

路由地址采用重定向地址的话,如果要引用动态变量,也是采用 :1、:2 的方式。

采用重定向到外部地址通常对网站改版后的URL迁移过程非常有用,例如:

  1. 'blog/:id'=>'http://blog.thinkphp.cn/read/:1'

表示当前网站(可能是http://thinkphp.cn)的 blog/123 地址会直接重定向到 http://blog.thinkphp.cn/read/123

默认情况下,外部地址的重定向采用301重定向,如果希望采用其它的,可以使用:

  1. 'blog/:id'=>array('http://blog.thinkphp.cn/read/:1',302);

在路由跳转的时候支持额外传入参数对(额外参数指的是不在URL里面的参数,隐式传入需要的操作中,有时候能够起到一定的安全防护作用,后面我们会提到),支持 额外参数1=值1&额外参数2=值2 或者 array('额外参数1'=>'值1','额外参数2'=>'值2'...) 这样的写法,可以参考不同的定义方式选择。例如:

  1. 'blog/:id'=>'blog/read?status=1&app_id=5',
  2. 'blog/:id'=>array('blog/read?status=1&app_id=5'),
  3. 'blog/:id'=>array('blog/read','status=1&app_id=5'),
  4. 'blog/:id'=>array('blog/read',array('status'=>1,'app_id'=>5)),

上面的路由规则定义中额外参数的传值方式都是等效的。statusapp_id参数都是URL里面不存在的,属于隐式传值,当然并不一定需要用到,只是在需要的时候可以使用。

路由参数

当路由地址采用数组方式定义的时候,还可以传入额外的路由参数。

这些参数的作用是限制前面定义的路由规则的生效条件。

限制URL后缀

例如:

  1. 'blog/:id'=>array('blog/read','status=1&app_id=5',array('ext'=>'html')),

就可以限制html后缀访问该路由规则才能生效。

限制请求类型

例如:

  1. 'blog/:id'=>array('blog/read','status=1&app_id=5',array('method'=>'get')),

就限制了只有GET请求该路由规则才能生效。

自定义检测

支持自定义检测,例如: 例如:

  1. 'blog/:id'=>array('blog/read','status=1&app_id=5',array('callback'=>'checkFun')),

就可以自定义checkFun函数来检测是否生效,如果函数返回false则表示不生效。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:79478次
    • 积分:1218
    • 等级:
    • 排名:千里之外
    • 原创:31篇
    • 转载:4篇
    • 译文:0篇
    • 评论:12条
    最新评论