为啥thinkphp中字段映射不起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥thinkphp中字段映射不起作用相关的知识,希望对你有一定的参考价值。
参考技术A Thinkphp的字段映射功能可以让你在表单中隐藏真正的数据表字段,而不用担心放弃自动创建表单对象的功能,假设我们的User表里面有username和email字段,我们需要映射成另外的字段,定义方式如下:Class
UserModel
extends
Model
protected
$_map
=
array(
'name'
=>'username',
//
把表单中name映射到数据表的username字段
'mail'
=>'email',
//
把表单中的mail映射到数据表的email字段
);
这样,在表单里面就可以直接使用name和mail名称作为表单数据提交了。在保存的时候会字段转换成定义的实际数据表字段。字段映射还可以支持对主键的映射。
如果我们需要把数据库中的数据显示在表单中,并且也支持字段映射的话,需要对查询的数据进行一下处理,处理方式是调用Model类的parseFieldsMap方法,例如:
//
实例化User模型
$User
=
M('User');
$data
=
$User->find(3);
这个时候取出的data数据包含的是实际的username和email字段,为了方便便表单输出,我们需要处理成字段映射显示在表单中,就需要使用下面的代码处理:
$data
=
$User->parseFieldsMap($data);
这样一来,data数据中就包含了name和mail字段数据了,而不再有username和email字段数据了。
4
为啥正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制]
【中文标题】为啥正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制]【英文标题】:Why does normal for loop allows assigning value to struct fields while for range doesn't work in Golang? [duplicate]为什么正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制] 【发布时间】:2020-08-19 16:13:36 【问题描述】:用于范围:
for _, acc := range accounts
accDetails, _ := repo.GetAccountDets(ctx, acc.number, acc.status)
acc.Details = *accDetails
上面那个不行。
但是,以下工作。
for i:=0; i < len(accounts); i++
accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
accounts[i].Details = *accDetails
这是为什么呢? 我认为在此处添加帐户结构详细信息没有任何价值
【问题讨论】:
第一个赋值给局部变量acc
。第二个分配给切片元素。 Change values while iterating 会回答你的问题吗?
@CeriseLimón 那么,有没有办法使用 for range 循环进行分配,或者根本没有办法?
for i, acc := range accounts .... accounts[i].Details = *accDetails
@CeriseLimón 你先回答了。如果你把它作为答案,我会选择它。
@sofs1 请注意,以下答案和一些重复项似乎暗示,通过遗漏,不可能在 range
循环中直接使用 value
来修改其内容, 仅当您处理非指针值时,这是正确的。如果您的accounts
slice/array/channel/map 包含指针,您可以通过迭代变量直接修改各个值,而无需使用索引。 play.golang.com/p/3FdQiyylxA6
【参考方案1】:
在for i,v:=range slice ...
形式的for 循环中,变量v
与其循环的元素具有相同的类型,并且每次迭代都将下一项的内容从切片/映射复制到v
。因此,如果v
是一个结构并且您为结构成员分配值,则这些成员永远不会被复制回从中复制它的切片中。
如果切片是指向结构的指针切片,则v
是指向结构的指针的副本,并且您对v
的成员所做的更改将反映在原始切片元素上。
解决此问题的一种方法是使用索引:
for i:=range accounts
accounts[i].Field=value
【讨论】:
【参考方案2】:我想说,这个问题超越了 Golang,它与底层数据结构或容器有关。在第二种情况下,您似乎已经知道容器“len(accounts)”的长度,因此它是一个可以按顺序访问的固定存储。不必总是如此。如果帐户是一个不断增加(或减少)的容器怎么办?你会如何取那个容器的长度。相反,您要问的只是“帐户”中的任何内容都可以给我。你打算怎么做?好吧,您设置了一个虚拟变量,它只允许访问或模仿容器的内容(因此带有它的所有属性或“结构字段”)。另外,它可以在后续代码中抛出,并适当考虑范围,用于“只读”目的。
【讨论】:
【参考方案3】:每当您在 for 循环中初始化变量时,该变量仅在局部范围内限定为 for 循环,在范围内您将在 acc 变量中创建元素的副本
for _, acc := range accounts
accDetails, _ := repo.GetAccountDets(ctx, acc.number, acc.status)
acc.Details = *accDetails
acc 只是 accounts 中元素的本地副本,如果您在 acc 中添加任何内容,它不会影响 accounts 切片。
但在你的另一个例子中..
for i:=0; i < len(accounts); i++
accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
accounts[i].Details = *accDetails
您没有为帐户中的元素制作本地副本,而是通过 accounts[i] 直接访问它们,它将更新 accounts 切片。
如果您仍想使用范围,那么您可以仅使用索引。
for i := range accounts
accDetails, _ := repo.GetAccountDets(ctx, accounts[i].number, accounts[i].status)
accounts[i].Details = *accDetails
【讨论】:
以上是关于为啥thinkphp中字段映射不起作用的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们不能在 TypeScript 类中定义一个 const 字段,为啥静态只读不起作用?
为啥具有 ISO 8601 值的日期时间字段在 iOS webkit 浏览器中不起作用?