【问题标题】:Display content and its related contents in Perl/Mysql在 Perl/Mysql 中显示内容及其相关内容
【发布时间】:2018-08-25 00:23:12
【问题描述】:

我正在尝试从像这样的小型 Perl 项目中实现此示例输出

   content1
        relatedcontent1
        relatedcontent2
        relatedcontent2
   content2
        relatedcontent1
        relatedcontent2 

这是我的代码

   #!C:/Perl64/bin/perl.exe
   use strict;
   use warnings;
   use v5.10; # for say() function
   use DBI;
   use HTML::Table;

   # MySQL database configurations
   my $dsn = "DBI:mysql:naxum";
   my $username = "root";
   my $password = '';
   print "Content-Type:text/html\r\n\r\n";
   # connect to MySQL database
   my %attr = ( PrintError=>0,  # turn off error reporting via warn()
         RaiseError=>1   # report error via die()
       );
   my $dbh = DBI->connect($dsn,$username,$password,\%attr);

   # query data from the sponsor table
   query_sponsor($dbh);
   query_person_by_target($dbh);

   sub query_sponsor{
   # query from the  table
    my ($dbh) = @_;
    my $sql = "SELECT name,id FROM sponsor";
    my $sth = $dbh->prepare($sql);
    # execute the query
   $sth->execute();
   print "<table>\n";
   print "<thead>\n";
   print "<tr>\n";
   print "<th>Id</th>\n";
   print "<th>Name</th>\n";
   print "</tr>\n";
   print "</thead>\n";
   print "<tbody>\n";
   while(my @row = $sth->fetchrow_array()){

 print "<tr>\n";
 print "<td>\n";
 print $row['1'];

  sub query_person_by_target{
      my ($dbhPerson) = @_;
      my $sqlPerson = "SELECT username, firstname FROM person WHERE sponsor_id = ?";
      my $sthPerson = $dbhPerson->prepare($sqlPerson);
     $sthPerson->execute($row['1']) or die "execution failed: $dbhPerson->errstr()";
      while ( my @rowPerson = $sthPerson->fetchrow_array()){
          print "<p>$rowPerson['0']</p>\n";
      }
      $sth->finish();
 }
 print "</td>\n";
 print "<td>$row['0']</td>\n";
 print "</tr>\n";
 }
 $sth->finish();
 print "</tbody>\n";
 print "</table>\n";
 }
 $dbh->disconnect();

但是,我无法获得我想要实现的输出。这是结果

   content1
   content2
   content3
   .....
   relatedcontent1

它只会在内容之外打印一个相关内容。每个内容及其各自至少 3 个相关内容。

【问题讨论】:

    标签: mysql perl


    【解决方案1】:

    您在程序的其他代码中间定义子例程。这使我认为您希望它们按照定义的方式执行,但事实并非如此-它们是按照您的调用方式执行的。你这样称呼他们:

    query_sponsor($dbh);
    query_person_by_target($dbh);
    

    因此,您从query_sponsor() 获得所有输出,然后是从query_person_by_name() 获得所有输出,这不足为奇。

    更好的方法是从query_sponsor() 中调用query_person_by_target()。我还将其分为两个阶段 - 第一阶段将数据提取到数据结构中,第二阶段显示该数据。

    由于我没有您的数据库,因此此代码未经测试。

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'state'; # for state variables
    use feature 'say';
    use CGI 'header';
    
    sub get_dbh {
      # MySQL database configurations
      my $dsn = "DBI:mysql:naxum";
      my $username = "root";
      my $password = '';
      # connect to MySQL database
      my %attr = (
        PrintError=>0,  # turn off error reporting via warn()
        RaiseError=>1,  # report error via die()
      );
    
      return DBI->connect($dsn, $username, $password, \%attr);
    }
    
    sub query_sponsor {
      state $dbh = get_dbh();
    
      my $sql = 'select name, id from sponsor';
      my $sth = $dbh->prepare($sql);
      $sth->execute;
    
      my @sponsors;
    
      while (my @row = $dbh->fetchrow_array) {
        push @sponsors, {
          name   => $row[0],
          id     => $row[1],
          people => get_people_for_sponsor($row[1]),
        };
      }
    
      return @sponsors;
    }
    
    sub get_people_for_sponsor {
      my ($sponsor_id) = @_;
    
      state $dbh = get_dbh;
    
      my $sql = 'select username, firstname
                 from   person
                 where  sponsor_id = ?';
      my $sth = $dbh->prepare;
      $sth->execute($sponsor_id);
      my @people;
      while (my @row = $sth->fetchrow_array) {
        push @people, {
          username  => $row[0],
          firstname => $row[1],
        };
      }
    
      return \@people;
    }
    
    my @sponsors = query_sponsor();
    
    # Now you have all of your data in @sponsors. You simply need
    # to walk that array and use the data to build the output you
    # want. My example is plain text - it shouldn't be too hard to
    # convert it to HTML.
    
    print header('text/plain');
    
    for my $s (@sponsors) {
      say "$s->{id}: $s->{name}";
      for my $p (@{$s->{people}}) {
        say "* $p->{firstname} / $p->{username}";
      }
    }
    

    我还建议您考虑使用模板工具包之类的工具来生成输出。将原始 HTML 放入您的 Perl 程序是一个糟糕的主意 - 它肯定会变成无法维护的混乱 :-)

    【讨论】:

      【解决方案2】:

      您已经声明了两个子例程,并且您正在一个接一个地调用,因此它的执行方式就像这样,例如考虑以下一个

      sub1();
      sub2();
      
      sub sub1()
      {
          for(0..5)
          {
              print "hello\n";
              sub sub2()
              {
                  print "hi\n";
      
              }
          }
      }
      
      #output
      hello
      hello
      hello
      hello
      hello
      hello
      hi
      

      因此您应该删除子query_person_by_target 子程序或在父子程序query_sponsor 内调用子子程序并在子和循环之外声明子子程序,如下所示(未测试)

      query_sponsor($dbh);
      
      sub query_sponsor
      {
          # query from the  table
          my ($dbh) = @_;
          my $sql = "SELECT name,id FROM sponsor";
          my $sth = $dbh->prepare($sql);
          # execute the query
          $sth->execute();
          print "<table>\n";
          print "<thead>\n";
          print "<tr>\n";
          print "<th>Id</th>\n";
          print "<th>Name</th>\n";
          print "</tr>\n";
          print "</thead>\n";
          print "<tbody>\n";
          while(my @row = $sth->fetchrow_array())
          {
      
              print "<tr>\n";
              print "<td>\n";
              print $row['1'];
      
              query_person_by_target($dbh);
      
              print "</td>\n";
              print "<td>$row['0']</td>\n";
              print "</tr>\n";
          }
          $sth->finish();
          print "</tbody>\n";
          print "</table>\n";
      }
      
      sub query_person_by_target{
          my ($dbhPerson) = @_;
          my $sqlPerson = "SELECT username, firstname FROM person WHERE sponsor_id = ?";
          my $sthPerson = $dbhPerson->prepare($sqlPerson);
          $sthPerson->execute($row['1']) or die "execution failed: $dbhPerson->errstr()";
          while ( my @rowPerson = $sthPerson->fetchrow_array()){
              print "<p>$rowPerson['0']</p>\n";
          }
          $sth->finish();
      }
      $dbh->disconnect();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-30
        • 1970-01-01
        • 2023-04-09
        • 2011-01-03
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多