TP细节总结1

  1. 接收参数尽量使用I函数,代替post、get 更安全!

    I('变量类型.变量名/修饰符',['默认值'],['过滤方法'],['额外数据源'])

  2. 在where 条件处尽量使用 array方式where(array('id'=>$id))
  3. 在使用myql 进行查询时,若只有一条数据,用limit 1 做限制,加快查询
  4. 随机挑一条记录

// 千万不要这样做:

$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");

  1. 关联操作
  1. 关联模型
  2. 关联关系

    通常我们所说的关联关系包括下面三种:

    一对一关联
    :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关联;
  • 分析清楚数据表之前的关联关系后,我们才可以进行关联定义和关联操作。
  1. 关联定义

    ThinkPHP可以很轻松的完成数据表的关联CURD操作,目前支持的关联关系包括下面四种:

    HAS_ONEBELONGS_TOHAS_MANYMANY_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, // 快捷定义

    ...

    );

    }

    下面我们首先来分析下各个关联方式的定义:

  2. 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 关联特有的,可以直接把关联数据映射到数据对象中,而不是作为一个关联数据。当关联数据的字段名和当前数据对象的字段名称有冲突时,还可以使用映射定义。

  3. 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

    直接把关联的字段值映射成数据对象中的某个字段

  4. 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_id

    condition

    关联条件
    关联查询的时候会自动带上外键的值,如果有额外的查询条件,可以通过定义关联的condition属性。

    mapping_fields

    关联要查询的字段
    默认情况下,关联查询的关联数据是关联表的全部字段,如果只是需要查询个别字段,可以定义关联的mapping_fields属性。

    mapping_limit

    关联要返回的记录数目

    mapping_order

    关联查询的排序

    外键的默认规则是当前数据对象名称_id,例如:UserModel对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置)
    那么think_user表的外键默认为 user_id,如果不是,就必须在定义关联的时候定义 foreign_key 。

  5. 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

    关联的外键名称
    外键的默认规则是当前数据对象名称_id

    relation_foreign_key

    关联表的外键名称
    默认的关联表的外键名称是表名_id

    mapping_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__'

  6. 关联查询

    由于性能问题,新版取消了自动关联查询机制,而统一使用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外,其他的关联模型是不需要创建的。

  7. 关联操作

    除了关联查询外,系统也支持关联数据的自动写入、更新和删除

  8. 关联写入

    $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时,不建议使用关联插入。

  9. 关联更新

    数据的关联更新和关联写入类似

    $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
    的数据更新是删除之前的数据后重新写入

  10. 关联删除

    的记录的同时删除关联数据

    $result = $User->relation(true)->delete("3");

    // 如果只需要关联删除部分数据,可以使用

    $result = $User->relation("Profile")->delete("3");

     

    2017/6/29 4:55 PM

TP细节总结1的更多相关文章

  1. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  2. 从TP、FP、TN、FN到ROC曲线、miss rate、行人检测评估

    从TP.FP.TN.FN到ROC曲线.miss rate.行人检测评估 想要在行人检测的evaluation阶段要计算miss rate,就要从True Positive Rate讲起:miss ra ...

  3. 深度解密HTTP通信细节

    目录 HTTP报文截获 背景介绍 抓包 mac本地 远程docker 请求 && 分析 关闭服务进程 关闭docker 重启docker 正常请求 HTTP协议分析 整体介绍 编码 M ...

  4. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

  5. TP分页

    ①在Home下设置Publics文件夹或在thinkPHP下library的vender 把page.class.php 考贝进入 ②通过new 实例化方式调用 $page=new \Home\Pub ...

  6. 【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}\ ...

  7. Tapdata Cloud 2.1.5来啦:新增支持Amazon RDS数据库,错误日志查询更便捷,Agent部署细节再优化

      需求持续更新,优化一刻不停--Tapdata Cloud 2.1.5 来啦!   最新发布的版本中,数据连接再上新,同时新增任务报错相关信息快速查询入口,开始支持 JVM 参数自定义设置.   更 ...

  8. Vue.js 和 MVVM 小细节

    MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...

  9. vue2.0实践的一些细节

    最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...

随机推荐

  1. 《Java编程思想》笔记 第十一章 持有对象

    1.保存对象引用 1.数组,数组具有固定大小 2.容器类,可自动调节大小 2.容器类 List  Set  Queue  Map 及常用的实现类 2.1 Collection (接口) 保存独立的元素 ...

  2. Django之模型ORM

    ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

  3. Delphi:对TNotifyEvent的理解

    type TNotifyEvent = procedure (Sender: TObject) of object; 在Delphi中事件也是一个类,类型就是事件类型,不同的事件属于不同的类.TNot ...

  4. [BZOJ2730][HNOI2012]矿场搭建 点双 割点

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2852  Solved: 1344[Submit][Stat ...

  5. 设置iSCSI的发起程序(客户端)(三)

    iSCSI 发起程序是一种用于同 iSCSI 目标器认证并访问服务器上共享的LUN的客户端.我们可以在本地挂载的硬盘上部署任何操作系统,只需要安装一个包来与目标器验证. 初始器客户端设置 功能 可以处 ...

  6. (十)MySQL日志

    1)日志种类 error log:错误日志 拍错 /var/log/mysqld.log \这是yum安装mysqld生成error默认目录 bin blog 二进制日志 备份 增量备份,记录DDL, ...

  7. mysql 查看表结构方法

    留给自己备查: mysql 导出为 csv 文件时如果直接使用导出命令是无法导出表结构的, 因此我们需要能够查询表结构的方法: 方法如下: 1.desc(描述)命令 desc tablename;de ...

  8. 训练指南 UVA - 11419(二分图最小覆盖数)

    layout: post title: 训练指南 UVA - 11419(二分图最小覆盖数) author: "luowentaoaa" catalog: true mathjax ...

  9. POJ 2082 Terrible Sets(单调栈)

    [题目链接] http://poj.org/problem?id=2082 [题目大意] 给出一些长方形下段对其后横向排列得到的图形,现在给你他们的高度, 求里面包含的最大长方形的面积 [题解] 我们 ...

  10. [NEERC2007][SHOI2008]Cactus Reloaded

    题目大意: 给你一个仙人掌,求图中相距最远的点对之间的距离. 思路: Tarjan+DP. 我们先考虑一个树的情况. 设用far[u]表示点u出发到其子树中叶子节点的最大距离,若v为u的子结点,很显然 ...