本章对于新手来说很重要,能基本理解本章的所有知识,对于后面的学习很有帮助。俗话说“基础不牢,地动山摇”。
## 目录结构
下载**ThinkPHP3.2.3**完整版后,解压到www目录。我们可以看到以下目录结构
├── Application
├── Public
├── README.md
├── ThinkPHP
│ ├── Common
│ ├── Conf
│ ├── LICENSE.txt
│ ├── Lang
│ ├── Library
│ │ ├── Behavior
│ │ ├── Org
│ │ ├── Think
│ │ └── Vendor
│ ├── Mode
│ │ ├── Api
│ │ ├── Sae
│ │ ├── api.php
│ │ ├── common.php
│ │ └── sae.php
│ ├── ThinkPHP.php
│ ├── Tpl
│ └── logo.png
├── composer.json
└── index.php
一个应用的目录是这样的:
www WEB部署目录(或者子目录)
├─index.php 入口文件
├─composer.json composer 依赖关系文件
├─README.md README文件
├─Application 应用目录
├─Public 资源文件目录
└─ThinkPHP 框架目录
ThinkPHP框架目录结构如下:
├─ThinkPHP 框架系统目录(可以部署在非web目录下面)
│ ├─Common 核心公共函数目录
│ ├─Conf 核心配置目录
│ ├─Lang 核心语言包目录
│ ├─Library 框架类库目录
│ │ ├─Think 核心Think类库包目录
│ │ ├─Behavior 行为类库目录
│ │ ├─Org Org类库包目录
│ │ ├─Vendor 第三方类库目录
│ │ ├─ ... 更多类库目录 比如**onethink**中的OT
│ ├─Mode 框架应用模式目录
│ ├─Tpl 系统模板目录
│ ├─LICENSE.txt 框架授权协议文件
│ ├─logo.png 框架LOGO文件
│ ├─README.txt 框架README文件
│ └─index.php 框架入口文件
当然应用目录不一定是Application,也可以是app,或者是入口文件所在目录。看一下示列代码中的startup:
examples
└── startup
├── Common 公共函数库
├── Home 应用目录
├── Runtime
└── index.php
└─ThinkPHP
这是因为我将startup里的入口文件index.php中的常量 **APP\_PATH** 定义为了当前目录:
`define('APP_PATH','./');`
`require '../../ThinkPHP/ThinkPHP.php';`
startup中Common、Home、Runtime这几个目录都是自动生成的,我只是定义了下入口文件。这也印证了官方手册里的话:
> README.md文件仅用于说明,实际部署的时候可以删除。
> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。 Application目录默认是空的,但是第一次访问入口文件会自动生成,参考后面的入口文件部分。
目录结构还要注意安全
> 在实际部署应用的时候,我们建议除了应用入口文件和Public资源目录外,其他文件都放到非WEB目录下面,具有更好的安全性。
> 实际上通过修改一些常量,可以将ThinkPHP框架目录和应用目录的结构修改的面目全非,这样别人拿到源码,第一眼认不出来ThinkPHP,伪装的目的也就达到了。
## 什么是控制器,如何建立
稍微懂点PHP的童鞋都知道M(模型)V(视图)C(控制器)。
控制器是我们处理响应的第二层,在其中根据用户过来的url,去进行业务数据调度和决定视图呈现的场所。
它物理上来说是一个类文件。
首先,我们找到startup下的默认控制器 就是 `examples/startup/Home/Controller/IndexController.class.php`文件。
**IndexController ** 是控制器类名,由 **控制器名(驼峰法,首字母大写)**的Index + Controller组成、
控制器文件的命名方式是:类名+class.php(类文件后缀)
我们访问 域名/[目录名(如果示列目录Apache配置了域名的话,此处不需要,localhost域名需要带上路径目录名如yang\_book_)]/examples/startup时的效果如下:
![起步](https://box.kancloud.cn/2016-04-07_5705df509a06b.png)
后面我讲的演示url路径会自动省略`.../examples/` 直接startup等目录开头,你们使用时要能自动转换一下访问路径。
**$this-\>show()** 我们后面基础知识部分的控制器章节会讲到。
我们看下控制器类,IndexController控制器类的开头是命名空间定义:
`namespace Home\Controller;`
这是系统的规范要求,表示当前类是Home模块下的控制器类,命名空间和实际的控制器文件所在的路径是一致的,也就是说:Home\Controller\IndexController类 对应的控制器文件位于应用目录下面的 Home/Controller/IndexController.class.php,如果你改变了当前的模块名,那么这个控制器类的命名空间也需要随之修改。
> 注意:命名空间定义必须写在所有的PHP代码之前声明,否则会出错
`use Think\Controller;`
表示引入 ThinkController 命名空间便于直接使用。 所以,
`use Think\Controller;`
`class IndexController extends Controller`
等同于使用:
`class IndexController extends \Think\Controller`
对于**3.1**的用户而言,如果你习惯了使用**Action**定义控制器的话,可以这样定义:
`namespace Home\Action;`
`use Think\Action;`
`class IndexAction extends Action{`
`}`
然后,在配置文件中,设置:
`'DEFAULT_C_LAYER'=>'Action'`
上面的设置方式通常可以用于原有3.1项目的升级。
### 配置文件在哪儿?如何设置
首先我们知道ThinkPHP很灵活,这归功于他提供了很多配置项,供大家重新配置。
配置文件分应用配置和框架配置。
应用配置又分公共配置和模块配置:
- startup/Common/Conf/config.php 公共配置
- startup/Home/Conf/config.php 模块配置
框架配置位于 /ThinkPHP/conf 下
默认有两个 convention.php和debug.php 我们一般称为惯例配置和调试配置。
当然还有其他配置项,因此有下面的一个优先级大家要了解下:
惯例配置-\>应用配置-\>模式配置-\>调试配置-\>状态配置-\>模块配置-\>扩展配置-\>动态配置
设置配置的方法有两种,一种是静态设置,一种是动态设置。
静态设置指的是在公共配置文件中写入框架配置中存在的键名(不存在的是自定义配置),覆盖框架默认配置。 这样的好处是,写一处,全局被影响。
动态设置指的是在代码中,通常是控制器和模型中,用C('键名','值')的方式进行临时性修改,影响范围小,只会在一次请求期间经过的代码中起作用。
## 如何开启调试模式
首先,调试模式只的是在开发阶段应用对应的框架模式。该模式下和正式部署环境的时候有一些区别:
- 不会在Runtime目录下面生成**common~runtime.php**文件(应用编译缓存文件)。
- 会自动加载框架的调试配置文件(位于`ThinkPHP/Conf/debug.php`)和应用调试配置文件(位于`Application/Common/Conf/debug.php`)
- 异常时显示具体的错误信息,如果在部署模式下面,你可能看到的是一个简单的提示文字,例如:
![2015-04-17/5530bcf7dafab](http://box.kancloud.cn/2015-04-17_5530bcf7dafab.png)
- 记录日志,部署模式不记录日志,且**SQL**级别日志只在调试模式时记录。
- 在部署模式下面,页面Trace显示的调试信息没有调试模式完整,通常我们建议页面Trace配合调试模式一起使用。
- Mongo数据库驱动由于接口的特殊性,不存在执行SQL的概念,因此SQL日志记录功能是额外封装实现的,所以出于性能考虑,只有在开启调试模式的时候才支持使用getLastSql方法获取最后执行的SQL记录。
- 开启错误信息显示,默认是关闭的。
鉴于以上几点,我们应该在开发的时候尽量开启调试模式,部署时关闭调试模式。
> 系统的默认情况下,调试模式是开启错误信息显示的,部署模式则关闭错误信息显示。
开启的方法很简单,入口文件 index.php 添加一行:
~~~
define('APP_DEBUG', 1);
~~~
调试模式开启的相关配置,进阶知识里会讲到。
## 如何使用模板标签
模板标签是TP模板的重要组成部分,有了它,我们才能摆脱html+PHP混编时那种混乱的\<?php ?\> 使我们的模板看上去简洁、优雅。
变量输出使用普通标签就足够了,但是要完成其他的控制、循环和判断功能,就需要借助模板引擎的标签库功能了,系统内置标签库的所有标签无需引入标签库即可直接使用。
标签和HTML标签一样 分为 闭合标签和不闭合标签。比如 :
- `<assign name="var" value="123" />`
- `<volist name="list" id="vo">`
`{$vo.id}:{$vo.name}<br/>`
`</volist>`
标签的使用一般都是 **<标签名 属性参数="">包裹内容</标签名>** 或者**<标签名 属性参数="" />**
`<else/>` 标签不能单独使用,必须在比较标签如 eq、if中间使用。
访问 **startup/Index/tags** ,会见到以下输出:
![2015-04-17/5530bd63b4a1d](http://box.kancloud.cn/2015-04-17_5530bd63b4a1d.png)
我们先看一下Index控制器下tags方法的内容:
public function tags()
$this->assign('age',10);
$this->assign('likes', array('爸爸', '妈妈', '小红'));
$this->assign('money', 0);
$this->display();
}
我们看一下`/Home/view/Index/tags.html`的内容。
~~~
<p>我今年{$age}岁了。</p>
<p>我是一个<eq name="age" value="18">大人<else/>小孩</eq>。</p>
<volist name="likes" id="like">
<p>我喜欢{$like}。</p>
</volist>
<p><empty name="money">我没有一分钱,很穷。</empty></p>
<include file="Index/award" />
~~~
大概常用的标签都用到了,比较标签、include、循环标签。
## 项目函数文件在哪儿,如何定义自己的函数
目录结构已经讲了公用函数目录。项目函数文件路径是`/Home/Common/function.php` 和Common公共目录一样也是在一个Common下的function.php。TP的设计就是让我们少记忆一些结构。
定义函数很简单,只要在其中写自己的函数就行了。
比如我在 项目函数中定义了hello function :
function hello()
echo 'hello!';
}
然后 我的Index下custom_function 方法中使用了 hello()
访问 `startup/Index/custom_function` 然后就能看见自定义函数起作用了:
![2015-04-17/5530bda80d894](http://box.kancloud.cn/2015-04-17_5530bda80d894.png "自定义函数hello的使用结果")
### 如何隐藏入口
每次我们默认的url 里 必须带上**index.php** 这样看上去长又丑陋。
如果想伪静态化,显示个**index.php** 就失效了。
所以我们想隐藏**index.php**。
只需要Apache开启rewrite模块,和项目和Index.php的目录放入一个.htaccess文件即可。
可以通过URL重写隐藏应用的入口文件index.php,下面是相关服务器的配置参考:
[ Apache ]
- httpd.conf配置文件中加载了**mod\_rewrite.so**模块
- AllowOverride None 将None改为 All
- 把下面的内容保存为.htaccess文件放到应用入口文件的同级目录下
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>
[ IIS ]
如果你的服务器环境支持**ISAPI_Rewrite**的话,可以配置**httpd.ini**文件,添加下面的内容:
`RewriteRule (.*)$ /index.php?s=$1 [I]`
在IIS的高版本下面可以配置web.Config,在中间添加rewrite节点:
<rewrite>
<rules>
<rule name="OrgPage" stopProcessing="true">
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^(.*)$" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php/{R:1}" />
</rule>
</rules>
</rewrite>
[ Nginx ]
在Nginx低版本中,是不支持**PATHINFO**的,但是可以通过在Nginx.conf中配置转发规则实现:
location / {
// …..省略部分代码
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
其实内部是转发到了ThinkPHP提供的兼容模式的URL,利用这种方式,可以解决其他不支持PATHINFO的WEB服务器环境。
如果你的ThinkPHP安装在二级目录,Nginx的伪静态方法设置如下,其中youdomain是所在的目录名称。
location /youdomain/ {
if (!-e $request_filename){
rewrite ^/youdomain/(.*)$ /youdomain/index.php?s=$1 last;
}
}
原来的访问URL:
`http://serverName/index.php/模块/控制器/操作/[参数名/参数值...]`
设置后,我们可以采用下面的方式访问:
`http://serverName/模块/控制器/操作/[参数名/参数值...]`
默认情况下,URL地址中的模块不能省略,如果你需要简化某个模块的URL访问地址,可以通过设置模块列表和默认模块或者采用子域名部署到模块的方式解决,请参考后面的模块和域名部署部分。
- 序
- 前言
- 内容简介
- 目录
- 基础知识
- 起步
- 控制器
- 模型
- 模板
- 命名空间
- 进阶知识
- 路由
- 配置
- 缓存
- 权限
- 扩展
- 国际化
- 安全
- 单元测试
- 拿来主义
- 调试方法
- 调试的步骤
- 调试工具
- 显示trace信息
- 开启调试和关闭调试的区别
- netbeans+xdebug
- Socketlog
- PHP常见错误
- 小黄鸭调试法,每个程序员都要知道的
- 应用场景
- 第三方登录
- 图片处理
- 博客
- SAE
- REST实践
- Cli
- ajax分页
- barcode条形码
- excel
- 发邮件
- 汉字转全拼和首字母,支持带声调
- 中文分词
- 浏览器useragent解析
- freelog项目实战
- 需求分析
- 数据库设计
- 编码实践
- 前端实现
- rest接口
- 文章发布
- 文件上传
- 视频播放
- 音乐播放
- 图片幻灯片展示
- 注册和登录
- 个人资料更新
- 第三方登录的使用
- 后台
- 微信的开发
- 首页及个人主页
- 列表
- 归档
- 搜索
- 分页
- 总结经验
- 自我提升
- 进行小项目的锻炼
- 对现有轮子的重构和移植
- 写技术博客
- 制作视频教程
- 学习PHP的知识和新特性
- 和同行直接沟通、交流
- 学好英语,走向国际
- 如何参与
- 浏览官网和极思维还有看云
- 回答ThinkPHP新手的问题
- 尝试发现ThinkPHP的bug,告诉官方人员或者push request
- 开发能提高效率的ThinkPHP工具
- 尝试翻译官方文档
- 帮新手入门
- 创造基于ThinkPHP的产品,进行连带推广
- 展望未来
- OneThink
- ThinkPHP4
- 附录