为啥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 浏览器中不起作用?

为啥将外键字段添加到模型后 URL 不起作用?

为啥在与数组中的字段匹配时,mongoDB聚合中的查找中的管道不起作用?

为啥这种方式的 TCP 打孔不起作用?

为啥我的 IBAction 更改标签文本不起作用?