PHP基础(028)---ThinkPHP框架2

ThinkPHP框架学习整理2:

Thinkphp是单一入口模式,也就是说所有流程都是从index.php开始的。项目目录下的index.php我们称之为入口文件。你所编写的Action,使用http://server/project/index.php/Action/function的形式访问。执行index.php的时候,Thinkphp的dispatch模块会自动分析应该加载哪个Action,并调用相应的函数。

一)构建项目:

  ThinkPHP 具有项目目录自动创建功能,因此构建项目应用程序非常简单,您只需要定义好项目的入口文件,在第一次访问入口文件的时候,系统就会自动根据您在入口文件中所定义的目录路径,迅速为您创建好项目的相关目录结构。
这里以 Myapp 为项目名称进行示例,先创建好目录结构后,再逐一为您介绍各目录功能用途。
具体操作步骤:
1>. 在 www 根目录下新建一个文件夹,起名为 Myapp。
2>. 下载 ThinkPHP 核心文件,将其复制到 Myapp 目录下。
3>. 在 Myapp 目录下,新建一个入口文件,起名为 index.php,代码如下:
<?php
// 定义项目名称
define ('APP_NAME','Myapp');
//定义项目路径
define('APP_PATH','./ Myapp /');
// 加载入口文件
require ('./ThinkPHP/ThinkPHP.php');
?>
4>. 打开浏览器,访问该项目的入口文件:这时可以看到项目构建成功后的提示画面,并且在 Myapp目录下,已为您构建好了项目目录。
注意:如果是 linux 环境下面部署,需要给项目入口文件里面指定的路径设置可写权限。这些目录仅仅针对项目目录,系统目录无需设置任何可写权限,因为每个项目的模版缓存和数据缓存,以及日志文件都是独立的。
 
二)ThinkPHP 框架目录结构:
ThinkPHP.php : ThinkPHP 公共文件。
Common 目录 : 系统公共文件目录
Lang 目录 : 系统语言包目录
Lib 目录 : 系统基类库目录
Tpl 目录 : 框架系统模版目录
Vendor 目录 : 第三方类库目录
另外系统基类库目录 Lib 文件夹下,还有相关的子目录:
Think 文件夹:系统运行库目录(必须)
ORG 文件夹:扩展类库目录( 非必须) 
具体内容可以打开目录查看结构和文件组成。
 
=》再来看看系统自动生成的Myapp项目目录结构
Cache 目录:项目自动生成的模版缓存
Common 目录:项目中应用的公共文件,通常包含 common.php 公共函数文件。
Conf 目录: 项目各项配置文件。
Data 目录:项目的数据缓存目录。
Lang 目录:项目的语言包文件。
Lib 目录:应用类库目录,在这文件夹内通常包含两个子目录:Action 和 Model,Action 目录放置命名控制器文件,Model 目录放置模块类文件。除此之外,还可以放置其他的项目类库。
Logs 目录:项目的日志文件。
Temp 目录:数据缓存目录,存放项目缓存文件。
Tpl 目录:项目模板文件,按风格创建对应的子目录。
注意:在 Linux 环境下,项目目录的 Cache(模版缓存目录)、Data(数据缓存目录)、Temp(编译缓存目录)、Logs(日志文件目录)必须设置为可写。
 
三)创建数据表和项目配置:
1) 创建数据库
2) 在 config.php 配置文件中设置数据库访问的连接信息
3) 在 项目/Lib/Model 目录下,建立模型文件,就可以直接对数据表进行增删改查等操作了。
具体操作步骤:(以 MySQL 为例,如果是其他数据库请修改后再执行)
1) 创建一个数据库,名为 myapp
2) 运行下面的 sql 增加一个 think_message 表。
3) 在 Myapp/Conf 目录下面创建一个 config.php 项目配置文件,代码如下:
<?php
return array(
// 定义数据库连接信息
‘DB_TYPE’=> ‘mysql’, // 指定数据库是 mysql
‘DB_HOST’=> ‘localhost’,//服务器地址
'DB_NAME'=>'myapp',  // 数据库名
‘DB_USER’=>‘root’,  //用户名
'DB_PWD'=>'123456',  //您的数据库连接密码
‘DB_PORT’=>‘3306’,  //端口
'DB_PREFIX'=>'think_',//数据表前缀(与数据库 myapp 中的表 think_message 对应)
 

 //'配置项'=>'配置值'
 'APP_GROUP_LIST' => 'Index,Admin',
 'DEFAULT_GROUP' => 'Index',

 'APP_GROUP_MODE' => 1,
 
 //独立分组,此文件夹名称可以修改为其他
 'APP_GROUP_PATH' => 'Modules',
   
 'TMPL_VAR_IDENTIFY' => 'array',
 'TMPL_FILE_DEPR' => '_',


);
?>
注意:请确保配置文件里面的设置和你本地的数据库连接信息一致。
4) 在 Myapp/Lib/Model/目录下,新建一个文件 MessageModel.class.php,代码如下:
class MessageModel extends Model{ }    
 
四)ThinkPHP 的表和模型的命名规则:
ThinkPHP 要求数据库的表名和模型类(model)的命名要遵循一定的规范,首先数据库的表名采用小写形式,模型类文件名的命名规则是:
不含前缀的数据表表名(采用驼峰命名法)+Model
在创建 message 表时,我们使用的名称是 think_message,think_就是数据表前缀。在配置文件中我们已使用'DB_PREFIX'=>'think_' 作出了指定。
例如:MessageAction.class.php
 
五)控制器和 URL 访问:
如何定义一个应用模块?
在项目目录/Lib/Action 文件夹下,建立一个“模块名+Action.class.php”文件,并继承 Action 类则可。 
如何定义一个操作?
在应用模块类的代码中,添加一个 function 方法则可
如何访问具体操作?
http://服务器地址/项目地址/模块名称/操作名称
如何通过 URL 传递变量?
http://服务器地址/项目地址/模块名称/操作名称/变量名 1/变量值 1/变量名 2/变量值 2/ 
 
六)ThinkPHP的数据操作:
  • 使用 ThinkPHP 开发时,项 目中每一个继承了 Model 的模型类,都 会对应着一个数据表(或者视图),模型与数据表存在一种映射关系。( 例如之前我们所定义的 MessageModel 类, 对应的就是think_message 表)。
  • 开发过程中,只要简单地定义好与数据表对应的模型类(xxxModel.class.php),甚至无需增加任何属性和方法就可以进行对数据操作了。
  • ThinkPHP 提供了灵活和方便的数据操作方法,不仅实现了对数据库操作的四个基本操作(CURD):创建、更新、读取和删除的实现,还内置了很多实用的数据操作方法。
如何添加记录到数据库表?
1) 获取(设置)要添加的数据内容。
2) 实例化数据模型,调用 Model 类的 add( )方法即可添加。
具体操作实践一 添加数据 :数据对象赋值
1.1> 在 Index 模块中新添一个方法 add1,代码如下:
public function add1(){
// 使用 D 函数实例化消息模型类
$Message = D('Message');
// 然后给数据对象赋值
$Message->title = 'ThinkPHP';
$Message->email = 'ThinkPHP@gmail.com';
// 使用 add 方法保存内容
$Message->add();
// 使用 select 方法进行数据查询
$rs = $Message->select();
// 使用 dump 函数 输出查询数据查看
dump ( $rs );
}
 
1.2> 在浏览器中访问 http://localhost/index.php/Index/add1,成功可以看到如下数据:
array(1) {
[0] => array(6) {
["id"] => string(1) "1"
["title"] => string(8) "ThinkPHP"
["content"] => string(0) ""
["create_time"] => string(1) "0"
["email"] => string(18) ThinkPHP@gmail.com
["status"] => string(1) "1"
}
}
D( ) 函数 通常要实例化一个类,都是导入这个类文件,然后使用 new 关键字进行实例化    相当于 new Model(‘message’);
dump( ) 函数是 ThinkPHP 内置的对浏览器友好的变量输出函数。
 
操作实践二 添加数据 :数组赋值
1> 在 Index 模块中再添加一个方法 add2,代码如下:
public function add2(){
// 使用 D 函数实例化一个模型类
$dao = D('Message');// 然后给数据对象赋值
$data['title'] = '敏捷式开发框架 ThinkPHP!';
$data['email'] = [email=]'TP@thinkphp.cn';[/email]
$data['create_time'] = time();
$data['content'] = '使用 ThinkPHP 进行数据操作';
// 使用 add 方法保存内容
// 不需要传入主键的值就可以新建数据
$dao->add($data);
// 使用 select 方法进行数据查询
$rs = $dao->select();
header("ContentType:text/html;charset=utf8");
dump ( $rs );
}
 
2> 在浏览器中访问 http://localhost/index.php/Index/add2,成功后同样可以看到刚加入的数据。
add( ) 方法
添加数据可以通过 add( )方法进行实现,如果表的主键是自动增长类型,不需要传入主键的值就可以新建数据,并且如果插入数据成功的话,add 方法的返回值就是最新插入的主键值,可以直接获取。
例如:$insertId = $dao->add($data);
select( ) 方法
对数据进行查询使用 select( )方法,当该方法没有传入任何参数时,会获取全部数据。
具体操作实践三    添加数据 :利用表单创建数据并添加记录
一般来说,在表中添加数据都是通过表单来建立,下面我们使用 Message 模块进行实践体验。
1> 打开 Myapp/Lib/Action/MessageAction.class.php 文件,将原来的操作方法代码删去,并新添一个方法 add(),代码很简单,只要渲染模板进行输出则可,如下所示:
public function add() {
$this->assign('title','添加数据');
$this->display( );
}
 
2> 对应 Message 应用模块,我 们在 Myapp/Tpl/目录下新建一个文件夹,起 名为 Message,
并在 Myapp/Tpl/Message 目录下新添一个模板文件 add.html,关键代码如下:
<form action="__URL__/insert" method="post" >
标题:<input name="title" type="text" />
邮箱:<input name="email" type="text" />
内容:<textarea name="content" rows="6" cols="50" ></textarea>
<input type="submit" value="提交" />
</form>
3> 在 MessageAction.class.php 中添加一个表单处理的方法 insert,代码如下:
// 处理表单数据的方法
public function insert() {
$dao = D('Message');
// 调用 Model 类的 create 方法创建通过表单提交的数据对象
$vo = $dao->create();
// 创建失败提示
if(false === $vo) {
exit($dao->getError().' [ <a href="javascript:history.back()">返 回</a> ]');
}
// 当主键是自动增长类型时,方法的返回值就是最新插入的主键值,可以直接获取
$rs = $dao->add();
// 添加数据失败提示
if (!$rs) {
exit($dao->getError().' [ <a href="javascript:history.back()">返 回</a> ]');
}
// 成功提示并返回,使用了函数 redirect($url,$time=0,$msg='')
redirect('add',2,'数据添加成功!');  }
4> 接着,通过访问 http://localhost/index.php/Message/add 进行表单数据提交测试。
上面示例中的action 提交到的处理地址是__URL__/insert  模板引擎会自动将这句替换为/index.php/Message/insert
常见模板使用的特殊变量还有:
__ROOT__ 网站根目录地址
__APP__ 当前项目(入口文件)地址
__URL__ 当前模块地址
__ACTION__ 当前操作地址
__SELF__ 当前 URL 地址
__PUBLIC__ 公共文件夹 Public 地址
create( ) 方法
create 方法用来创建数据对象,当参数为空时,默认是通过表单提交的数据。调用该方法后,就可以直接使用 add()方法进行添加数据,而不用再设置插入数据的内容。
getError( ) 方法
用来捕获数据库操作过程中的出错提示。
1> 页面 Trace
页面 Trace 功能提供了很好的 SQL 调试方法,而且可以很直观的在当前页面查看到 SQL 语句信息,我们只需要设置参数:'SHOW_PAGE_TRACE' => TRUE,这样,我们可以在页面看到类似下面的信息:
SQL 记录 : 1 条 SQL
[ 09040805:38:13 ] RunTime:0.000238s SQL = SELECT * FROM think_message
2> 开启 SQL 日志
页面 Trace 信息虽然直观,但是只能显示当前页面的 SQL 执行信息,如果你使用了 Ajax 操作,那么后台的执行 SQL 可能就不会显示,我们只能通过查看 SQL 日志了。可以在配置参数里面开启SQL 日志记录。
'SQL_DEBUG_LOG' => TRUE,
我们可以在 Logs 目录下面的 sql 日志文件里面看到:
[ 09040805:50:12 ]
RunTime:0.000238s SQL = SELECT * FROM think_message WHERE id in (1,2,5)
这样的记录信息,可以分析具体执行的 SQL 语句是否有问题,以及执行时间,便于优化。
3> 使用 getLastSql 方法
如果你没有开启 SQL 日志,也没有使用页面 Trace 信息显示功能,那么依然可以调试可能出现错误的 SQL 语句,我 们可以在查询方法的后面使用 getLastSql 方法来查看最后一次执行的 SQL 语句。
便于分析错误可能的原因。
$dao->find(8);
echo $dao->getLastSql();
 
4> 使用调试配置文件
单独定义调试配置文件,可以给你的项目设置最合理的参数。而且你还可以给调试模式增加单独的数据库连接。
我们可以在项目的 Conf 目录下面增加调试配置,内容如下:
'SHOW_RUN_TIME' => TRUE, // 开启运行时间显示
'SHOW_ADV_TIME' => TRUE, // 显示详细运行时间信息
'SHOW_DB_TIMES' => TRUE, // 显示数据库查询和写入次数
'SHOW_RUN_TIME' => TRUE, // 开启运行时间显示
5> 开启调试模式
只要在配置中设置'DEBUG_MODE'=>true,就可以开启调试模式。
系统默认是调用 ThinkPHP/Common/debug.php 的配置设置。要自行定义时,只要在项目Myapp/Conf/目录下,添加 debug.php 文件,然后根据需要进行设置。
 
七)Thinkphp 的数据查询:
如何查询记录?
1> 设置查询条件 (如果是查找所有记录,这一步可省略)
2> 使用最直观易懂的操作方式:要进行数据操作的模型->对查询设定(连贯操作)->进行查询
例如:$User->where(‘name=thinkphp’)->find();
基础知识连贯操作
所谓连贯操作,是 ThinkPHP 使用了魔术方法来实现的一些特殊的 Model 类方法,可以对数据对象连续调用数个方法(参数)来设定特定的条件,然后执行最终所指定的操作,这类特定方法的命名都很直观易记,主要方法有:
field //要查询的字段名
table //数据表名称 不指定时,默认为当前数据对象所对应的表
where //查询条件
order // 排序
limit //结果限制
having //having 支持
group //group 支持
distinct //distinct 筛选支持
连贯操作应用代码示例:
$User->where('status=1')
->table('`other_db`.`think_user`')
->order('create_time')
->limit(10)
->select();
数据查询具体操作实践
我们新建立一个应用模块 Search 专门用来体验 ThinkPHP 的各种查询方式。先在 Myapp/Lib/Action 目录下,新建一个 PHP 文件,命名为:SearchAction.class.php。并定义类:
<?php
// 数据查询体验
class SearchAction extends Action{
function _initialize( ) {
// 为了方便使用 dump 函数查看结果输出,先在初始化方法里统一编码
header("ContentType:text/html; charset=utf8");
}
}//类定义 end
?>
 
1> 查询单条记录
当数据表的主键为 id 并且是自动增长时,可以直接使用 find(id 编号)进行查询。
1.1> 在 Search 应用模块中新添一个方法,代码如下:
// 使用 find 方法查询 1
public function find1(){
// 实例化模型
$dao = D('Message');
// 查询 id 为 5 的记录
$rs = $dao->find(5);
// 输出结果
dump ($rs);
// 输出 sql 语句进行对比
dump($dao->getLastSql());
}
2> 查询符合特定条件的单条数据
2.1> 新添一个方法 find2,代码如下:
// 使用 find 方法查询 2
public function find2(){
// 实例化模型
$dao = D('Message');
// 设置查询条件
$where['status'] = 1;
$where['email'] = 'TP@thinkphp.cn';
// 需要查询的字段
$field = 'email,title';
// 进行查询
$rs = $dao->where($where)->field($field)->find();
// 输出结果
dump($rs);
// 输出 sql 语句
dump($dao->getLastSql());
}
2.2> 访问 find2 操作 http://localhost/index.php/Search/find2
可以看到这样进行查询的 sql 就是:
"SELECT `email`,`title` FROM `think_message` WHERE ( `status` = 1 ) AND ( `email` = 'TP@thinkphp.cn' ) LIMIT 1 "
注意:使用 find( )方法进行查询,无论符合条件的结果有多少个,都只会返回单条记录。
在连贯操作中的参数(where,field,order 等)顺序是不分先后的,如本例,如果使用
$rs = $dao‐>field($field)‐>where($where)‐>find();
所得的操作结果完全一样,所以不必去记住顺序。
3> 获取所有记录
3.1> 添加一个方法 select1,代码如下:
// 获取所有记录集
public function select1(){
// 实例化模型
$dao = D('Message');
// 设置查询条件
$where['status'] = 1;
// 需要查询的字段
$field = 'email,title';
// 进行查询
$rs = $dao->where($where)->field($field)->select();
// 输出结果
dump($rs);
// 输出 sql 语句进行
dump($dao->getLastSql());
}
3.2> 访问 select1 操作:http://127.0.0.1/index.php/Search/select1
同 find 方法一样,连贯操作中,除了 select 方法必须放到最后,参数条件顺序不限。
使用 select 方法进行查询,返回的是一个数据记录集。
select 方法也支持 join,like 等更复杂的查询,具体应用可以参看相关手册。
select 方法还有一个别名 findall,使用方式是一样的。
$rs = $dao->where($where)->field($field)->findall();
 
八)ThinkPHP 的数据更新:
更新记录使用 save 方法:
$User->find(1); // 查找主键为 1 的数据
$User->email = 'TOPThink@thinkphp.cn'; // 修改数据对象
$User->save(); // 保存当前数据对象
// 还可以使用下面的方式更新
$User->score = array('exp','(score+1)'); // 对用户的积分加 1
$User-> save();
如果不是使用数据对象的方式来保存,可以传入要保存的数据和条件
$data['id'] = 1;
$data['name'] = 'TopThink';
$User->save($data);
除了 save 方法外,你还可以使用 setField 方法来更新特定字段的值,例如:
$User->where('id=1')->setField('name','TopThink');
使用原生 sql
通过 execute 方法执行 sql 语句,
$User->execute("UPDATE __TABLE__ SET name='thinkPHP' WHERE status=1");
 
九)ThinkPHP 的数据删除:
删除记录使用 delete 方法
删除单条记录
$User->find(2);
$User->delete(); // 删除查找到的记录
删除多条记录
$where[‘id’] = array(‘in’,’1,2,3,4,6,8’);
$User->where($where)->delete();
使用原生 sql
$User->execute("DELETE FROM __TABLE__ WHERE name='thinkPHP'");
 
十)ThinkPHP 的模板使用:
通常一个应用模块中,会有若干操作(function)需要有与用户交互的页面,这就需要用到模板输出,ThinkPHP 本身已内置了一套具有 ThinkPHP 特色的,很强大易扩展且应用非常方便的模板引擎。
如何使用模板?
仅需一步,在项目/Tpl/风格目录/下,建立一个 html 文件与操作名称相对应就可以了。
具体操作实践
1 在 Myapp/Tpl/下建立一个目录,根据应用模块的名称,我们将这个文件夹命名为 Index。
2 在 Myapp/Tpl/Index/目录下建立一个 html 文件,根据操作名称,我们命名该文件为index.html。
3 打开 Myapp/Lib/Action/IndexAction.class.php 文件,将 index 操作的代码修改为。
<?php
class IndexAction extends Action{
public function index(){
$value = 'hello,ThinkPHP';
$this->assign('title',$value);
$this->display( );
}
}
?>
4 打开 Myapp/Tpl/default/Index/index.html 文件,代码为:
<!DOCTYPE html PUBLIC "//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta httpequiv="ContentType" content="text/html; charset=utf8" />
<title>{$title}</title>
</head>
<body>
测试输出: {$title}
</body>
</html>
5 在浏览器中输入 http://127.0.0.1/Myapp/ ,我们可以看到,在浏览器的标题栏和页面中,index方法所定义的模板变量$title 已成功地输出。
如果要同时输出多个模板变量,可以使用下面的方式:
$array = array();
$array['name'] = 'thinkphp';
$array['email'] = 'liu21st@gmail.com';
$array['phone'] = '12335678';
$this->assign($array);
这样,就可以在模板文件中同时输出 name、email 和 phone 三个变量。
模板调用
1 直接调用 index 操作模板
$this->display();
// 对应 Myapp/Tpl/Index/index.html
2 调用 Index 模块的 test1 操作模板
$this->display('test1');
//对应 Myapp/Tpl/Index/test1.html
2 调用 Message 模块的 test2 操作模板()
$this->display('Message:test2');
//对应 Myapp/Tpl/Message/test2.html
3 调用 XP 主题的 Message 模块的 test2 操作模板
$this->display('Xp@Message:test2');
//对应 Myapp/Tpl/Xp/Message/test2.html
4 直接指定模板文件的全名
$this->display('../Message/test3.html');
//对应 Myapp/Tpl/Message/test3.html
模板变量循环输出
在模板中对数据进行循环输出使用 iterate 标签。
模版变量赋值
$Message = D('Message');
$list = $Message->select();
$this->assign('list',$list);
模版定义
<iterate name="list" id="vo">
{$vo.name}
</iterate>
注意 name 和 id 表示的含义,name 是已赋值的模板变量,id 是在这个循环中所使用的变量。
id=’vo’中的 vo 即 foreach($list as $val)中的$val。
// 输出 list 的第 5~15 条记录
<iterate name="list" id="vo" offset="5" length='10'>
{$vo.name}
</iterate>
// 输出偶数记录
<iterate name="list" id="vo" mod="2" >
<eq name="mod" value="1">
{$vo.name}
</eq>
</iterate>
// 输出 key
<iterate name="list" id="vo" key="k" >
{$k}.{$vo.name}
</iterate>
iterate 还有其它别名是 volist,sublist
子循环输出
<volist name="list" id="vo">
<sublist name="vo['sub']" id="sub">
{$sub.name}
</sublist>
</volist>
 
 
 

posted on 2014-05-05 23:59  lbsf  阅读(217)  评论(0)    收藏  举报

导航