TP细节总结1
TP细节总结1
- 接收参数尽量使用I函数,代替post、get 更安全!
I('变量类型.变量名/修饰符',['默认值'],['过滤方法'],['额外数据源'])
- 在where 条件处尽量使用 array方式where(array('id'=>$id))
- 在使用myql 进行查询时,若只有一条数据,用limit 1 做限制,加快查询
- 随机挑一条记录
// 千万不要这样做:
$r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1");
// 这要会更好:
$r = mysql_query("SELECT count(*) FROM user");
$d = mysql_fetch_row($r);
$rand = mt_rand(0,$d[0] - 1);
$r = mysql_query("SELECT username FROM user LIMIT $rand, 1");
- 关联操作
- 关联模型
- 关联关系
通常我们所说的关联关系包括下面三种:
一对一关联
:ONE_TO_ONE,包括HAS_ONE 和
BELONGS_TO一对多关联
:ONE_TO_MANY,包括HAS_MANY 和
BELONGS_TO多对多关联
:MANY_TO_MANY关联关系必然有一个参照表,例如:
- 有一个员工档案管理系统项目,这个项目要包括下面的一些数据表:基本信息表、员工档案表、部门表、项目组表、银行卡表(用来记录员工的银行卡资料)。
- 这些数据表之间存在一定的关联关系,我们以员工基本信息表为参照来分析和其他表之间的关联:
- 每个员工必然有对应的员工档案资料,所以属于HAS_ONE关联;
- 每个员工必须属于某个部门,所以属于BELONGS_TO关联;
- 每个员工可以有多个银行卡,但是每张银行卡只可能属于一个员工,因此属于HAS_MANY关联;
- 每个员工可以同时在多个项目组,每个项目组同时有多个员工,因此属于MANY_TO_MANY关联;
- 分析清楚数据表之前的关联关系后,我们才可以进行关联定义和关联操作。
- 关联定义
ThinkPHP可以很轻松的完成数据表的关联CURD操作,目前支持的关联关系包括下面四种:
HAS_ONE、BELONGS_TO、HAS_MANY和MANY_TO_MANY。
一个模型根据业务模型的复杂程度可以同时定义多个关联,不受限制,所有的关联定义都统一在模型类的 $_link 成员变量里面定义,并且可以支持动态定义。要支持关联操作,模型类必须继承Think\Model\RelationModel类,关联定义的格式是:
namespace
Home\Model;use
Think\Model\RelationModel;class
UserModel
extends
RelationModel{protected $_link = array(
'关联1' => array(
'关联属性1' => '定义',
'关联属性N' => '定义',
),
'关联2' => array(
'关联属性1' => '定义',
'关联属性N' => '定义',
),
'关联3' => HAS_ONE, // 快捷定义
...
);
}
下面我们首先来分析下各个关联方式的定义:
- HAS_ONE
HAS_ONE关联表示当前模型拥有一个子对象,例如,每个员工都有一个人事档案。我们可以建立一个用户模型UserModel,并且添加如下关联定义:
namespace
Home\Model;use
Think\Model\RelationModel;class
UserModel
extends
RelationModel{protected $_link = array(
'Profile'=> self::HAS_ONE,
);
}
上面是最简单的方式,表示其遵循了系统内置的数据库规范,完整的定义方式是:
namespace
Home\Model;use
Think\Model\RelationModel;class
UserModel
extends
RelationModel{protected $_link = array(
'Profile'=>array(
'mapping_type' => self::HAS_ONE,
'class_name' => 'Profile',
// 定义更多的关联属性
……
),
);
}
关联HAS_ONE支持的关联属性有:
mapping_type :关联类型
这个在HAS_ONE 关联里面必须使用HAS_ONE 常量定义。
class_name :要关联的模型类名
例如,class_name 定义为Profile的话则表示和另外的Profile模型类关联,这个Profile模型类是无需定义的,系统会自动定位到相关的数据表进行关联。
mapping_name :关联的映射名称,用于获取数据用
该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。如果mapping_name没有定义的话,会取class_name的定义作为mapping_name。如果class_name也没有定义,则以数组的索引作为mapping_name。
foreign_key :
关联的外键名称外键的默认规则是当前数据对象名称_id,例如: UserModel对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置)
那么think_user表的外键默认为 user_id,如果不是,就必须在定义关联的时候显式定义 foreign_key 。condition :
关联条件关联查询的时候会自动带上外键的值,如果有额外的查询条件,可以通过定义关联的condition属性。
mapping_fields :
关联要查询的字段默认情况下,关联查询的关联数据是关联表的全部字段,如果只是需要查询个别字段,可以定义关联的mapping_fields属性。
as_fields :直接把关联的字段值映射成数据对象中的某个字段
这个特性是ONE_TO_ONE 关联特有的,可以直接把关联数据映射到数据对象中,而不是作为一个关联数据。当关联数据的字段名和当前数据对象的字段名称有冲突时,还可以使用映射定义。
- BELONGS_TO
Belongs_to 关联表示当前模型从属于另外一个父对象,例如每个用户都属于一个部门。我们可以做如下关联定义。
'Dept' => self::BELONGS_TO
完整方式定义为:
'Dept' => array(
'mapping_type' => self::BELONGS_TO,
'class_name' => 'Dept',
'foreign_key' => 'userId',
'mapping_name' => 'dept',
// 定义更多的关联属性
……
),
关联BELONGS_TO定义支持的关联属性有:
属性
描述
class_name
要关联的模型类名
mapping_name
关联的映射名称,用于获取数据用
该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。foreign_key
关联的外键名称
mapping_fields
关联要查询的字段
condition
关联条件
parent_key
自引用关联的关联字段
默认为parent_id 自引用关联是一种比较特殊的关联,也就是关联表就是当前表。as_fields
直接把关联的字段值映射成数据对象中的某个字段
- HAS_MANY
HAS_MANY 关联表示当前模型拥有多个子对象,例如每个用户有多篇文章,我们可以这样来定义:
'Article' => self::HAS_MANY
完整定义方式为:
'Article' => array(
'mapping_type' => self::HAS_MANY,
'class_name' => 'Article',
'foreign_key' => 'userId',
'mapping_name' => 'articles',
'mapping_order' => 'create_time desc',
// 定义更多的关联属性
……
),
关联HAS_MANY定义支持的关联属性有:
属性
描述
class_name
要关联的模型类名
mapping_name
关联的映射名称,用于获取数据用
该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。foreign_key
关联的外键名称
parent_key
自引用关联的关联字段
默认为parent_idcondition
关联条件
关联查询的时候会自动带上外键的值,如果有额外的查询条件,可以通过定义关联的condition属性。mapping_fields
关联要查询的字段
默认情况下,关联查询的关联数据是关联表的全部字段,如果只是需要查询个别字段,可以定义关联的mapping_fields属性。mapping_limit
关联要返回的记录数目
mapping_order
关联查询的排序
外键的默认规则是当前数据对象名称_id,例如:UserModel对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置)
那么think_user表的外键默认为 user_id,如果不是,就必须在定义关联的时候定义 foreign_key 。 - MANY_TO_MANY
MANY_TO_MANY 关联表示当前模型可以属于多个对象,而父对象则可能包含有多个子对象,通常两者之间需要一个中间表类约束和关联。例如每个用户可以属于多个组,每个组可以有多个用户:
'Group' => self::MANY_TO_MANY
完整定义方式为:
'Group' => array(
'mapping_type' => self::MANY_TO_MANY,
'class_name' => 'Group',
'mapping_name' => 'groups',
'foreign_key' => 'userId',
'relation_foreign_key' => 'groupId',
'relation_table' => 'think_group_user'
//此处应显式定义中间表名称,且不能使用C函数读取表前缀)
MANY_TO_MANY支持的关联属性定义有:
属性
描述
class_name
要关联的模型类名
mapping_name
关联的映射名称,用于获取数据用
该名称不要和当前模型的字段有重复,否则会导致关联数据获取的冲突。foreign_key
关联的外键名称
外键的默认规则是当前数据对象名称_idrelation_foreign_key
关联表的外键名称
默认的关联表的外键名称是表名_idmapping_limit
关联要返回的记录数目
mapping_order
关联查询的排序
relation_table
多对多的中间关联表名称
多对多的中间表默认表规则是:数据表前缀_关联操作的主表名_关联表名
如果think_user 和 think_group 存在一个对应的中间表,默认的表名应该是
如果是由group来操作关联表,中间表应该是 think_group_user,如果是从user表来操作,那么应该是think_user_group,也就是说,多对多关联的设置,必须有一个Model类里面需要显式定义中间表,否则双向操作会出错。
中间表无需另外的id主键(但是这并不影响中间表的操作),通常只是由 user_id 和 group_id 构成。
默认会通过当前模型的getRelationTableName方法来自动获取,如果当前模型是User,关联模型是Group,那么关联表的名称也就是使用 user_group这样的格式,如果不是默认规则,需要指定relation_table属性。3.2.2版本开始,relation_table定义支持简化写法,例如:
'relation_table'=>'__USER_GROUP__'
- 关联查询
由于性能问题,新版取消了自动关联查询机制,而统一使用relation方法进行关联操作,relation方法不但可以启用关联还可以控制局部关联操作,实现了关联操作一切尽在掌握之中。
$User
= D("User");$user
);输出$user结果可能是类似于下面的数据:
array(
,
'account' => 'ThinkPHP',
'password' => '123456',
'Profile' => array(
'email' => 'liu21st@gmail.com',
'nickname' => '流年',
),
)
我们可以看到,用户的关联数据已经被映射到数据对象的属性里面了。其中Profile就是关联定义的mapping_name属性。
如果我们按照下面的方式定义了as_fields属性的话,
protected $_link = array(
'Profile'=>array(
'mapping_type' => self::HAS_ONE,
'class_name' => 'Profile',
'foreign_key' => 'userId',
'as_fields' => 'email,nickname',
),
);
查询的结果就变成了下面的结果
array(
,
'account' => 'ThinkPHP',
'password' => 'name',
'email' => 'liu21st@gmail.com',
'nickname' => '流年',
)
email和nickname两个字段已经作为user数据对象的字段来显示了。
如果关联数据的字段名和当前数据对象的字段有冲突的话,怎么解决呢?
我们可以用下面的方式来变化下定义:
'as_fields' => 'email,nickname:username',
表示关联表的nickname字段映射成当前数据对象的username字段。
默认会把所有定义的关联数据都查询出来,有时候我们并不希望这样,就可以给relation方法传入参数来控制要关联查询的。
$User
= D("User");$user
);关联查询一样可以支持select方法,如果要查询多个数据,并同时获取相应的关联数据,可以改成:
$User = D("User");
$list = $User->relation(true)->Select();
如果希望在完成的查询基础之上
再进行关联数据的查询,可以使用$User = D("User");
);
//
表示对当前查询的数据对象进行关联数据获取$profile = $User->relationGet("Profile");
事实上,除了当前的参考模型User外,其他的关联模型是不需要创建的。
- 关联操作
除了关联查询外,系统也支持关联数据的自动写入、更新和删除
- 关联写入
$User = D("User");
$data = array();
$data["account"] = "ThinkPHP";
$data["password"] = "123456";
$data["Profile"] = array(
'email' =>'liu21st@gmail.com',
'nickname' =>'流年',
);
$result = $User->relation(true)->add($data);
这样就会自动写入关联的Profile数据。
同样,可以使用参数来控制要关联写入的数据:
$result = $User->relation("Profile")->add($data);
当MANY_TO_MANY时,不建议使用关联插入。
- 关联更新
数据的关联更新和关联写入类似
$User = D("User");
$data["account"] = "ThinkPHP";
$data["password"] = "123456";
$data["Profile"] = array(
'email' =>'liu21st@gmail.com',
'nickname' =>'流年',
);
$result = $User-> relation())->save($data);
Relation(true)会关联保存User模型定义的所有关联数据,如果只需要关联保存部分数据,可以使用:
$result = $User->relation("Profile")->save($data);
这样就只会同时更新关联的Profile数据。
关联保存的规则:
HAS_ONE:
关联数据的更新直接赋值HAS_MANY:
的关联数据如果传入主键的值
则表示更新
否则就表示新增MANY_TO_MANY:
的数据更新是删除之前的数据后重新写入 - 关联删除
的记录的同时删除关联数据
$result = $User->relation(true)->delete("3");
// 如果只需要关联删除部分数据,可以使用
$result = $User->relation("Profile")->delete("3");
2017/6/29 4:55 PM
TP细节总结1的更多相关文章
- Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)
Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...
- 从TP、FP、TN、FN到ROC曲线、miss rate、行人检测评估
从TP.FP.TN.FN到ROC曲线.miss rate.行人检测评估 想要在行人检测的evaluation阶段要计算miss rate,就要从True Positive Rate讲起:miss ra ...
- 深度解密HTTP通信细节
目录 HTTP报文截获 背景介绍 抓包 mac本地 远程docker 请求 && 分析 关闭服务进程 关闭docker 重启docker 正常请求 HTTP协议分析 整体介绍 编码 M ...
- 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)
orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...
- TP分页
①在Home下设置Publics文件夹或在thinkPHP下library的vender 把page.class.php 考贝进入 ②通过new 实例化方式调用 $page=new \Home\Pub ...
- 【2019.10.7 CCF-CSP-2019模拟赛 T2】绝对值(abs)(线段树细节题)
找规律 设\(p_i=a_{i+1}-a_i\),则答案就是\(\sum_{i=1}^{n-1}p_i\). 考虑若将\(a_i\)加上\(x\)(边界情况特殊考虑),就相当于是将\(p_{i-1}\ ...
- Tapdata Cloud 2.1.5来啦:新增支持Amazon RDS数据库,错误日志查询更便捷,Agent部署细节再优化
需求持续更新,优化一刻不停--Tapdata Cloud 2.1.5 来啦! 最新发布的版本中,数据连接再上新,同时新增任务报错相关信息快速查询入口,开始支持 JVM 参数自定义设置. 更 ...
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- vue2.0实践的一些细节
最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...
随机推荐
- selenium 多表单切换处理(iframe/frame)
在web应用中,前台网页的设计一般会用到iframe/frame表单嵌套页面的应用.简单的就是一个页面签嵌套多个HEML/JSP文件.selenium webdriver 只能在同一页面识别定位元素 ...
- Java写到.txt文件,如何实现换行
http://blog.csdn.net/liangoo7/article/details/7882773 java中写.txt文件,实现换行的几种方法: 1.使用java中的转义符"\r\ ...
- Nodejs调用Aras Innovator服务,处理AML并返回AML
公司已经布署了Aras Innovator服务器,如果需要与Aras Innovator进行交互,需要进行自主开发程序,例如使用C#.VB.Java等,都是可以与它进行交互的 C#:调用Aras In ...
- 【转-记】mysql总结
1 | 查询所有数据 select * from Info 查所有数据 select Code,Name from Info 查特定列 2 | 根据条件查 select * from Inf ...
- [jquery] 删除文章的时候弹出确认窗口
[<a href="{:U(GROUP_NAME . '/Category/delCate')}/id/{$v.id}" onclick='return del();'> ...
- UVA 10382.Watering Grass-贪心
10382 - Watering Grass Time limit: 3.000 seconds n sprinklers are installed in a horizontal strip of ...
- Node 入门<1>
1. Node JavaScript web服务器框架,主要特点:事件驱动,异步 I/O,强制不共享任何资源的单线程,单进程系统. 每一个node进程都构成网络应用中的一个节点. ...
- 详细的KVO总结,包括基本改变,使用案例,注意点.看我就够了!
概述 KVO全称Key-Value-Observing,也叫键值监听,是一种观察者设计模式.提供了一种机制,当指定的对象的属性被修改后,对象就会收到一个通知.也就是说每次指定的被观察的对象的属性被修改 ...
- [BZOJ 1913] signaling 信号覆盖
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1913 TIP:(注意,这题只能输出6位才能过,7位都不行wtf?) Algorithm: ...
- [SHOI2009] 交通网络
简单最短路计数. #include<bits/stdc++.h> #define ll long long using namespace std; #define D double co ...