2017-05-03 5 views
0

내 컨트롤러에서 foreach 루프의 일환으로이 코드 조각이있는 템플릿 Toolkit에 익명의 해시 배열 항목 :액세스 펄

my $gr = My::Model::Group->new(id => $gra->gr_id); 
$gra = My::Model::Group::Admin->new(id => $gra->id); 
push(@$groups, {$gr => $gra}); 

이 @ $ 그룹 배열에서 나는 익명 저장할 키 요소가 그룹 객체이고 값 요소가 해당 그룹 객체의 관리자 인 해시. 그런 다음 템플릿에 나는 내가이 코드가, 관리자가 로그인 할 수있는 다른 그룹의 목록을 보여주고 싶은 : 나는 파트너의 페이지를 잘 작성하지 않습니다하지만 당신을 보여줄 것을 알고

[%- FOREACH gr IN groups -%] 
    <li><input type="radio" name="group" value="[% gr.id %]">[% gr.name %]</input></li> 
[%- END -%] 

무엇 나는 성취하고 싶다. 템플릿 코드에 대한 제안 사항이 있습니까?

+0

'FOREACH item IN list'가 정확합니다. 하지만 재결성하고 싶지, 그렇지? 이것은 Excel의 피벗과 같습니다. 당신은'{1 => 'foo', 2 => 'bar', 3 => 'foo'}'와 같은 것을 가지고 있고 사용자'foo'가'1, 3'이고'bar'는' 2 '. 이해 했니? – simbabque

+0

네, 맞습니다. 당신은 절대적으로 정확합니다 – Albert

+0

관리자가 두 명입니까? 아직 예상되는 출력을 이해하지 못합니다. – simbabque

답변

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') 
    ], 
]; 

네 쌍이 있습니다. 두 명의 관리자, 네 개의 그룹. 그룹 중 3 개는 foo admin에 속하고 1 개는 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 구문을 사용하고 있습니다). 템플릿 툴킷이 autovivification을 모르는 것 같고 the DEFAULT keyword//= assignment operator in Perl과 비슷합니다.

우리가 할 수있는 다음 push (아직 존재하지 않은 경우) 우리가 by_name 내부의 키 item.1.name와 해시 심판 요소 내에 생성 된 배열 심판에 item의 첫 번째 요소입니다.

일단 준비가 끝나면 나머지는 단순한 루프 일뿐입니다. sortedkeysby_admin으로 반복 한 다음 해당 키 뒤에있는 배열 참조를 반복합니다. 하지만 컨트롤러 대신, 템플릿에없는 전처리를 수행하는 감각을 만들 것

bar -> 3 
foo -> 1 
foo -> 2 
foo -> 4 

:

여기에 출력합니다. 보통의 Perl 코드처럼 읽기 쉽습니다. 나는 간결 use strictuse warnings을 생략 한

my %by_admin; 
for my $group (@$groups) { 
    push @{ $by_admin{ $group->[1]{name} } }, $group->[0]; 
} 

참고.

+0

을 얻었습니다. 고마워요! 당신들은 내 하루를 만들었습니다 – Albert

+0

@Albert 정말 중요한 부분은'DEFAULT'입니다. 그게 알아내는 데 시간이 좀 걸렸어. – simbabque

+1

언급했듯이 이것은 Perl (TT 아님)에서 가장 잘 수행되므로 Perl 코드를 추가했습니다. – ikegami

3

이 작업을 수행하려면 코드를 크게 재 작성해야합니다.

Perl 해시의 키는 문자열이며 스칼라는 아닙니다. 해시에서 문자열이 아닌 키를 문자열로 사용하면 (예 : $gr 표현식이 { $gr => $gra } 인 경우 문자열로 삽입하거나 인쇄 한 것처럼 캐릭터 라인이 지정됩니다.) 명시 적으로 오버플로하지 않는 한 ""My::Model::Group 개체에 대한 연산자, 끝날 키가의 라인을 따라 리터럴 문자열로 저장되는 :

"My::Model::Group=HASH(0x1234567890)" 

이 문자열은 원래 오브젝트로 변환 할 수 없습니다 - 사실, 원래 목적은 아마도 쓰레기했다 - 범위를 벗어나 자마자 수집되므로 더 이상 존재하지 않습니다.

쌍을 배열로 저장하는 것을 고려하십시오. 대신 참조 예 : 그들이 직렬화 얻을 당신이 해시 키와 같은 개체를 사용할 수없고 객체 다움을 잃게됩니다

push @$groups, [$gr, $gra]; 
+0

괜찮 았는데, 어떻게 id $ gr에있는 템플릿에 액세스 할 수 있습니까? 코드의 스 니펫으로 – Albert