我将这段代码作为控制器中foreach循环的一部分:
my $gr = My::Model::Group->new(id => $gra->gr_id);
$gra = My::Model::Group::Admin->new(id => $gra->id);
push(@$groups, {$gr => $gra});
在@ $ groups数组中,我想存储匿名哈希,其中key元素是group对象,value元素是该group对象的admin。然后在模板中我想显示管理员可以登录的不同组的列表,为此我有这个代码:
[%- FOREACH gr IN groups -%]
<li><input type="radio" name="group" value="[% gr.id %]">[% gr.name %]</input></li>
[%- END -%]
我知道p IN合作伙伴不对,但是要向您展示我想要实现的目标。有关模板代码的任何建议吗?
答案 0 :(得分:3)
您需要重新修改代码才能实现这一目标。
Perl哈希中的键是字符串,而不是标量。使用非字符串作为哈希中的键的任何东西(例如,$gr
中的{ $gr => $gra }
将导致它被字符串化,就像您将其插入字符串或打印它一样除非你明确重载了""
对象上的My::Model::Group
运算符,否则该键最终将被存储为以下行的文字字符串:
"My::Model::Group=HASH(0x1234567890)"
此字符串无法转换回原始对象 - 事实上,原始对象一旦超出范围就可能被垃圾收集,因此它根本不存在。
考虑将该对存储为数组引用,例如
push @$groups, [$gr, $gra];
答案 1 :(得分:3)
duskwuff already explains in their answer您无法将对象用作哈希键,因为它们被序列化并且您将失去对象。我的答案建立在此基础上。
让我们假设你有一个数组数组,其中每个内部数组都包含一对对象。我已经创建了Moo课程来说明。
package My::Model::Group;
use Moo;
has [qw/id name/] => ( is => 'ro' );
package My::Model::Group::Admin;
use Moo;
has [qw/id name/] => ( is => 'ro' );
package main;
my $groups = [
[
My::Model::Group->new( id => 1, name => 'group1' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
[
My::Model::Group->new( id => 2, name => 'group2' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
[
My::Model::Group->new( id => 3, name => 'group3' ) =>
My::Model::Group::Admin->new( id => 1, name => 'bar' )
],
[
My::Model::Group->new( id => 4, name => 'group4' ) =>
My::Model::Group::Admin->new( id => 1, name => 'foo' )
],
];
有四对。两名管理员,四组。其中三个组属于 foo admin,另一个属于 bar 。现在让我们看看模板。
use Template;
my $tt = Template->new();
$tt->process( \*DATA, { groups => $groups }, \my $output )
or die $tt->error;
print $output;
__DATA__
[%- FOREACH item IN groups -%]
[%- DEFAULT by_admin.${item.1.name} = [] -%]
[%- by_admin.${item.1.name}.push(item.0) -%]
[%- END -%]
[%- FOREACH admin IN by_admin.keys.sort -%]
[%- FOREACH group IN by_admin.$admin -%]
[%- admin %] -> [% group.id %]
[%- END -%]
[%- END -%]
相关部分显然是DATA
部分。我们需要将数组数据结构重组为具有管理员的哈希,然后将每个组分类到一个管理槽中。
我们不需要创建by_admin
变量。它将全局隐式创建。但我们确实需要为$by_admin->{$item[0]->name}
设置一个默认值(我现在使用Perl语法,以便更容易理解)。似乎Template Toolkit不知道autovivification,而the DEFAULT
keyword与//=
assignment operator in Perl类似。
我们可以item
将item.1.name
的第一个元素放入我们刚刚创建的数组引用中(如果它还没有存在),并使用键{{1}在哈希引用元素中} by_name
。
一旦我们做好准备,其余的只是一个简单的循环。我们迭代by_admin
的{{3}} push
,然后迭代该键后面的数组引用。
这是输出:
bar -> 3
foo -> 1
foo -> 2
foo -> 4
不是在模板中进行预处理,而是在控制器中进行预处理是有意义的。作为普通的Perl代码,它应该更容易阅读。
my %by_admin;
for my $group (@$groups) {
push @{ $by_admin{ $group->[1]{name} } }, $group->[0];
}
请注意,为简洁起见,我省略了use strict
和use warnings
。