@a5635268
2016-02-11T21:17:16.000000Z
字数 14858
阅读 2100
源码分析与使用笔记
定义数据表模型
http://document.thinkphp.cn/manual_3_2.html#define_model
$New = new \Home\Model\NewModel('blog','think_',$connection);
# ↓↓数据库连接信息
new \Home\Model\NewModel('blog','think_','mysql://root:1234@localhost/demo');
$connection = array(
'db_type' => 'mysql',
'db_host' => '127.0.0.1',
'db_user' => 'root',
'db_pwd' => '12345',
'db_port' => 3306,
'db_name' => 'demo',
);
# 3.23支持分布式部署↓↓
$connection = array(
'db_type' => 'mysql',
'db_host' => '192.168.1.2,192.168.1.3',
'db_user' => 'root',
'db_pwd' => '12345',
'db_port' => 3306,
'db_name' => 'demo',
'db_charset' => 'utf8',
'db_deploy_type'=> 1,
'db_rw_separate'=> true,
'db_debug' => true,
);
//数据库配置2 在配置文件中定义
'DB_CONFIG2' => 'mysql://root:1234@localhost:3306/thinkphp',
new \Home\Model\BlogModel('blog','think_','DB_CONFIG2');
D方法还可以支持跨模块调用,需要使用:
//实例化Admin模块的User模型
D('Admin/User');
//实例化Extend扩展命名空间下的Info模型
D('Extend://Editor/Info');
// 使用M方法实例化 操作db_name数据库的ot_user表
$User = M('db_name.User','ot_');
$New = M('new','think_',$connection);
// 等效于 $New = new \Think\Model('new','think_',$connection);
http://document.thinkphp.cn/manual_3_2.html#connect_db
可以在查询的时候,临时切换数据库,甚至可以切换到远程的数据库
http://document.thinkphp.cn/manual_3_2.html#distributed_database
//table: think_user
$Model->table('__USER__')->where('status>1')->select();
//alias
$Model->alias('a')->join('__DEPT__ b ON b.user_id= a.id')->select();
//field
$Model->field(array('user_id','content'),true)->select();
$Model->field('title,email,content')->create();
$Model->field('title,email,content')->save($data);
//page
$Article->page('1,10')->select(); // 查询第一页数据,每页10条
//having 只支持字符串
$this->field('username,max(score)')->group('user_id')->having('count(test_time)>3')->select();
//join
$Model->join('__WORK__ ON __ARTIST__.id = __WORK__.artist_id','RIGHT')->select();
$Model->join('RIGHT JOIN __WORK__ ON __ARTIST__.id = __WORK__.artist_id')->select();
//排重
$Model->distinct(true)->field('name')->select();
//数据缓存
//缓存有效期和缓存类型是由DATA_CACHE_TIME和DATA_CACHE_TYPE配置参数决定的
$Model->where('id=5')->cache(true)->find();
$Model->cache(true,60,'xcache')->find(); //也可以单独设置
$result = $Model->cache('key',60)->find(); //甚至可以指定一个key键到用到的时候取出来;
//直接返回sql
$result = M('User')->fetchSql(true)->find(1);
//关闭表单令牌验证,开启??
$model->token(false)->create();
http://document.thinkphp.cn/manual_3_2.html#name_range
也就是TP的查询语言进行封装,封装在自定义模型类属性里面;对于一些比较经常刷的表,可以采用这个方式,的确可以让代码重用度比较高;
// Model::MODEL_INSERT(或者1)和Model::MODEL_UPDATE(或者2)
create($_POST,Model::MODEL_UPDATE);
//字段过滤
$User->field('name,email')->create($data);
//在自定义模型类中可以通过以下的方式在规定数据库在新增或者更新的时候需要插入的值
namespace Home\Model;
use Think\Model;
class UserModel extends Model{
protected $insertFields = 'name,email'; // 新增数据的时候允许写入name和email字段
protected $updateFields = 'email'; // 编辑数据的时候只允许写入email字段
}
http://document.thinkphp.cn/manual_3_2.html#insert_data
# 有就更新,没有就添加?
add($data='',$options=array(),$replace=false)
# creat后调用add或者save都可以自动识别
$User = M("User"); // 实例化User对象
// 根据表单提交的POST数据创建数据对象
if($User->create()){
$result = $User->add(); // 写入数据到数据库
if($result){
// 如果主键是自动增长型 成功后返回值就是最新插入的值
$insertId = $result;
}
}
# 使用过滤方法对要写入的数据进行过滤
$data['name'] = '<b>thinkphp</b>';
$data['email'] = 'thinkphp@gmail.com';
$User = M('User');
$User->data($data)->filter('strip_tags')->add();
# 可以进行批量写入
$User->addAll($dataList);
http://document.thinkphp.cn/manual_3_2.html#read_data
//array(`id`=>`nickname`)
$list = $User->getField('id,nickname');
// 获取id数组集
$User->getField('id',true);
//类似于select()方法的结果遍历将id的值设为数组key
$list = $User->getField('id,nickname,email');
//键名是用户id,键值是 nickname:email的输出字符串。
$list = $User->getField('id,nickname,email',':');
http://document.thinkphp.cn/manual_3_2.html#update_data
$User-> where('id=5')->setField('name','ThinkPHP');
$User->where('id=5')->setInc('score',3); // 用户的积分加3
$User->where('id=5')->setInc('score'); // 用户的积分加1
$User->where('id=5')->setDec('score',5); // 用户的积分减5
$User->where('id=5')->setDec('score'); // 用户的积分减1
# 3.23支持延迟更新
$Article->where('id=5')->setInc('view',1,60); // 文章阅读数加1,并且延迟60秒更新(写入)
注意:save方法的返回值是影响的记录数,如果返回false则表示更新出错,因此一定要用恒等来判断是否更新失败。
http://document.thinkphp.cn/manual_3_2.html#delete_data
delete方法的返回值是删除的记录数,如果返回值是false则表示SQL出错,返回值如果为0表示没有删除任何数据。
$User->delete('1,2,5'); // 删除主键为1,2和5的用户数据
$User = M("User"); // 实例化User对象
// 然后直接给数据对象赋值
$User->name = 'ThinkPHP';
$User->email = 'ThinkPHP@gmail.com';
// 把数据对象添加到数据库
$User->add();
$User = D("User");
$User->create(); // 创建User数据对象,默认通过表单提交的数据进行创建
// 增加或者更改其中的属性
$User->status = 1;
$User->create_time = time();
// 把数据对象添加到数据库
$User->add();
$user = M('user');
$user -> find(1);
$user -> getById(1); //getBy字段名(字段值)
//↑↑以上查询结果是保存在内存里面的,可以通过对象属性的方式取出来;
//注意只有find与getby, 才可以;
echo $user -> username;
// 查找主键为1、3、8的多个数据
$userList = $User->select('1,3,8');
# 先查询再更新
$User->find(1); // 查找主键为1的数据
$User->name = 'TOPThink'; // 修改数据对象
$User->save(); // 保存当前数据对象
# 直接更新
$User->id = 1;
$User->name = 'TOPThink'; // 修改数据对象
$User->save(); // 保存当前数据对象
$User->delete(8); // 删除主键为8的数据
$User->delete('5,6'); // 删除主键为5、6的多个数据
http://document.thinkphp.cn/manual_3_2.html#field_map
作用:在表单中隐藏真正的数据表字段的一种安全处理方式,比如在数据表中是username,然后在表单中为name;
可以支持数组创建where条件
http://document.thinkphp.cn/manual_3_2.html#express_query
# 模糊搜索配置
C('DB_LIKE_FIELDS','nickname|remark');
$where['nickname'] = '周'; //由于配置了DB_LIKE_FIELDS,所以这里的nickname是like模糊搜索
$user -> where($where) -> find();
# 区间查询
$map['id'] = array('between',array('1','8'));
# EXP:表达式
$map['id'] = array('exp',' IN (1,3,8) ');
// exp查询的条件不会被当成字符串,所以后面的查询条件可以使用任何SQL支持的语法,包括使用函数和字段名称。查询表达式不仅可用于查询条件,也可以用于数据更新
$User = M("User"); // 实例化User对象
// 要修改的数据对象属性赋值
$data['name'] = 'ThinkPHP';
$data['score'] = array('exp','score+1');// 用户的积分加1
$User->where('id=5')->save($data); // 根据条件保存修改的数据
http://document.thinkphp.cn/manual_3_2.html#fast_query
# 可读性非常差,不推荐使用
$map['status&score&title'] =array('1',array('gt','0'),'thinkphp','_multi'=>true);
http://document.thinkphp.cn/manual_3_2.html#region_query
$map['id'] = array(array('gt',1),array('lt',10)) ; // ( id > 1) AND ( id < 10)
$map['id'] = array(array('gt',3),array('lt',10), 'or') ;
$map['id'] = array(array('neq',6),array('gt',3),'and'); //默认是and
# 区间查询的条件可以支持普通查询的所有表达式
$map['name'] = array(array('like','%a%'), array('like','%b%'), array('like','%c%'), 'ThinkPHP','or'); //( name LIKE '%a%') OR ( name LIKE '%b%') OR ( name LIKE '%c%') OR ( name = 'ThinkPHP')
# 字符串模式查询
$User = M("User"); // 实例化User对象
$map['id'] = array('neq',1);
$map['name'] = 'ok';
$map['_string'] = 'status=1 AND score>10';
$User->where($map)->select();
//( `id` != 1 ) AND ( `name` = 'ok' ) AND ( status=1 AND score>10 )
# 请求字符串查询方式
$map['id'] = array('gt','100');
$map['_query'] = 'status=1&score=100&_logic=or';
# 复合查询
$where['name'] = array('like', '%thinkphp%');
$where['title'] = array('like','%thinkphp%');
$where['_logic'] = 'or';
$map['_complex'] = $where;
$map['id'] = array('gt',1);
//( id > 1) AND ( ( name like '%thinkphp%') OR ( title like '%thinkphp%') )
//一个数组一个括弧
http://document.thinkphp.cn/manual_3_2.html#stat_query
Count, Max, Min, Avg, Sum
http://document.thinkphp.cn/manual_3_2.html#sql_query
# query
// 表前缀处理
$Model->query("select * from __PREFIX__user where status=1");
$Model->query("select * from __USER__ where status=1");//3.22版本
# execute
$Model->execute("update think_user set name='thinkPHP' where status=1");
// 表前缀处理同上
如果当前采用了分布式数据库,并且设置了读写分离的话,以上内部已经实现了读写分离
$user = $User->getByName('liu21st');
$userId = $User->getFieldByName('liu21st','id');//表示根据用户的name获取用户的id值。
// 首先构造子查询SQL
# type 1:
$subQuery = $model->field('id,name')->table('tablename')->group('field')->where($where)->order('status')->select(false);
// type 2:
$subQuery = $model->field('id,name')->table('tablename')->group('field')->where($where)->order('status')->buildSql();
// 利用子查询进行查询
$model->table($subQuery.' a')->where()->order()->select()
http://document.thinkphp.cn/manual_3_2.html#auto_validate
array(
array(验证字段1,验证规则,错误提示,[验证条件,附加规则,验证时间]),
array(验证字段2,验证规则,错误提示,[验证条件,附加规则,验证时间]),
......
);
验证条件 (可选)
验证时间(可选)
protected $_validate = array(
array('verify','require','验证码必须!'), //默认情况下用正则进行验证
array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一
array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内
array('value','checkValue','当前类方法验证',1,'callback'), //当前的类方法验证
array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致
array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
);
$User->validate($rules)->create();
http://document.thinkphp.cn/manual_3_2.html#auto_operate
http://document.thinkphp.cn/manual_3_2.html#param_bind
http://document.thinkphp.cn/manual_3_2.html#multi_model_layer
ThinkPHP支持模型的分层 ,除了Model层之外,我们可以项目的需要设计和创建其他的模型层。
例如在Home模块的设计中需要区分数据层、逻辑层、服务层等不同的模型层,我们可以在模块目录下面创建Model、Logic和Service目录,把对用户表的所有模型操作分成三层:
D('User','Logic');
同样是继承\Think\Model, 只是其名称不同,用于业务逻辑分层处理
http://document.thinkphp.cn/manual_3_2.html#virtual_model
虚拟模型是指虽然是模型类,但并不会真正的操作数据库的模型;
一般用不到;
http://document.thinkphp.cn/manual_3_2.html#view_model
tp的模拟视图,这里的视图与mysql中的视图是两个概念;
namespace Home\Model;
use Think\Model\ViewModel;
class BlogViewModel extends ViewModel {
public $viewFields = array(
'Blog'=>array('id','name','title'),
'Category'=>array('title'=>'category_name', '_as' => 'cate', '_on'=>'Blog.category_id=Category.id','_type' => 'left',
'User'=>array('name'=>'username', '_on'=>'Blog.user_id=User.id'),
);
}
# 获取表名称;
'_table'=>"test_user"
// 3.2.2版本以上还可以使用简化定义(自动获取表前缀)
'_table'=>"__USER__"
# 还可以定义特殊字段
'Category'=>array('title'=>'category_name','COUNT(Blog.id)'=>'count','_on'=>'Category.id=Blog.category_id')
# 定义完之后可以让其和普通模型一样操作
D("BlogView")->field('id,name,title,category_name,username')->order('id desc')->group('id')->select();
http://document.thinkphp.cn/manual_3_2.html#relation_model
http://document.thinkphp.cn/manual_3_2.html#adv_model
高级模型提供了更多的查询功能和模型增强功能,利用了模型类的扩展机制实现。
namespace Home\Model;
use Think\Model\AdvModel;
class UserModel extends AdvModel{
}
protected $_filter = array(
'过滤的字段'=>array('写入回调方法','读取回调方法','是否传入整个数据对象(默认为改字段)'),
)
protected $serializeField = array(
'info' => array('name', 'email', 'address'), //把name,email,address,序列化之后存储到info字段中
);
// 查询的时候,其实可以通过属性值读取出来的;
$User->find(8);
echo $User->name;
文本字段,貌似没什么用
只读字段
protected $readonlyField = array('name', 'email'); //对于一些一旦写入就无法更改的字段
不是很理解,后续通过一个例子来看
$User = M("User"); // 实例化User对象
// 返回结果是一个数组数据
$data = $User->find(6);
// 返回结果是一个stdClass对象
$data = $User->returnResult($data, "object");
// 还可以返回自定义的类
$data = $User->returnResult($data, "User");
// 是对data数据做了处理,然后再返回的类;
Class User {
public function __construct($data){
// 对$data数据进行处理
}
}
http://document.thinkphp.cn/manual_3_2.html#mongo
$Model = new Think\Model\MongoModel("User");
$Model->field("name,email,age")->order("status desc")->limit("10,8")->select();
http://document.thinkphp.cn/manual_3_2.html#template_define
通过配置定义:
可以定义多主题模板
http://document.thinkphp.cn/manual_3_2.html#template_theme
略
http://document.thinkphp.cn/manual_3_2.html#template_display
display('[模板文件]'[,'字符编码'][,'输出类型'])
$this->display('Member:read'); //表示调用Member模块下面的read模板。
$this->display('./Template/Public/menu.html'); //直接渲染指定目录的模板
http://document.thinkphp.cn/manual_3_2.html#get_template_file
T函数的返回值是一个完整的模板文件名,可以直接用于display和fetch方法进行渲染输出;
很少用到这个东西
http://document.thinkphp.cn/manual_3_2.html#template_fetch
# 返回渲染后的内容
$content = $this->fetch('Member:edit');
# 渲染输出
show('渲染内容'[,'字符编码'][,'输出类型'])
http://document.thinkphp.cn/manual_3_2.html#template_engine
'TMPL_ENGINE_TYPE' =>'PHP' # 支持原生的PHP模板或者其他模板引擎;
http://document.thinkphp.cn/manual_3_2.html#var_output
# 可输出对象
{$data:name}
{$data->name}
http://document.thinkphp.cn/manual_3_2.html#system_var
# 支持输出 $_SERVER、$_ENV、 $_POST、 $_GET、 $_REQUEST、$_SESSION和 $_COOKIE变量
{$Think.server.script_name}
# 常量输出
{$Think.const.MODULE_NAME}
{$Think.MODULE_NAME}
# 配置输出
{$Think.config.db_charset}
# 语言变量
{$Think.lang.page_error}
http://document.thinkphp.cn/manual_3_2.html#use_function
http://document.thinkphp.cn/manual_3_2.html#default_val
http://document.thinkphp.cn/manual_3_2.html#use_operate
http://document.thinkphp.cn/manual_3_2.html#taglib
# 对于非内置标签库,都要提前导入
<taglib name="html,article" />
# 可以配置内置标签库
'TAGLIB_BUILD_IN' => 'cx,article'
# 可以预加载标签库
'TAGLIB_PRE_LOAD' => 'article,html'
http://document.thinkphp.cn/manual_3_2.html#template_extend
在父模板中定义一些需要再子模板赋值的block数据块,然后再在子模板中通过extend标签,把这些数据块给到父模板,一般在后台应用中使用;
http://document.thinkphp.cn/manual_3_2.html#modify_edlim
标签和变量的定界符可以修改
{$info['status']?$info['msg']:$info['error']}; //三元运算符中暂时不支持点语法。
http://document.thinkphp.cn/manual_3_2.html#include
模版表达式的定义规则为:模块@主题/控制器/操作
<include file='模版表达式或者模版文件1,模版表达式或者模版文件2,...' />
<include file="Public/header" /> // 包含头部模版header
<include file="Blue/Public/menu" /> // 包含blue主题下面的menu模版
<include file="./Application/Home/View/default/Public/header.html" /> <include file="Public/header" title="ThinkPHP框架" keywords="开源WEB开发框架" /> // 包含header模板的时候传入了title和keywords变量
http://document.thinkphp.cn/manual_3_2.html#compare
http://document.thinkphp.cn/manual_3_2.html#literal_output
可以使标签不被解析
{/* 注释内容 */ } 或 {// 注释内容 } //注意{和注释标记之间不能有空格。
http://document.thinkphp.cn/manual_3_2.html#template_layout
设置了模板布局之后,就是先解析模板布局文件,然后再把display的渲染的模板作为一个特定变量放在布局模板中,这个特定变量可以设置;
通过以下三种方式可以使用模板布局
'LAYOUT_ON'=>true,
'LAYOUT_NAME'=>'layout',
<layout name="layout" />
在进行模板渲染之前,系统还会对读取的模板内容进行一些特殊字符串替换操作,也就是实现了模板输出的替换和过滤。
__ROOT__: 会替换成当前网站的地址(不含域名)
__APP__: 会替换成当前应用的URL地址 (不含域名)
__MODULE__:会替换成当前模块的URL地址 (不含域名)
__CONTROLLER__(__或者__URL__ 兼容考虑): 会替换成当前控制器的URL地址(不含域名)
__ACTION__:会替换成当前操作的URL地址 (不含域名)
__SELF__: 会替换成当前的页面URL
__PUBLIC__:会被替换成当前网站的公共目录 通常是 /Public/
# 可以进行以下配置
'TMPL_PARSE_STRING' =>array(
'__PUBLIC__' => '/Common', // 更改默认的/Public 替换规则
'__JS__' => '/Public/JS/', // 增加新的JS类库路径替换规则
'__UPLOAD__' => '/Uploads', // 增加新的上传路径替换规则
)
http://document.thinkphp.cn/manual_3_2.html#define_controller
http://document.thinkphp.cn/manual_3_2.html#before_after_action
http://document.thinkphp.cn/manual_3_2.html#action_bind
url中的查询字符串可以作为方法的参数传进去
我们一般不这样做;
可以设置伪静态后缀
http://document.thinkphp.cn/manual_3_2.html#url_suffix
系统本身提供了一个不区分URL大小写的解决方案,可以通过配置简单实现。
其实不建议这么搞;
http://document.thinkphp.cn/manual_3_2.html#url_build
U('地址表达式',['参数'],['伪静态后缀'],['显示域名'])
地址表达式: [模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...
U('Admin/User/select') // 生成Admin模块的User控制器的select操作的URL地址
U('Blog/cate',array('cate_id'=>1,'status'=>1))
U('Blog/cate','cate_id=1&status=1','xml');
# ↓↓ 可以生成路由地址
'news/:id\d'=>'News/read'
U('/news/1'); // http://serverName/index.php/Home/news/1
# ↓↓ 支持域名
U('Blog/read@blog.thinkphp.cn','id=1');
# ↓↓支持描点;
U('Blog/read#comment?id=1');
http://document.thinkphp.cn/manual_3_2.html#ajax_return
http://document.thinkphp.cn/manual_3_2.html#page_jump_redirect
http://document.thinkphp.cn/manual_3_2.html#input_var
http://document.thinkphp.cn/manual_3_2.html#request_method
http://document.thinkphp.cn/manual_3_2.html#empty_action
http://document.thinkphp.cn/manual_3_2.html#empty_controller
3.2.2版本开始支持插件控制器的调用
http://document.thinkphp.cn/manual_3_2.html#addon_controller
把操作绑定到一个类当中的run方法来运行;
http://document.thinkphp.cn/manual_3_2.html#action_bind_class