0

我有一个 Perl 脚本,它从数据库中读取数据并在 HTML 表单/表格中打印出结果。每本书的表单还包含一个提交按钮。

我希望 Perl 创建一个文本文件(或读入一个已经创建的文件)并打印提交表单中的书名。但我似乎无法param()抓住提交动作!

#!/usr/bin/perl -w

use warnings;      # Allow for warnings to be sent if error's occur
use CGI;           # Include CGI.pm module
use DBI;
use DBD::mysql;    # Database data will come from mysql

my $dbh = DBI->connect('DBI:mysql:name?book_store', 'name', 'password')
    or die("Could not make connection to database: $DBI::errstr");  # connect to the database with address and pass or return error

my $q = new CGI;                     # CGI object for basic stuff
my $ip = $q->remote_host();          # Get the user's ip
my $term = $q->param('searchterm');  # Set the search char to $term
$term =~ tr/A-Z/a-z/;                # set all characters to lowercase for convenience of search

my $sql = '
  SELECT *
  FROM Books
  WHERE Title LIKE ?
    OR Description LIKE ?
    OR Author LIKE ?
';                    # Set the query string to search the database

my $sth = $dbh->prepare($sql);    # Prepare to connect to the database

$sth->execute("%$term%", "%$term%", "%$term%")
    or die "SQL Error: $DBI::errstr\n";  # Connect to the database or return an error

print $q->header;
print "<html>";
print "<body>";

print " <form name='book' action='bookcart.php' method=post> ";  # Open a form for submitting the result of book selection

print "<table width=\"100%\" border=\"0\"> ";

my $title  = $data[0];
my $desc   = $data[1];
my $author = $data[2];
my $pub    = $data[3];
my $isbn   = $data[4];
my $photo  = $data[5];

print "<tr> <td width=50%>Title: $title</td> <td width=50% rowspan=5><img src=$photo height=300px></td></tr><tr><td>Discreption Tags: $desc</td></tr><tr><td>Publication Date: $pub</td></tr><tr><td>Author: $author</td></tr><tr><td>ISBN: $isbn</td> </tr></table> <br>";

print "Add this to shopping cart:<input type='submit' name='submit' value='Add'>";

if ($q->param('submit')) {
    open(FILE, ">>'$ip'.txt");
    print FILE "$title\n";
    close(FILE);
}

print "</form>";    # Close the form for submitting to shopping cart
4

3 回答 3

3
  • 您还没有使用use strict, 来强制您声明所有变量。这是个坏主意

  • 您使用remote_host了 ,这是客户端主机系统的名称。您的服务器可能无法解析此值,在这种情况下它将保持未设置状态。如果您想要 IP 地址,请使用remote_addr

  • 您已经准备并执行了 SQL 语句,但没有从查询中获取数据。您似乎期望结果在数组@data中,但您尚未声明此数组。use strict如果你生效了,你会被告知这件事

  • 您已使用字符串'$ip'.txt作为文件名,因此,如果您正确使用 IP 地址而不是主机名,您的文件将看起来像'92.17.182.165'.txt. 你真的想要那里的单引号吗?

  • 你不检查你的open通话状态,所以你不知道打开是否成功,或者它可能失败的原因

我怀疑你是否真的花了过去 48 小时来编写这个。我认为你更有可能在最后一分钟匆忙地把一些东西放在一起,并使用 Stack Overflow 来帮助你摆脱你为自己挖的洞。

在寻求他人的帮助之前,您至少应该使用最少的良好实践编码方法,例如应用use strict. 您还应该尽最大努力调试您的代码:只需很少的时间即可找到$ip具有错误值且@data为空的代码。

于 2013-05-12T14:13:34.743 回答
1

使用 strictwarnings。您想使用strict的原因有很多。关于这方面的一篇不错的文章已在 perlmonks 结束,您可以从这里开始。使用严格和警告

您不一定需要以下行,您正在使用 DBI 并且可以使用 DBI 严格访问 mysql。

use DBD::mysql;

有许多选项可用CGI,我建议也根据用户偏好和期望的需求阅读perldoc 。

我不会使用以下内容:

my $q = new CGI;

# I would use as so..
my $q = CGI->new;

使用remote_addr而不是 remote_host 来检索您的 IP 地址。

下一行您将所有大写字母转换为小写字母,除非需要专门从您的数据库中读取所有小写字母,否则我觉得这没用。

$term =~ tr/A-Z/a-z/;    

接下来是您的 $sql 行,再次是用户偏好,但我会sprintf在您的调用中直接查看或使用它。此外,您正在尝试读取不存在的数据数组,取回数据的调用在哪里?我还建议阅读文档DBI,了解许多返回数据的方法。因此,例如,您希望使用数组返回数据...

这是一个未经测试的示例和提示,可帮助您入门。

use strict;
use warnings; 
use CGI qw( :standard );
use CGI::Carp qw( fatalsToBrowser ); # Track your syntax errors
use DBI;

# Get IP Address
my $ip = $ENV{'REMOTE_ADDR'};

# Get your query from param, 
# I would also parse your data here
my $term = param('searchterm') || undef;

my $dbh = DBI->connect('DBI:mysql:db:host', 'user', 'pass', 
                       {RaiseError => 1}) or die $DBI::errstr;

my $sql = sprintf ('SELECT * FROM Books WHERE Title LIKE %s 
                    OR Description LIKE %s', $term, $term);

my $sth = $dbh->selectall_arrayref( $sql );

# Retrieve your result data from array ref and turn into 
# a hash that has title for the key and a array ref to the data.
my %rows = ();
for my $i ( 0..$#{$sth} ) {
  my ($title, $desc, $author, $pub, $isbn, $pic) = @{$sth->[$i]};
  $rows{$title} = [ $desc, $author, $pub, $isbn, $pic ];  
}

# Storing your table/column names 
# in an array for mapping later.
my @cols;
$cols[0] = Tr(th('Title'), th('Desc'), th('Author'), 
              th('Published'), th('ISBN'), th('Photo'));

foreach (keys %rows) {
   push @cols, Tr( td($_), 
                   td($rows{$_}->[0]),
                   td($rows{$_}->[1]),
                   td($rows{$_}->[2]),
                   td($rows{$_}->[3]),
                   td(img({-src => $rows{$_}->[4]}));
}

print header,
      start_html(-title => 'Example'),
      start_form(-method => 'POST', -action => 'bookcart.php'), "\n",
      table( {-border => undef, -width => '100%'}, @cols ),
      submit(-name => 'Submit', -value => 'Add Entry'),
      end_form,
      end_html;

# Do something with if submit is clicked..
if ( param('Submit') ) {

   ......

}
于 2013-05-12T19:06:46.973 回答
-2

这假设您正在对 CGI.pm 使用 OO 方法,并且 $q 是相关对象。假设$q = new CGI您的脚本中有某个地方,这应该可以工作。

您可以发布其余的脚本吗?

我创建了一个模型来测试它,它按预期工作:

#!/usr/bin/perl

use CGI;

my $q = new CGI;

print $q->header;
print "<form><input type=submit name=submit value='add'></form>\n";

if ($q->param('submit')) {
    print "submit is \"" . $q->param('submit') . "\"\n";
}

点击提交按钮后,页面会显示submit is "add"评估正在按计划进行。

我想您需要做的是确保 $q 是您的 CGI 对象,然后从那里继续前进。

于 2013-05-12T11:38:40.943 回答