如何从URL中获取查询字符串 - Perl

4

我不知道如何使用Perl从URL中获取查询字符串。我尝试了几种方法,例如:

my $qs = $ENV{'QUERY_STRING'};
my @d = split(/&/, $qs);

if ( $d[1] eq 'reports' ) {
    ... do something
}

并且

use CGI;
my $q = CGI->new;
my $page = $q->param('page');

但是我无法获得键的值。现在我手动将查询字符串放入其中,即 project.local/routes.cgi?page=reports 但是我从命令行中得到以下结果:
Use of uninitialized value $qs in split at ./routes.cgi line 23.
Use of uninitialized value $d[1] in string eq at ./routes.cgi line 25.

我不确定为什么会有这个警告,因为如果它不存在,它应该只是未定义的吧?

我应该如何存储和检查查询字符串变量?我主要使用routes.cgi脚本作为路由控制器,所有链接都指向i.e. <a href="project.local/routes.cgi?page=xx">,然后我处理一个模板工具包文件并重定向到该页面(这个概念好吗?)

诊断结果:

Use of uninitialized value $qs in split at ./routes.cgi line 23 (#1)
    (W uninitialized) An undefined value was used as if it were already
    defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

编辑:

use URI qw( );
use URI::QueryParam qw( );

my $u = URI->new($base_url);
my ($p) = $u->query_param('page');

if ( $p eq 'reports' ) {
    ...do something
}

@putnamhill 谢谢,非常有帮助。我已经在我的答案中包含了那个结果。 - a7omiton
虽然我不确定这个警告信息是否有助于解决潜在的问题,因为我正在获取环境变量的内容? - a7omiton
不要自己解析URI(或从$ENV中获取查询参数),如果这样做,你很可能会出错。使用CGI对象来获取参数。如果需要(或想要)解析完整的URI,请使用https://metacpan.org/pod/URI模块。 - Leeft
@RobEarl 当我使用url 'cgi-bin/routes.cgi?page=reports'运行脚本时,我会收到一个内部服务器错误,当我从命令行运行cgi脚本时,$q->param('page')的值未初始化。 - a7omiton
1
请参考https://dev59.com/7HI95IYBdhLWcg3wxA09#2165040,了解如何解决可怕的内部服务器错误(特别是与浏览器/错误日志相关的部分)。 - RobEarl
显示剩余4条评论
3个回答

4

看起来你已经花了很多天的时间(根据你之前的问题)在处理你的 route.cgi。通过阅读你之前问题中的评论和答案,许多开发者已经建议你:使用一些框架。

现在是关于你的问题:

Use of uninitialized value $qs in split at ./routes.cgi line 23.

这意味着(根据use diagnostics的提示)- $qs变量不包含任何值。为什么$ENV{'QUERY_STRING'};没有值取决于您的环境,但通常,您不应该依赖于某些环境变量,而应该依赖于从HTTP请求中获得的内容。

Use of uninitialized value $d[1] in string eq at ./routes.cgi line 25.

当然,因为$qs未定义,所以split会将空白分开,分离的空白也是空白 - 因此您的@d数组中没有任何内容,因此$d [1]未初始化。
顺便说一句,当您来自php-word(正如您在其中一个问题中所说)时,您应该知道,在成功拆分“QUERY_STRING”后,&将获得$d [0] 值为page=report而不仅仅是report
正如@AndyLester告诉您的那样,处理URL(获取或组成)的部分使用URI::URL模块,但您真的应该至少阅读它的描述。
广告路由:通常最好、最美观、最有利于SEO的URL如下:
http://example.com/blog/archive/2013/12/20

而不是

http://example.com/run?section=blog&action=archive&year=2014&month=12&day=20

因此,在“路由”中不使用URL参数,而是使用PATH_INFO。这种“哲学”已经发展成为许多框架,如Poet+MasonMojoliciousDancer等等,或者在这里有独立的模块来处理路由(搜索MetaCPAN.org)。
从我的角度来看,基于以下命令进行Perl Web应用程序开发:
安装自己的Perl环境(只需一次)。
curl -L http://install.perlbrew.pl | bash
#relog, to init the environment

perlbrew available
prelbrew install perl-5.20.0
prelbrew switch perl-5.20.0
prelbrew install-cpanm

当我有了“自己的”Perl时
cpanm Poet #will install a bunch of modules
#or alternatively
cpanm Mojolicious

从现在开始,事情相对容易:

cd my_development_directory
poet new myapp
cd myapp

echo 'This is my report <% localtime %>' > comps/report.mc
./bin/run.pl

假设您有一个正在运行的 Perl Web 应用程序。那么,请将您的浏览器指向:http://localhost:5000/report,您将会得到:

This is my report Tue Jul 29 16:09:52 2014

同时,您还将获得一个很棒的调试面板和更多功能...(请参阅Mason和Poet手册)

我仍然是Perl开发中的初学者,因此其他更有经验的Perl程序员可能会给您提供更好的建议。


1

谢谢分享。但是,现在问题中包含的代码仍然会出现未初始化警告。 - a7omiton

-1

jm666说得对,你真的应该考虑使用一个框架。然而,如果你想尽量减少模块的安装,可以尝试像这样的方法...

use strict;
use warnings;
use URI::Escape;
use Data::Dumper;

#this will catch anything after the "?", as in SomeURL?Var=111&OtherVar=QQQ
my $RequestHash;
if($ENV{"QUERY_STRING"}) {
    #QUERY_STRING="id=demo:5&other=some%20text&last=more%20text"
    my @TempArray=split("&", $ENV{"QUERY_STRING"});
    foreach my $item (@TempArray) {
        my ($Key, $Value)=split("=", uri_unescape($item)); #need to fix this to work with more than one "=" in the value
        $RequestHash->{lc($Key)}=$Value; #normalize the key name to lower case - because you never know what users will do
    } #end foreach
} #end query check if

print Data::Dumper::Dumper($RequestHash);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接