shopping cart implementation using perl - perl

I need to design a shopping cart using perl such that the user gets clear idea of the goods he choose to buy. I thought of saving data of those items in a cookie. But i wonder how to update an already existing cookie each time an item is added. Is there any better way to design a cart/checkout page. Is there any perl module which makes my work easier?
Here is the snippet i tried out for updating cookie of cart
$cooki = $q->cookie('CART'); #retrieve cookie CART if already exists into var $cooki
$val2 = $cooki;
$val1 = $picid;
$cooki=$q->cookie(-name=>'CART',
-value =>["$val1"," $val2"],
-expires=>'+5m',
-path=>'/');
print $q->header(-cookie=>$cooki);
retrieval:
$cooki = $q->cookie('CART');
But it stores only the current id of the pic selected like for ex '45%20' i.e. 45 with a space and not multiple values like '45 12 16' . Where could i go wrong?

Do not use Cookies, instead use CGI::Session. For all the reasons why, you can read CGI::Session::Tutorial.
I created a working examples of using sessions to transfer information from one form to another in this question: How to access variable of other perl program in my perl program

Try this, because the return is an array:
#cooki = $q->cookie('CART');

Use CGI::Cookie and set cookies in anonymous array
my $c = CGI::Cookie->new(-name => 'CART',
-value => ['45','12','16'],
then fetch existing cookies by:
%cookies = CGI::Cookie->fetch;
$cart = $cookies{'CART'}->value;

Related

Handle POST data sent as array

I have an html form which sends a hidden field and a radio button with the same name.
This allows people to submit the form without picking from the list (but records a zero answer).
When the user does select a radio button, the form posts BOTH the hidden value and the selected value.
I'd like to write a perl function to convert the POST data to a hash. The following works for standard text boxes etc.
#!/usr/bin/perl
use CGI qw(:standard);
sub GetForm{
%form;
foreach my $p (param()) {
$form{$p} = param($p);
}
return %form;
}
However when faced with two form inputs with the same name it just returns the first one (ie the hidden one)
I can see that the inputs are included in the POST header as an array but I don't know how to process them.
I'm working with legacy code so I can't change the form unfortunately!
Is there a way to do this?
I have an html form which sends a hidden field and a radio button with
the same name.
This allows people to submit the form without picking from the list
(but records a zero answer).
That's an odd approach. It would be easier to leave the hidden input out and treat the absence of the data as a zero answer.
However, if you want to stick to your approach, read the documentation for the CGI module.
Specifically, the documentation for param:
When calling param() If the parameter is multivalued (e.g. from multiple selections in a scrolling list), you can ask to receive an array. Otherwise the method will return the first value.
Thus:
$form{$p} = [ param($p) ];
However, you do seem to be reinventing the wheel. There is a built-in method to get a hash of all paramaters:
$form = $CGI->new->Vars
That said, the documentation also says:
CGI.pm is no longer considered good practice for developing web applications, including quick prototyping and small web scripts. There are far better, cleaner, quicker, easier, safer, more scalable, more extensible, more modern alternatives available at this point in time. These will be documented with CGI::Alternatives.
So you should migrate away from this anyway.
Replace
$form{$p} = param($p); # Value of first field named $p
with
$form{$p} = ( multi_param($p) )[-1]; # Value of last field named $p
or
$form{$p} = ( grep length, multi_param($p) )[-1]; # Value of last field named $p
# that has a non-blank value

PERL | Not getting the value after second submit

everyone.
I'm doing an tool with Perl that actually verifies a status in the database and if necessary it gets the properly queries and after confirmation it updates the value.
The page has three possible contents:
If the query that will be used is already filled it updates and returns the status.
If only the serial that the user input is filled it generates the query and then asks for confirmation.
If none of those 2 variables are already filled it goes to the main form where the user can submit the serial.
The problem that I'm facing is that after it generates the $final_query and shows up for confirmation, when I click the Confirm button it reloads the page but it pass directly through the if($final_query) and even the elseif that verifies if the $serial_no is already set.
Does Perl really lose those values if I perform a second submit or am I doing something wrong?
I'd love to have some explanation about it because it's the second time that I'm doing something with that language.
Thanks in advance!
--edit
I chopped the code to show where it defines the $final_query but I kept the structure to help in the understanding.
The full code is available at http://pastebin.com/6NqhbVau
#headers
if ($final_query) {
$content = "<h1>first if</h1>";
#updateESNDatabase($database, $final_query);
#it only enters here if the user type the ESN
}elsif ($serial_no) {
#selects the database
switch(checkUpdateNeeded($database, $serial_no)) {
case 0 {
#Shows that the updates are no needed
}
case 1 {
$final_query = `cat $query1`;
chop($final_query);
$final_query =~ s/SERIALNUM/$serial_no/g;
$final_query =~ s/LOGINID/$login_id/g;
$content = $cgi->start_form .
"<center>" .
"<h3> Please double check the queries below before you update on database </h3>" .
"</center>" .
$cgi->submit("Confirm") . $cgi->end_form;
$content .= $final_query;
}
case 2 {
#Makes almost the same as the first case, it only uses a different file to generate the query.
}
}
} else {
#Generates the first page, where the users inputs information
}
$page->set_content($content);
$page->process;
I figured out how to perform this.
As per my analysis I cannot simply create a variable and pass it through the cgi form.
To workaround this what I've done is create a hidden input in HTML and then send the variable through it.
<input type='hidden' name='the_query' value=\"$final_query\">

Drupal save global variables

I make a form in drupal to store data (for annonymous user) so when the form is validate i would like to save it to access it from all page but that does not work outside this function the variable is NULL
can you help me or have you another method to proceed ?
function myform_form_submit($form, &$form_state) {
....
$GLOBALS ['info'] = $info;
}
When a Drupal form is evaluated, it executes any code, including database changes. But then it redirects the user to a new page, which discards the PHP session, including $GLOBALS, among other things.
The more Drupally way is to use persistent variables, which are stored in the "variables" database table.
The variable_set function can be used here. So replace
### $GLOBALS['info'] = $info ### replace with:
variable_set('mymodule_info', $info);
and then when you access it, instead of using $GLOBALS, just use
$info = variable_get('mymodule_info', NULL);
You can use any name to specify the variable. I add NULL as a second parameter to variable_get in case the value isn't present in the database.
If the data is associated with a particular user, you might need to do something like
global $user;
variable_set('mymodule_info_uid_' . $user->uid, $info);
and then to retrieve the data use
global $user;
$info = variable_get('mymodule_info_uid_' . $user->uid, NULL);
EDIT: Ah, now I see you're dealing with anonymous users. In that case, PHP can identify anonymous users for you by giving a session id that can be used in the same way:
variable_set('mymodule_info_session_' . session_id(), $info);
variable_get('mymodule_info_session_' . session_id(), NULL);
This should be persistent for an anonymous user's browsing session.
The issue with this approach is that you'll need to come up with some way of clearing these out. You'll probably need to store a timestamp in the $info variable and have a cron job to delete expired entries from the variable table.

How can I store more information in a session in Zend?

So I created a user system, and I want to grab the a few other fields from my database after authenticate()ing them. How can I do this?
If you want to store extra information in the identity beyond the typical, you can do something like this upon successful authentication.
This is in my login controller, processAction() upon successful authentication:
$identity = new stdClass;
$identity->username = strtolower( $auth->getIdentity() );
$identity->miscParam1 = 'Miscellaneous parameter1';
$identity->miscParam2 = 'Miscellaneous parameter2';
# ... etc ...
$storage = $auth->getStorage();
$storage->write($identity);
It's important to note that if you use this approach, then every time you want to get the username or the other parameters, you will need to retrieve it like so:
$identity = Zend_Auth::getInstance()->getStorage()->read();
echo $identity->username; # echo is just for example
echo $identity->miscParam1;
echo $identity->miscParam2;
Note that you would use getStorage()->read() instead of getIdentity() (which might also work but I am not sure).
Now, the only thing left to do is populate $identity->miscParam1 (etc) with information from your database using Zend_Db_Select. (Looking back at your question... I hope you weren't asking how to query. I probably didn't even answer your question.)

Perl DBI Query -> JSON -> JQuery AutoComplete

I've been trying to read up on how to implement a JSON solution in order to use JQueryUI's autocomplete functionality. I am trying to use autocomplete to search a database on for a name and after selection populate the ID to a hidden object. I've seen alot of examples around the web, but haven't found the best way to implement this. The database doesn't change that often, so I'm not sure how to best approach this performance wise.
Backend:
#!/usr/bin/perl
use CGI;
use DBI;
use strict;
use warnings;
my $cgi = CGI->new;
my $dbh = DBI->connect('dbi:mysql:hostname=localhost;database=test',"test","test") or die $DBI::errstr;
my $sth = $dbh->prepare(qq{select id, name from test;}) or die
$dbh->errstr;
$sth->execute() or die $sth->errstr;
my $json = undef;
while(my #user = $sth->fetchrow_array()) {
$json .= qq{{"$user[0]" : "$user[1]"}};
}
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json;
The jQuery autocomplete needs a "value" or "label" field returned with the json result. If you do not include it, the jquery autocomplete will not work:
The basic functionality of the autocomplete works with the results of the query assigned to the ‘label’ and ‘value’ fields. Explanation on the ‘label’ and ‘value’ fields from the jQuery UI site:
“The local data can be a simple Array of Strings, or it contains Objects for each item in the array, with either a label or value property or both. The label property is displayed in the suggestion menu. The value will be inserted into the input element after the user selected something from the menu. If just one property is specified, it will be used for both, eg. if you provide only value-properties, the value will also be used as the label.”
Link to full example: http://www.jensbits.com/2011/05/09/jquery-ui-autocomplete-widget-with-perl-and-mysql/
You need to grap the JSON package from CPAN instead of doing this:
my $json = undef;
while(my #user = $sth->fetchrow_array()) {
$json .= qq{{"$user[0]" : "$user[1]"}};
}
For example, with JSON it'd look like this:
use JSON;
my $json = {};
while(my #user = $sth->fetchrow_array()) {
$json->{$user[0]} = $user[1];
}
print JSON::to_json($json);
The JSON package will automatically construct a valid JSON string from any Perl data structure you provide it. We use it all over the place on Melody and it's proved to be a real life saver for sanely converting a structure into valid JSON.
Here I'm talking about performance.
There is some trigger you can set to improve performance, client side you can set the minimum number of characters required before the request is sent.
You can also set the "timeout" between two characters typing before the request is sent.
If your database table is really huge, I suggest you put a LIMIT on results you retrieve.
First to avoid long request processing, but also because some clients like IE6 arent't really fast handling more than a hundred results (Not to say, it's also not really user friendly).
On a project using IE6, we limited the elements returned to 100. If the user can't reduce the search to 100 elements, we presume he/she doesn't know what he/she is looking for.
Hope it helps a bit.