2

我有一个 TT 插件,它可以处理微不足道的唯一 ID:

sub get_unique_uid_tt {
  my ( $classname, $o ) = @_;

  my %h;

  foreach my $item ( @{$o} ) {
    unless ( exists $h{ $item->id } ) {
      $h{ $item->id } = 1;
    }
  }

  return keys %h;
}

模板调用很简单:

[% Namespace.get_unique_uid_tt( data.users ) %]

并且“数据”是一个 RDB 对象,用户是它的关系之一。我已经验证“.users”直接在 Perl 中返回一个列表,无论关系有一个还是多个元素。

但是,似乎 TT 返回单个元素列表的元素,而正确返回多个元素的列表。

我查了一下,发现你可以用“.list”强制列表上下文:

[% Namespace.get_unique_uid_tt( data.users.list ) %]

正如 Data::Dumper 所揭示的,这不适用于单元素列表:

$VAR1 = [
      {
        'value' => 1,
        'key' => '__xrdbopriv_in_db'
      },
      {
        'value' => bless(
         ... snip ...
         ),
        'key' => 'db'
      },
      {
        'value' => '1',
        'key' => 'id'
      }
];

而不是预期的

 $VAR1 = [
     bless( {
             '__xrdbopriv_in_db' => 1,
             'id' => '1',
             'db' => ... snip ...
     }, 'DataClass' )
 ];

在 TT 中是否有任何其他简单的方法来获取对象列表,即使是在单元素列表上?(一种方法是重写函数,但最好不要重写)

4

2 回答 2

6

在 TT 邮件列表中找到了这个:

http://lists.template-toolkit.org/pipermail/templates/2009-December/011061.html

似乎 TT 的“.list”通常无法将对象转换为列表,而不仅仅是 RDBO。

建议是做一个 vmethod:

$Template::Stash::LIST_OPS->{ as_list } = sub {
   return ref( $_[0] ) eq 'ARRAY' ? shift : [shift];
};

我将此添加到我的上下文对象中(相同的想法):

$context->define_vmethod(
    'list',
    'as_list',
    sub {
        return ref( $_[0] ) eq 'ARRAY' ? shift : [shift];
    },
);
于 2010-01-06T22:00:00.927 回答
3

这不是你所追求的,但你能改变 TT 插件来处理列表和单个项目吗?

sub get_unique_uid_tt {
  my ( $classname, $o ) = @_;

  my %h;

  if (ref $o eq 'ARRAY') {
    foreach my $item ( @{$o} ) {
      unless ( exists $h{ $item->id } ) {
        $h{ $item->id } = 1;
      }
    }
  }
  else {
      return ($o->id);
  }

  return keys %h;
}
于 2010-01-06T22:00:25.920 回答