You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Dennis Stout <st...@stout.dyndns.org> on 2003/07/21 22:09:17 UTC

Values of an array..

I dunno if it's an array or a reference ot an array anymore, heh.

Whats happening, is instead of this thing pulling all 3 of my domains from a
database, it's pulling the first domain in the list as many times as I have
domains for.  So when I only had 2 domains in the db for myself, it listed
hte first twice.  I added a 3rd ot test the theory, and behold, I get hte
first one 3 times.

Here is some massive subroutinage..

sub post_search_form {
        my $state = shift;
        my %args = $state->{q};
        $state->{template} = 'generic.tmpl';
        $state->{title} = "User Search";
        my $blah = "";
        my $where;
        my %search;

        $search{USER} = $state->{q}{user} if $state->{q}{user};
        $search{ISP} = $state->{q}{isp} if $state->{q}{isp};
        $search{PWORD} = $state->{q}{pword} if $state->{q}{pword};
        if ($state->{q}{name}) {
                ($search{FIRST}, $search{LAST}) = split("
",$state->{q}{name});
        }
        $search{H_PHONE} = $search{W_PHONE} = $search{D_PHONE} =
$search{C_PHONE} = $state->{q}{phone} if $state->{q}{phone};
        $search{EMAIL1} = $search{EMAIL2} = $search{EMAIL3} =
$search{EMAIL4} = $state->{q}{email} if $state->{q}{email};
        $search{STATICIP} = $state->{q}{staticip} if $state->{q}{staticip};
        $search{DOMAIN} = $state->{q}{domain} if $state->{q}{domain};
        $search{ACCNUM} = $state->{q}{accnum} if $state->{q}{accnum};

        foreach (keys %search) {
                if ($_ eq "DOMAIN") {
                        $where .= "domain.$_ LIKE \"\%$search{$_}\%\" AND ";
                } elsif ($_ eq m/PHONE/) {
                        $where =~ s/ AND $/ OR /;
                        $where .= "users.$_ LIKE \"\%$search{$_}\%\" OR ";
                } else {
                        $where .= "users.$_ LIKE \"\%$search{$_}\%\" AND ";
                }
        }

        $where =~ s/ OR $//;
        $where =~ s/ AND $//;

        my %user_list = get_users($where);

        foreach (keys %user_list) {
                my $user = $_;
                foreach (@{$user_list{$user}{DOMAIN}}) {
                        $user_list{$user}{DOMAINS} .=
"$user_list{$user}{DOMAIN}[$_],";
                }
                chop($user_list{$user}{DOMAINS});

                $blah .=
"<tr><td>$_</td><td>$user_list{$_}{ISP}</td><td>$user_list{$_}{PWORD}</td><t
d>$user_list{$_}{FIRST}
$user_list{$_}{LAST}</td><td>$user_list{$_}{H_PHONE},$user_list{$_}{W_PHONE}
,$user_list{$_}{C_PHONE},$user_list{$_}{D_PHONE}</td><td>$user_list{$_}{EMAI
L1},$user_list{$_}{EMAIL2},$user_list{$_}{EMAIL3},$user_list{$_}{EMAIL4}</td
><td>$user_list{$_}{STATICIP}</td><td>$user_list{$_}{DOMAINS}</td><td>$user_
list{$_}{ACCNUM}</td></tr>";
        }

        $args{body} =<<EOF;
<center>
<table width="100%" border="1">
<tr><td>user</td><td>isp</td><td>password</td><td>name</td><td>phone</td><td
>email</td><td>
static ip</td><td>domain</td><td>service number</td></tr>
$blah
</table>
</center>
EOF

        return output_html($state, %args);
}

sub get_users {
        my $where = shift;
        my %search;
        my %user_list;

        my $sth =
$Sql->select("ISP,USER,PWORD,FIRST,LAST,H_PHONE,W_PHONE,C_PHONE,D_PHONE,EMAI
L1,EMAIL2,EMAIL3,EMAIL4,STATICIP,ACCNUM","users","$where");
        while (my $row = $sth->fetchrow_hashref) {
                $user_list{$row->{USER}} = {
                        ISP     =>      $row->{ISP},
                        PWORD   =>      $row->{PWORD},
                        FIRST   =>      $row->{FIRST},
                        LAST    =>      $row->{LAST},
                        H_PHONE =>      $row->{H_PHONE},
                        W_PHONE =>      $row->{W_PHONE},
                        C_PHONE =>      $row->{C_PHONE},
                        D_PHONE =>      $row->{D_PHONE},
                        EMAIL   =>      $row->{EMAIL},
                        STATICIP        =>      $row->{STATICIP},
                        ACCNUM  =>      $row->{ACCNUM},
                };
        }

        foreach my $user (keys %user_list) {
                $sth = $Sql->select("DOMAIN","domain","USER='$user'");
                while (my $row = $sth->fetchrow_hashref) {
                        push @{$user_list{$user}{DOMAIN}}, $row->{DOMAIN};
                        warn "$row->{DOMAIN}";
                }
        }

        return %user_list;
}


That warn statement in sub get_users generates this in my error_log file

www.blah.org at /home/httpd/ttms/perl/SQLCrap.pm line 145.
www.boop.com at /home/httpd/ttms/perl/SQLCrap.pm line 145.
www.fucker.com at /home/httpd/ttms/perl/SQLCrap.pm line 145.

And yet displayed on the webpage is

www.blah.org,www.blah.org,www.blah.org

So uh...  what am I doing wrong?

Dennis


Re: Values of an array..

Posted by Eric Wong <er...@taedium.net>.
On Mon, Jul 21, 2003 at 02:38:20PM -0700, Andrew Hurst wrote:
> At 01:22 PM 7/21/2003 -0800, Dennis Stout wrote:
> >> >"Dennis Stout"  wrote ...
> >> >         my %user_list = get_users($where);
> >> >
> >> >         foreach (keys %user_list) {
> >> >                 my $user = $_;
> >> >                 foreach (@{$user_list{$user}{DOMAIN}}) {
> >> >                         $user_list{$user}{DOMAINS} .=
> >> >"$user_list{$user}{DOMAIN}[$_],";
> >> >                 }
> >> >                 chop($user_list{$user}{DOMAINS});
> >> >...
> >>
> >> >$user_list{$user}{DOMAINS} .= "$user_list{$user}{DOMAIN}[$_],";
> >>
> >> That line is the culprit.  $_ contains each domain name as a text
> >> string.  Which evaluates to 0 when used as an integer, which then gives 
> >the
> >> first entry in the array.  Thus you get the first entry in the array as
> >> many times as you have entries in the array.  Try changing that to a
> >> regular (indexed) for loop and that should fix it.
> >
> >Good eye, I was too busy thinking of hashes and things.
> >
> >I hate array's.
> >
> >Should just be $user_list{$user}{DOMAINS} .= "$_,"; huh?
> 
> Yep.  After I sent the last email I realized that suggesting an indexed
> for loop was more effort than just deleting part of the string already
> there, like you just suggested.

This would be a good place for a join (perldoc -f join):

    $user_list{$user}{DOMAINS} = join ',', @{$user_list{$user}{DOMAIN}};

which lets you do away with the trailing chop() as well.

Since this has nothing to do with mod_perl, if you must reply, please
do it off-list.

Eric

Re: Values of an array..

Posted by Andrew Hurst <hu...@llnl.gov>.
At 01:22 PM 7/21/2003 -0800, Dennis Stout wrote:
> > >"Dennis Stout"  wrote ...
> > >         my %user_list = get_users($where);
> > >
> > >         foreach (keys %user_list) {
> > >                 my $user = $_;
> > >                 foreach (@{$user_list{$user}{DOMAIN}}) {
> > >                         $user_list{$user}{DOMAINS} .=
> > >"$user_list{$user}{DOMAIN}[$_],";
> > >                 }
> > >                 chop($user_list{$user}{DOMAINS});
> > >...
> >
> > >$user_list{$user}{DOMAINS} .= "$user_list{$user}{DOMAIN}[$_],";
> >
> > That line is the culprit.  $_ contains each domain name as a text
> > string.  Which evaluates to 0 when used as an integer, which then gives the
> > first entry in the array.  Thus you get the first entry in the array as
> > many times as you have entries in the array.  Try changing that to a
> > regular (indexed) for loop and that should fix it.
>
>Good eye, I was too busy thinking of hashes and things.
>
>I hate array's.
>
>Should just be $user_list{$user}{DOMAINS} .= "$_,"; huh?

Yep.  After I sent the last email I realized that suggesting an indexed for 
loop
was more effort than just deleting part of the string already there, like 
you just
suggested.

>Thanks

No problem.

-Andrew


>Dennis


Re: Values of an array..

Posted by Dennis Stout <st...@stout.dyndns.org>.
> >"Dennis Stout"  wrote ...
> >         my %user_list = get_users($where);
> >
> >         foreach (keys %user_list) {
> >                 my $user = $_;
> >                 foreach (@{$user_list{$user}{DOMAIN}}) {
> >                         $user_list{$user}{DOMAINS} .=
> >"$user_list{$user}{DOMAIN}[$_],";
> >                 }
> >                 chop($user_list{$user}{DOMAINS});
> >...
>
> >$user_list{$user}{DOMAINS} .= "$user_list{$user}{DOMAIN}[$_],";
>
> That line is the culprit.  $_ contains each domain name as a text
> string.  Which evaluates to 0 when used as an integer, which then gives the
> first entry in the array.  Thus you get the first entry in the array as
> many times as you have entries in the array.  Try changing that to a
> regular (indexed) for loop and that should fix it.

Good eye, I was too busy thinking of hashes and things.

I hate array's.

Should just be $user_list{$user}{DOMAINS .= "$_,"; huh?

Thanks

Dennis


Re: Values of an array..

Posted by Andrew Hurst <hu...@llnl.gov>.

>"Dennis Stout"  wrote ...
>         my %user_list = get_users($where);
>
>         foreach (keys %user_list) {
>                 my $user = $_;
>                 foreach (@{$user_list{$user}{DOMAIN}}) {
>                         $user_list{$user}{DOMAINS} .=
>"$user_list{$user}{DOMAIN}[$_],";
>                 }
>                 chop($user_list{$user}{DOMAINS});
>...

>$user_list{$user}{DOMAINS} .= "$user_list{$user}{DOMAIN}[$_],";

That line is the culprit.  $_ contains each domain name as a text 
string.  Which evaluates to 0 when used as an integer, which then gives the 
first entry in the array.  Thus you get the first entry in the array as 
many times as you have entries in the array.  Try changing that to a 
regular (indexed) for loop and that should fix it.

Hope that helps.
-Andrew


Re: Values of an array..

Posted by Dennis Stout <st...@stout.dyndns.org>.
> shouldnt 'my $user' be outside the foreach loop?

No, it's supposed to be changed each iteration through the loop.  Basically it
saves $_ to something else, so the next foreach loop doesn't overwrite it,
since I need it's value as a key for the hash the next loop creates.

Dennis


Re: Values of an array..

Posted by Gedanken <ge...@io.com>.
shouldnt 'my $user' be outside the foreach loop?  

I had a similar coding problem this weekend - completely unrelated to 
mod_perl.  I was using 
www::mechanize (greatest module ever) to parse xml and generate files.  If 
i had 18 user sections, it 
was writing the last member to disk 18 times.  I changed the scope of my 
vars slightly and all worked just fine.

-- 
gedanken