TP细节总结1

TP细节总结1

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

    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->relation(true)->find(1);

    输出$user结果可能是类似于下面的数据:

    array(

    'id' => 1,

    '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(

    'id' => 1,

    'account' => 'ThinkPHP',

    'password' => 'name',

    'email' => 'liu21st@gmail.com',

    'nickname' => '流年',

    )

    emailnickname两个字段已经作为user数据对象的字段来显示了。

    如果关联数据的字段名和当前数据对象的字段有冲突的话,怎么解决呢?

    我们可以用下面的方式来变化下定义:

    'as_fields' => 'email,nickname:username',

    表示关联表的nickname字段映射成当前数据对象的username字段。

    默认会把所有定义的关联数据都查询出来,有时候我们并不希望这样,就可以给relation方法传入参数来控制要关联查询的。

    $User = D("User");

    $user = $User->relation('Profile')->find(1);

    关联查询一样可以支持select方法,如果要查询多个数据,并同时获取相应的关联数据,可以改成:

    $User = D("User");

    $list = $User->relation(true)->Select();

    如果希望在完成的查询基础之上 再进行关联数据的查询,可以使用

    $User = D("User");

    $user = $User->find(1);

    // 表示对当前查询的数据对象进行关联数据获取

    $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(true)->where(array('id'=>3))->save($data);

    Relation(true)会关联保存User模型定义的所有关联数据,如果只需要关联保存部分数据,可以使用:

    $result = $User->relation("Profile")->save($data);

    这样就只会同时更新关联的Profile数据。

    关联保存的规则:

    HAS_ONE 关联数据的更新直接赋值

    HAS_MANY 的关联数据如果传入主键的值 则表示更新 否则就表示新增

    MANY_TO_MANY 的数据更新是删除之前的数据后重新写入

  10. 关联删除

    //删除用户ID3的记录的同时删除关联数据

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

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

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

     

    2017/6/29 4:55 PM

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值