Perl param()从它自己的打印HTML接收

时间:2013-05-12 11:11:26

标签: html forms perl cgi

我有一个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

3 个答案:

答案 0 :(得分: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为空,则可能很少发现。

答案 1 :(得分:1)

使用 strictwarnings。出于多种原因,您希望使用strict。关于perlmonks的一篇不错的文章结束了,你可以从这开始。 Using strict and warnings

您不一定需要以下行,您正在使用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') ) {

   ......

}

答案 2 :(得分:-2)

这假设您正在使用OO方法来CGI.pm,并且$ 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对象,并从那里继续前进。