【问题标题】:Perl param() receiving from its own print HTMLPerl param() 从它自己的打印 HTML 接收
【发布时间】:2013-05-06 14:00:07
【问题描述】:

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

【问题讨论】:

  • 你在什么环境下运行这个脚本?它是由网络服务器运行的 CGI 脚本吗? bookcart.php 是什么? $data 是什么?为什么要将 html/form 创建与参数评估混合在一起?您希望输出文件的文件名是什么样的?
  • 输出是访问页面的用户的IP地址,它的html,所以我可以格式化数据库的输出,脚本是在提交搜索词后从书籍数据库中提取数据另一个 html 页面,$data 是一个占位符,用于将数据从数据库绘制移动到 html 表。
  • 好吧,我猜你会惊讶地看到真正的输出文件名。我猜您没有回答最重要的问题:为什么要将 html/表单创建与参数评估混合在一起?
  • 那为什么不尝试一步一步地学习一件事呢?使用表单创建一个 html 文件,将表单提交给一个小脚本并使用它。
  • 因为它会在 2 个半小时后到期......我从星期五开始一直在做这个......直!

标签: html forms perl cgi


【解决方案1】:

这假设您正在对 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 对象,然后从那里继续前进。

【讨论】:

  • 是的 $q 是对象,并且 id 也确实在那里使用了 CGI ......我也不认为你的解决方案有效......它没有在我的 winSCP 文件夹中创建新的文本文件
  • 可能是因为我的解决方案没有在 WinSCP 文件夹中创建文本文件。这也可能是权限问题,脚本无权在当前工作目录中创建文件。尝试在您的公开通话中添加||or,如下所示:open (FILE, "&gt;&gt;'$ip'.txt") || print "&lt;!-- Cannot open output file: $! --&gt;\n"; 如果无法创建页面,则会在生成的 HTML 页面中添加 HTML 注释,列出错误。
  • 不可能,所有权限都设置为读写和算术。加上添加错误语句只是多余的......我已经知道它没有打开和输出文件......
  • @DrewButler 错误处理不是无关:$! 包含错误原因,例如没有这样的路径,没有权限等。此外,您的脚本可能以不同的用户身份运行。
【解决方案2】:
  • 您没有使用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 为空。

【讨论】:

  • 您受到批评是因为您似乎很少努力帮助自己,并且期望别人为您做事。这不是寻求帮助,而是推卸责任。
【解决方案3】:

使用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') ) {

   ......

}

【讨论】:

  • 除了多余之外,使用 tr// 也绝对是大写字符串的错误方式,因为它只在 ASCII 范围内发挥作用。
猜你喜欢
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多