2014-01-15 65 views
2

我想從dbix :: class結果集中構建一個樹狀的嵌套數據結構。問題是,當涉及到超過1個更深一層的元素,我得到異常:子程序返回空字符串而不是哈希引用

不能使用字符串(「」)作爲HASH裁判而「嚴格裁判」在使用中 /家/ ROMEL /應用/ MyApp的/腳本/../ LIB/MyApp的/ Products.pm線38

的代碼包含兩個子程序:使用Data ::打印機

sub _findparent { 

my ($tree, $pid) = @_; 

    if (my ($parent) = grep { $_->{'id'} == $pid } @$tree) { 
     say "found parent $parent->{'id'} = $pid ($parent->{'name'})"; 
     $parent->{'children'} = [] if (ref $parent->{'children'} ne 'ARRAY'); 
     return $parent; 
    } else { 
     for my $i (@$tree) { 
      say "traversing $i->{'name'} $i->{'id'}"; 
      _findparent($i->{'children'}, $pid) if (ref $i->{'children'} eq 'ARRAY');| 
     } 
    } 
} 

sub index { 
    my $self = shift; 

    my @data = $self->db->resultset('Category')->search(); 

    my @tree; 

    for my $i (@data) { 
     my $i = $i->get_column_data; 


     if (my $parent_id = $i->{'parent_id'}) { 

      say "--- $i->{'name'} has parent (id $parent_id), searching"; 

      #if (my $parent = _findparent(\@tree, $parent_id)) { 
      # push ($parent->{'children'}, $i); 
      #} 

      push (_findparent(\@tree, $parent_id)->{'children'}, $i); 
     } else { 
      $i->{'children'} = []; 
      push (@tree, $i); 
      say "adding \"$i->{name}\" to tree as root"; 
     } 
    } 

    $self->render(menudata => [@tree]); 
} 

的@tree傾倒:

[ 
    [0] { 
     children  [ 
      [0] { 
       children  [], 
       created_on undef, 
       id   2, 
       modified_on undef, 
       name   "children 1 level", 
       parent_id  1, 
       position  undef, 
       user_id  undef 
      } 
     ], 
     created_on undef, 
     id   1, 
     modified_on undef, 
     name   "parent category one", 
     parent_id  undef, 
     position  undef, 
     user_id  undef 
    }, 
    [1] { 
     children  [ 
      [0] { 
       children  [], 
       created_on undef, 
       id   4, 
       modified_on undef, 
       name   "children 1 level 2", 
       parent_id  3, 
       position  undef, 
       user_id  undef 
      }, 
      [1] { 
       children  [], 
       created_on undef, 
       id   5, 
       modified_on undef, 
       name   "children 1 level 3", 
       parent_id  3, 
       position  undef, 
       user_id  undef 
      }, 
      [2] { 
       created_on undef, 
       id   12, 
       modified_on undef, 
       name   "children 1 level 4", 
       parent_id  3, 
       position  undef, 
       user_id  undef 
      } 
     ], 
     created_on undef, 
     id   3, 
     modified_on undef, 
     name   "parent category two", 
     parent_id  undef, 
     position  undef, 
     user_id  undef 
    } 
] 

最後的表結構:38

+-------------+-------------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+-------------+-------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
| name  | varchar(45) | YES |  | NULL |    | 
| user_id  | int(11)  | YES | MUL | NULL |    | 
| created_on | datetime | YES |  | NULL |    | 
| modified_on | datetime | YES |  | NULL |    | 
| position | varchar(45) | YES |  | NULL |    | 
| parent_id | varchar(45) | YES |  | NULL |    | 
+-------------+-------------+------+-----+---------+----------------+ 

線是嵌套的元素不止一層深的一個

push (_findparent(\@tree, $parent_id)->{'children'}, $i); 

所以_findparent不返回任何東西。

+2

您在'_findparent'的'else'分支中沒有顯式返回。在這種情況下找出你真正想要返回的東西,並將其明確。 – amon

+0

謝謝。但是如果我不想在那裏返回任何東西,只需使用grep更深一層執行另一個搜索? – romel

+2

當然可以:您想要返回適當的父節點。您也不處理樹中任何位置不存在該ID的情況。你有使用樹數據結構和遞歸函數的經驗嗎? – amon

回答

3

你的問題是,_findparent不是return一個可用的值,如果在第一級找不到ID。讓我們來看看else分支:

sub _findparent { 

    my ($tree, $pid) = @_; 

    if (my ($parent) = grep { $_->{'id'} == $pid } @$tree) { 
     ... 
    } else { 
     for my $i (@$tree) { 
      say "traversing $i->{'name'} $i->{'id'}"; 
      _findparent($i->{'children'}, $pid) if (ref $i->{'children'} eq 'ARRAY');| 
     } 
    } 
} 

如果不使用顯式return,返回最後一條語句的值 - 在這裏一環。循環沒有有用的返回值,所以你不應該使用它。

相反,通過對一個有用的返回值,從一個較低的水平:

sub _findparent { 

    my ($tree, $pid) = @_; 

    if (my ($parent) = grep { $_->{'id'} == $pid } @$tree) { 
     ... 
    } else { 
     for my $i (@$tree) { 
      say "traversing $i->{'name'} $i->{'id'}"; 
      next if not ref $i->{children} eq 'ARRAY'; 
      my $parent = _findparent($i->{'children'}, $pid); 
      return $parent if defined $result; 
     } 
     return; # return undef if nothing was found 
    } 
} 

... 
# put the return value in a variable 
my $parent = _findparent(...); 
# check if the operation was successful 
if (not defined $parent) { 
    die "Tried to find the parent for $id, but there was no matching parent"; 
} 
# if so use the value 
push @$parent, ...; 

支票可以縮寫爲:

my $parent = _findparent(...) // die "..."; 

它使用//定義-或運算符。

相關問題