ThinkPHP的入门学习-目录结构及基础知识
一、系统目录(ThinkPHP框架目录)
ThinkPHP.php 框架的公共入口文件
Common 包含框架的一些公共文件、系统定义、系统函数和惯例配置等
Lang 系统语言文件
Lib 系统基类库目录
Tpl 系统模板目录
Mode 框架模式扩展目录
Vendor 第三方类库目录
二、应用目录(项目目录)
index.php 项目入口文件(可以使用其他名称或者放置于其他位置)
Common 项目公共文件目录,一般放置项目的公共函数
Conf 项目配置目录,所有的配置文件都放在这里。
Lang 项目语言包目录(可选)
Lib 项目类库目录,通常包括Action和Model子目录
Tpl 项目模板目录,支持模板主题
Runtime 项目运行时目录,包括Cache(模板缓存)、Temp(数据缓存)、Data(数据目录)和Logs(日志文件)子目录
上面的只是默认方式,项目下面的目录名称和结构是可以重新定义的。其实项目目录并不需要开发人员手动创建,只需要定义好项目的入口文件之后,系统会在第一次执行的时候自动生成项目必须的所有目录结构(前提是项目目录具有可写权限,这点在Linux环境下面需要注意)。
可以看出新版的目录结构更加便于部署和配置,因为只有Runtime目录才是需要具备可写权限的,在Linux环境下面可以更加快速的部署和配置目录权限。
三、部署目录
当我们实际部署网站的时候,目录结构往往由于项目的复杂而变得复杂。我们推荐的部署目录结构如下:
ThinkPHP 系统目录(下面的目录结构同上面的系统目录)
Home 项目目录(下面的目录结构同上面的应用目录)
Admin后台管理项目目录
…… 更多的项目目录
index.php 网站的入口文件
admin.php 网站的后台入口文件
如果采用分组模块的话 可以简化为一个项目目录
ThinkPHP 系统目录(下面的目录结构同上面的系统目录)
App 项目目录
Public 网站公共目录
index.php 网站的入口文件
项目的模板文件还是放到项目的Tpl目录下面,只是将外部调用的资源文件,包括图片 JS 和CSS统一放到网站的公共目录Public下面,分Images、Js和Css子目录存放,如果有可能的话,甚至也可以把这些资源文件单独放一个外部的服务器远程调用,并进行优化。
这样部署的好处是系统目录和项目目录可以放到非WEB访问目录下面,网站目录下面可以只需要放置Public公共目录和index.php入口文件(如果是多个项目的话,每个项目的入口文件都需要放到WEB目录下面),从而提高网站的安全性。
四、入口文件
ThinkPHP采用单一入口模式进行项目部署和访问,无论完成什么功能,一个项目只有一个统一(但不一定是唯一)的入口。并且所有的项目的入口文件是类似的,入口文件主要完成的作用是:
路径定义 项目名称定义(可选)
额外参数定义(可选)
载入框架入口文件(必须)
实例化一个App应用(必须)
下面是一个标准的入口文件的写法:
<?php
// 定义ThinkPHP框架路径(相对于入口文件)
define('THINK_PATH', '../ThinkPHP');
//定义项目名称和路径
define('APP_NAME', 'Myapp');
define('APP_PATH', '.');
// 加载框架入口文件
require(THINK_PATH."/ThinkPHP.php");
//实例化一个网站应用实例
App::run();
?>
运行入口文件后,就会在自己定义的项目目录下生成相应的目录结构文件
五、项目编译原理和文件说明
ThinkPHP 正式版本开始引入了新的项目编译机制,所谓的项目编译机制是指系统第一次运行的时候会自动生成核心缓存文件~runtime.php和项目编译缓存文件~app.php,这些编译缓存文件把核心和项目必须的文件打包到一个文件中,并且去掉所有空白和注释代码,因为存在一个预编译的过程,所以还会进行一些相关的目录检测,对于不存在的目录可以自动生成,这个自动生成机制后面还会提到。当第二次执行的时候就会直接载入编译过的缓存文件,从而省去很多IO开销,加快执行速度。项目编译机制对运行没有任何影响,预编译操作和其他的目录检测机制只会执行一次,因此无论在预编译过程中做了多少复杂的操作,对后面的执行没有任何效率的缺失。
编译缓存文件,默认是自动生成在项目目录下面的Runtime目录下面。如果希望自己设置目录,可以在入口文件里面设置RUNTIME_PATH进行更改,例如
define('RUNTIME_PATH','./MyApp/temp/');
注意在Linux环境下面需要对RUNTIME_PATH目录设置可写权限。
核心编译缓存文件~runtime.php包含的文件由系统的core.php文件决定,如果是采用了模式扩展的话,就由模式扩展入口文件决定。默认的核心模式下面包含了下面的一些文件:系统定义文件defines.php、系统函数库functions.php、系统基类Think、异常基类ThinkException、日志类 Log、应用类 App、控制器基类 Action、视图类 View。
其他类库可以在操作方法中使用系统导入机制或者自动加载机制完成加载。
项目编译缓存文件~app.php 通常包含了下面的一些文件:项目配置文件(由惯例配置、项目配置合并而成)、项目公共函数文件common.php。每个项目还可以单独添加自己的项目编译文件列表,只需要在项目配置目录下面定义app.php文件,返回需要额外添加到项目编译缓存的文件列表数组即可。
注意在调试模式下面不会生成项目编译缓存,但是依然会生成核心缓存。如果不希望生成核心缓存文件的话,可以在项目入口文件里面设置NO_CACHE_RUNTIME,例如:
define('NO_CACHE_RUNTIME',True);
以及设置对编译缓存的内容是否进行去空白和注释,例如:
define('STRIP_RUNTIME_SPACE',false);
则生成的编译缓存文件是没有经过去注释和空白的,仅仅是把文件合并到一起,这样的好处是便于调试的错误定位,建议部署模式的时候把上面的设置为True或者删除该定义。
六、 URL的访问解析
ThinkPHP框架基于模块和操作的方式进行访问,由于ThinkPHP框架的应用采用单一入口文件来执行,因此网站的所有的模块和操作都通过URL的参数来访问和执行。这样一来,传统方式的文件入口访问会变成由URL的参数来统一解析和调度。
ThinkPHP强大的URL解析、调度以及路由功能为这个功能实现提供了有力的保证,并且可以在绝大多数的服务器环境里面部署成功。
ThinkPHP支持的URL模式包括普通模式、PATHINFO模式、REWRITE模式和兼容模式,并且都提供路由支持。默认为PATHINFO 模式,提供最好的用户体验和搜索引擎友好支持。
例如普通模式下面的URL为:
http://localhost/appName/index.php?m=moduleName&a=actionName&id=1
如果使用PATHINFO模式的话,URL成为:
http://localhost/appName/index.php/moduleName/actionName/id/1/
PATHINFO模式对以往的编程方式没有影响,GET 和POST方式传值依然有效,因为系统会对PATHINFO 方式自动处理,例如上面URL地址中的id的值可以通过 $_GET['id'] 的方式正常获取到。
如果使用REWRITE模式,通过配置URL可以成为:
http://localhost/appName/moduleName/actionName/id/1/
例如上面生成的myApp项目如果我们通过下面的URL访问:
http://localhost/myApp/
其实是定位到myApp项目的Index模块的index操作,因为系统在没有指定模块和操作的时候,会执行默认的模块和操作,这个在ThinkPHP的惯例配置里面是Index模块和index操作。因此下面的URL和上面的结果是相同的:
http://localhost/myApp/index.php/Index/index/
通过项目配置参数,我们可以改变这个默认配置。
系统还支持分组模式和URL路由的功能,这些都能够带来URL的不同体验。
七、控制器模块操作类
ThinkPHP的控制器就是模块类,通常位于项目的LibAction目录下面。类名就是模块名加上Action后缀,例如IndexAction类就表示了Index模块。控制器类必须继承系统的Action基础类,这样才能确保使用Action类内置的方法。而index操作其实就是IndexAction类的一个公共方法,所以我们在浏览器里面输入URL:
http://localhost/myApp/index.php/Index/index/
其实就是执行了IndexAction类的index(公共)方法。
每个模块的操作并非一定需要有定义操作方法,如果我们只是希望输出一个模板,既没有变量也没有任何的业务逻辑,那么只需要按照规则定义好操作对应的模板文件即可,而不需要定义操作方法。例如,我们在IndexAction中如果没有定义help方法,但是存在对应的Index/help.html 模板文件,那么下面的URL访问依然可以正常运作:
http://localhost/myApp/index.php/Index/help/
因为系统找不到IndexAction类的help方法,会自动定位到Index模块的模板目录中查找help.html模板文件,然后直接渲染输出。
控制器中还设计了模块分组、空操作、空模块、前置和后置操作、操作链等功能,后面会有详细的描述。
八、模型类
在ThinkPHP中基础的模型类就是Model类,该类完成了基本的CURD、ActiveRecord模式、连贯操作和统计查询,一些高级特性被封装到另外的模型类中,例如AdvModel高级模型类完成了一些包括文本字段、只读字段、序列化字段、乐观锁、多数据库连接等模型的高级特性,ViewModel视图模型类完成了模型的视图操作,RelationModel关联模型类完成了模型的关联操作。
基础模型类Model的设计非常灵活,甚至可以无需进行任何模型定义,就可以进行相关数据表的ORM和CURD操作,只有在需要封装单独的业务逻辑的时候,模型类才是必须被定义的。
新版实现了动态模型的设计,可以从基础模型类切换到其他模型类进行方法操作而不会丢失现有的数据属性。这是一个真正的按需加载的思想,而不再是必须要事先继承需要操作的模型类。
九、数据库抽象层
ThinkPHP内置了抽象数据库访问层,把不同的数据库操作封装起来,而使用了统一的操作接口。我们只需要使用公共的Db类进行操作,而无需针对不同的数据库写不同的代码和底层实现,Db类会自动调用相应的数据库适配器来处理。目前支持Mysql、MsSQL、PgSQL、Sqlite、Oracle、Ibase以及PDO等多种数据库和连接。
数据库抽象层也支持分布式数据库的连接,包括对等和主从方式两种的支持,而且也支持多数据库连接和切换,为企业级应用保驾护航。
十、视图的解析
ThinkPHP的视图主要由View视图类和模板文件构成。视图类负责Action控制器类和模板文件之间沟通,Action类把数据通过View类传递到模板文件,而模板文件把接收到的数据转换成相应的数据格式显示。在特殊的情况下面,视图类会缓存模板文件的输出结果,这个时候缓存文件也纳入了视图层的概念之中了。
如果模板文件使用了某些模板引擎进行标签定义,而不是使用原生的PHP语法,那么在模板输出的过程中还需要引入模板解析,如果是编译型的模板引擎例如ThinkPHP内置的模板引擎和Smarty之类的,那么模板文件会有一个编译的过程,通常编译后的模板文件会生成一个编译后的模板缓存文件,第二次输出模板文件的时候就是直接输出编译后的模板缓存。如果是解释型的模板引擎,就会在每次输出模板的过程中进行解析操作。
无论如何,视图应该仅仅是进行数据的输出显示,通常在视图渲染过程是不会改变数据本身的,而只是进行格式化输出和显示。
十一、ThinkPHP中使用的模版引擎
ThinkPHP内置了一个基于XML的性能卓越的模板引擎 ThinkTemplate,这是一个专门为ThinkPHP服务的内置模板引擎,无论在功能或是性能还有易用性方面都比Smarty优秀。ThinkTemplate是一个使用了XML标签库技术的编译型模板引擎,使用了动态编译和缓存技术,支持两种类型的模板标签,支持PHP原生代码和模板标签的混合使用。而且支持自定义标签库,在基于内置模板引擎的基础上,扩展更多更强大更适合自己项目所使用的模板标签,任何想达到的功能皆有可能。