Solved

how a constructor handle a query string?

Posted on 2000-02-20
16
349 Views
Last Modified: 2006-11-17
I have a class with 2 methods: new and valueOf.

new is supposed to get the query string and decode it into an anonymous hash. The keys for this hash are html form element names (ie., name, address, fav colors, etc), and the values are what the user enters. Has to handle duplicates in the data (fave colors are red and purple).

valueOf gets the name of the form element and returns the value.

i hope i've explained this fully enough. I have NO IDEA how to get the query string into the constructor.

Thanks! Betsy
0
Comment
Question by:garfld
  • 8
  • 4
  • 3
  • +1
16 Comments
 
LVL 3

Accepted Solution

by:
monas earned 100 total points
ID: 2540379
package Yours;

use CGI;

sub new{
  my $q = new CGI or return {};
  my %ret;

  foreach $k ($q->param){
    $ret{$k} = $q->param($k);
  }

  return %ret;
}
0
 
LVL 2

Author Comment

by:garfld
ID: 2540934
There must be more to the pm. and, I don't know what you mean by use CGI. If you want to help me you are going to need to spell this out abc. If it's too much trouble - i can understand that, just tell me.

If the keys/values for the hash are from the html form, why would he want a method valueOf to get the name of the form element and returns the value? Why not just process that in the foreach loop?

I am so over my head with this - it shouldn't be that confusing but it is.

Thanks!
0
 
LVL 3

Expert Comment

by:monas
ID: 2541408
garfld,

      there is module CGI.pm distributed with standard perl distribution. To use it - you should write "use CGI;" as it is spelled in my example. By creating new instance of class CGI you say to get query string and parse it.

      as for valueOf...  you see - hash can hold one and only one value for any key (and there could not be two or more equal keys). Therefore - CGI module in those cases provide array and not a scalar value. valueOf could check is it array and return first item from it in those cases. But then - I have no idea how to get other values with this way constructed API...
0
 
LVL 3

Expert Comment

by:alien_life_form
ID: 2542440
Greetings.

What monas is suggesting is:

"Why in the world would you want to write a module to handle CGI transactions, when perl comes with a perfectly good and featureful and very hard to beat module that does the very same thing?"

Possible differing answers are:

i) CGI.pm is too heavy. => Then you could take a look at CGI::Lite
by Gurusam Saratyi.

ii) I want to learn how to write a perl module => That is good, but then you should know about the perl idiom:

use Foo.pm;

and about the relevant documentation that ships with the perl distribution itself.

As for your question "I do I get the query string into the constructor?" the answer is: you don't.
The module you are writing should be able to grab it either from the environment ($ENV{QUERY_STRING)) if GET was used, or from standard input if the method used was POST, in which case your module must know about

$ENV{CONTENT_LENGHT}


So a pseudo-code version (meaning: totally unchecked, even for spelling) of what you appear to want to do is:

package CGI::NewAndBetter;
@ISA=qw(Exporter);

sub new {
[...]
if ($ENV{HTTP_METHOD} eq 'GET') {
#get the query  string out of the environment,
#parse it, and fill a hash with it
} elsif ($ENV{HTTP_METHOD) eq 'PUT') {
#read all the parameters from stdin
#parse them, store them in the hash.
} else {
#complain loudly
}
 return bless \%theHash
}

sub valueOf {
 my($self,$key)=(@_);
 return $$self{$key} if defined $$self{$key};
 return (undef);
}


You would then import and use your new module as:

use CGI::NewAndBetter;

my $query=new CGI::NewAndBetter;

etc.


But unless you are doing it as a purely academic exercise, I would go with CGI.pm - it has been around for what, 5 years now? - and it has grown to a level of sophistication and completeness that cannot probably be matched. It also comes with very good documentation, which does not hurt any.

HTH & cheers,
   alf

P.S: if none of this makes any sense to you, then you definitely should get yourself acquainted with the perl documentation, and perhaps with the CGI protocol specs.


0
 
LVL 2

Author Comment

by:garfld
ID: 2544564
this *is* for a class and i am *desperately* trying to understand & write it. i am spinning in circles and burying myself here. i guess i have reached my outer limits here of programming :-) the peter principle? my levels of competency?

anyway, alf, i am rejecting your answer because maybe you or someone else would comment further. your answer is definitely on the right track but i need more details, not just pseudo code. no kidding, i am frantic here.

Thanks!
0
 
LVL 3

Expert Comment

by:alien_life_form
ID: 2545165
Greetings.

Let me see if I am digging your position here.

i) You appear to be on your way to write a package to handle CGI intractions in perl;

ii) You do not want to take advantage of prior art in this field;

iii) But you are not motivating (ii)

iv) You appear not to be acquainted with the documentation that comes with perl, with the principles and syntax of OO and modules within perl (and there are hints that some aspects of the Common Gateway Interface are not very clear to you, either);

v) You are giving a rather vague description of your problem;

vi) Yet you seem to expect that someone will come out with a fully coded solution for a task that has not even been clearly stated and motivated.(And may I draw your attention to the fact that it is by sole virtue of the intuition of the forum participants that we even know that CGI is involved here? You never mentioned it, a part from saying you neeed to 'get the query string in a constructor'. Now I'd say we're way removed from a class diagram here.);

And my take on this is:

Yes, you are in over your head on this.

And, I might add, until you revise your attitude towards reading and understanding the basic facts and tools that are relevant to your undertakings, you are doomed to firmly cling to your current position - or, at the very least, to reinvent the wheel.

Cheers,
   alf
0
 
LVL 2

Author Comment

by:garfld
ID: 2546328
Alien, I'm learning, is that reinventing the wheel? You don't learn the basics by relying on modules written by other people and not understanding them.

If you think I'm asking for too much help, just don't answer. This is a help forum and your sarcastic comments are not helpful. If I knew all the answers I'd be answering, not asking.

I think you're just annoyed that I rejected your answer - which should have been a comment, by the way, not an answer which blocked anyone else from commenting.
0
 
LVL 3

Expert Comment

by:alien_life_form
ID: 2546561
Greetings.

Learning is a *good thing*. In programming, this is most often achieved by reading other people's code (which is how you also achieve understanding). Learning usually does not happen while in a 'frantic' state, to use your word.

You are doing perl code so I assume you have a complete distribution on your disk - it includes a full fledged example (CGI.pm) of what you want to do, and reading it will be a great learning experience. If you feel that that is too complex grab CGI::Lite, which is simpler, off the net and read that.

Neither module will bite you, and you can then adapt the living code to your assignment's task. Of course, anybody could cut and paste the very same code from its editor to the comment window, but that would not be extremely useful, now would it? (I have CGI.pm in my emacs right now, would you like to taste some?)

I could also try and solve your assignment for you with original code. Now why would I bother to do that? I cannot code better perl that Stein or Gurusam (both of which can code my pants off), so it's unlikely I would get world recognition out of that. At the same time you would not learn much either, because, in this process, you would not have perused the Sources Of Wisdom, also known as the docs. (Let me point out to you that your second comment of the thread read, in part "...and, I don't know what you mean by use CGI." . Since "use Foo;" is to a perl programmer  what "#include <stdio.h>" is to a C programmer, doubts are right away cast on your perl proficiency, and doc perusal, by this statement alone.)

Now I would say that reading about the subject you are tackling, write some halfway working code, post it and ask for help would be a more fruitful approach, but who am I to say?

As for being sarcastic, I dunno. Jocularity is more my suit. If icy, bitter sarcasm is what interests you, you should try this thread on comp.lang.perl.misc, but bring your asbestoes in case TomC or Abigail get interested in this.

Cheers, & keep up the good (home)work
  alf
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 3

Expert Comment

by:monas
ID: 2546674
OK, Guys, let's go back to constructive discution.

I understand that garfld has program-maximum to become guru of perl and CGI. But to get to this state one need [lot of] time. And experience comes by learning things step-by-step.

So, garfld, what step would you like to take first:

a) learning how CGI programs gets information passwd to them;

b) learning how to program and use perl modules;

c) learning how to put number of values into one "slot" of hash;

d) you name a simple step.

And by the way... Using modules written by others is not so stupid idea... One will never know in depth all the ares, all the nuisances, but thanks to availability of includable parts, one could make use of others knowledge...

And 10 years ago when I was freshmen at university the biggest attention was paid to teach us fundamental things (like fast sorting, memory management, etc). Now things has changed. Now the most important thing is to show students how to use present libraries (think modules in perl) and extend work done by others...
0
 
LVL 2

Author Comment

by:garfld
ID: 2547076
Thanks for a voice of reason. Here's what i need now:

I can write a module and i can write a perl script which creates a new instance of the object and hardcodes the values for that one instance, and i can run that in dos.

Separately, I can write an html form, parse the query string, and use the string. But I can't get it all to work together.

What i just can't get, I can't get from the html form to the constructor and that's where i'm stuck.
0
 
LVL 3

Expert Comment

by:monas
ID: 2547124
OK, post either your last/best try to put things together, or separate working parts what are clear to you, and we will see what will happen...
0
 
LVL 2

Author Comment

by:garfld
ID: 2551428
oh, god - this is the best i could do so far - please don't laugh - do i have to put in that whole thing to parse string? the whole class - all 9 of us - is freaking out & i'm not the only one who can't do it.

#module:
package Pizza;
use strict;
{
   sub new  
   {
      my $class = shift;
      my $newOrder  = {};
      my $newOrder->{toppings} = [];

     if ($ENV{'REQUEST_METHOD'} eq 'GET')
     { @pairs = split(/&/, $ENV{'QUERY_STRING'}); }
     elsif ($ENV{'REQUEST_METHOD'} eq 'POST')
     { read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
     @pairs = split(/&/, $buffer);
            
     if ($ENV{'QUERY_STRING'})
     { @getpairs = split(/&/, $ENV{'QUERY_STRING'});
                                   push(@pairs,@getpairs);
     }
     }
                  
     foreach $pair (@pairs)
   {
    ($key, $value) = split (/=/, $pair);
    $key =~ tr/+/ /;
    $key =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
     $value =~ tr/+/ /;
     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
     $value =~s/<!--(.|\n)*-->//g;
                  
     if ($newOrder{$key} )
     {      $newOrder{$key} .= ", $value";       }
     else
     { $newOrder{$key} = $value; }
     }
             
      bless $newOrder, $class;
     
      return $newOrder;
   }

     sub valueOf
     {
     my $newOrder    = shift;
     my $item;
    my $top;

     foreach $item {%$newOrder}
            
     foreach $top {$newOrder->{$toppings}} )
      {
       return $$newOrder{$top};
     }
     return $$newOrder{$item}
     }
 
1;
}



#perl script:
#!/usr/bin/perl
 
 use Pizza;
 $myorder = pizza->new();
 $myorder->valueOf();
 
 print "Content-type: text/html\n\n";
 print "Thanks for your order, $name<br><br>";
 print "Your order is: ", $myorder->valueOf(), "\n";
 print "\n\n";
0
 
LVL 2

Author Comment

by:garfld
ID: 2553418
ok, i've got it & if anyone wants to see it i'll post it.

alien: we're doing cgi.pm next week :-)
0
 
LVL 84

Expert Comment

by:ozo
ID: 2553441
perl -Mdiagnostics 10298135.perl
"my" variable $newOrder masks earlier declaration in same scope at Pizza.pm
        line 9 (#1)
   
    (W) A lexical variable has been redeclared in the same scope, effectively
    eliminating all access to the previous instance.  This is almost always
    a typographical error.  Note that the earlier variable will still exist
    until the end of the scope or until all closure referents to it are
    destroyed.
   
Global symbol "@pairs" requires explicit package name at Pizza.pm line 12 (#2)
   
    (F) You've said "use strict vars", which indicates that all variables
    must either be lexically scoped (using "my"), or explicitly qualified to
    say which package the global variable is in (using "::").
   
Global symbol "$buffer" requires explicit package name at Pizza.pm line 14 (#2)
Global symbol "@getpairs" requires explicit package name at Pizza.pm line 18 (#2)
Global symbol "$pair" requires explicit package name at Pizza.pm line 23 (#2)
Global symbol "$key" requires explicit package name at Pizza.pm line 25 (#2)
Global symbol "$value" requires explicit package name at Pizza.pm line 25 (#2)
Global symbol "%newOrder" requires explicit package name at Pizza.pm line 32 (#2)
Global symbol "%item" requires explicit package name at Pizza.pm line 49 (#2)
0
 
LVL 2

Author Comment

by:garfld
ID: 2553488
I was getting all those errors from the parse-form and didn't know what to do about it. But i took out strict, and took out 'my', and of course, fixed up the parsing to put the values into an anonymous hash and changed the valueOf sub totally... and now it works.

as i said, if anyone's curious, i'll post it. else, thanks anyway!
0
 
LVL 2

Author Comment

by:garfld
ID: 2606934
This is pretty close to the way it worked out & you spent a lot of time with me, you deserve points.

I have to work over this weekend to change it and use cgi.pm :-)

Here's what i ended up with:

package Pizza;
{
sub new   {
$class = shift;
$newOrder  = {};
      
 if ($ENV{'REQUEST_METHOD'} eq 'GET')

            … parse…            
      
if  ($newOrder->{$key} )  {
$newOrder->{$key} .= ", $value";  }
else {
$newOrder->{$key} = $value; }
                  }
bless $newOrder, $class;

return $newOrder;

 }

 sub valueOf       {
 $newOrder = shift;
 $key      = shift;
 return $newOrder->{$key};

 }
 
1;
}
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now