Home > Archive > PERL CGI Beginners > April 2005 > Variables in Modules
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Variables in Modules
|
|
| Sergio Pires de Albuquerque 2005-04-13, 8:55 pm |
| Dear Guys,
I´ve been trying to develop an application that consists in about 8-10
scripts that should know about module variables (not OO yet). I read the
docs and found that I can use a module variable (declared with our) in
scripts that 'use' that module. Ok, there are:
module1.cgi (declare and define var1)
main.cgi (declare and initialize var1) "use module1"
script1.cgi (read and alter var1) "use module1"
script2.cgi (gets var1 with undefined or previous value) "use module1"
I tried with our, importing that var and fully qualified it, but always
it get the previous value. My question is: Which method is common to
share data among apps? What Am I doing wrong? Also, I always use
"strict" and "warnings".
Thanks in advance.
| |
|
| --- Sergio Pires de Albuquerque <spires@unitech.inf.br> wrote:
> I tried with our, importing that var and fully qualified it, but
> always
> it get the previous value. My question is: Which method is common to
> share data among apps? What Am I doing wrong? Also, I always use
> "strict" and "warnings".
You're talking about global variables and, in general, using them is a
bad thing as it makes code more difficult to maintain. I won't go into
that, though, as there's plenty of info elsewhere about that.
In your case, don't give access to the variables. If you're not going
to go OO, give access to subroutines which can read and alter those
variables.
package Foo;
use strict;
use warningsl
my $var = 7;
sub var { $var }
sub set_var {
my $new_var = shift;
unless (defined $new_var and $new_var =~ /^\d+$/) {
require Carp;
Carp::croak("Argument to set_var() can only be digits: ($var));
}
$var = $new_var;
}
1;
With techniques like that, you can at least ensure that there is one
canonical place where the data is being fetched and altered. This
gives you some measure of protection to ensure that naughty code isn't
doing things it should not be doing and, if it ever gets set to a bad
value, you have only one place to put your debugging code.
Cheers,
Ovid
--
If this message is a response to a question on a mailing list, please send
follow up questions to the list.
Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/
| |
| Wiggins d'Anconia 2005-04-13, 8:55 pm |
| Ovid wrote:
> --- Sergio Pires de Albuquerque <spires@unitech.inf.br> wrote:
>
>
>
>
>
> You're talking about global variables and, in general, using them is a
> bad thing as it makes code more difficult to maintain. I won't go into
> that, though, as there's plenty of info elsewhere about that.
>
> In your case, don't give access to the variables. If you're not going
> to go OO, give access to subroutines which can read and alter those
> variables.
>
> package Foo;
> use strict;
> use warningsl
>
> my $var = 7;
> sub var { $var }
> sub set_var {
> my $new_var = shift;
> unless (defined $new_var and $new_var =~ /^\d+$/) {
> require Carp;
> Carp::croak("Argument to set_var() can only be digits: ($var));
> }
> $var = $new_var;
> }
> 1;
>
> With techniques like that, you can at least ensure that there is one
> canonical place where the data is being fetched and altered. This
> gives you some measure of protection to ensure that naughty code isn't
> doing things it should not be doing and, if it ever gets set to a bad
> value, you have only one place to put your debugging code.
>
> Cheers,
> Ovid
>
I agree with what Ovid said, but in the case where the data won't need
or shouldn't be changed, you might consider using constants, which have
a global nature but are considered less messy than global variables.
perldoc constant
Though I would still drop them into their own module that can be 'use'd.
This works well for DB DSNs, base URLs, etc.
http://danconia.org
| |
| Sergio Pires de Albuquerque 2005-04-13, 8:55 pm |
| Ovid wrote:
>--- Sergio Pires de Albuquerque <spires@unitech.inf.br> wrote:
>
>
>
>
>
>
>You're talking about global variables and, in general, using them is a
>bad thing as it makes code more difficult to maintain. I won't go into
>that, though, as there's plenty of info elsewhere about that.
>
>In your case, don't give access to the variables. If you're not going
>to go OO, give access to subroutines which can read and alter those
>variables.
>
> package Foo;
> use strict;
> use warningsl
>
> my $var = 7;
> sub var { $var }
> sub set_var {
> my $new_var = shift;
> unless (defined $new_var and $new_var =~ /^\d+$/) {
> require Carp;
> Carp::croak("Argument to set_var() can only be digits: ($var));
> }
> $var = $new_var;
> }
> 1;
>
>With techniques like that, you can at least ensure that there is one
>canonical place where the data is being fetched and altered. This
>gives you some measure of protection to ensure that naughty code isn't
>doing things it should not be doing and, if it ever gets set to a bad
>value, you have only one place to put your debugging code.
>
>Cheers,
>Ovid
>
>
>
Ok,
Thanks, but when I call another script from script1.cgi the value has
gone and the old restored (probably with my $var in package). Both
scripts "use" the module and turn into that symbol table (via package).
What can I do?
Thanks in advance,
| |
| David Dorward 2005-04-13, 8:55 pm |
| On Wed, Apr 13, 2005 at 05:14:31PM -0300, Sergio Pires de Albuquerque wrote:
> Thanks, but when I call another script from script1.cgi the value has
> gone
HTTP is stateless. Each time a user requests an HTTP resource provided
by a script, that script is run from scratch. If you want to make data
persistent from one HTTP request to another, you either have to get
the browser to pass it back (by encoding the data in the URL
(typically with the query string, or (with the help of a form) in a
POST request - either way it can be accessed with the param method of
the CGI module), or by storing it on the server and asking the client
to pass a token about (typically in a Cookie) to identify which set of
data belongs to the user (this is usually done with sessions:
http://search.cpan.org/~sherzodr/CG...3.95/Session.pm )
--
David Dorward http://dorward.me.uk
| |
| Lawrence Statton 2005-04-14, 3:55 am |
| > Dear Guys,
>
> I´ve been trying to develop an application that consists in about 8-10
> scripts that should know about module variables (not OO yet). I read the
> docs and found that I can use a module variable (declared with our) in
> scripts that 'use' that module. Ok, there are:
>
> module1.cgi (declare and define var1)
> main.cgi (declare and initialize var1) "use module1"
> script1.cgi (read and alter var1) "use module1"
> script2.cgi (gets var1 with undefined or previous value) "use module1"
>
>
> I tried with our, importing that var and fully qualified it, but always
> it get the previous value. My question is: Which method is common to
> share data among apps? What Am I doing wrong? Also, I always use
> "strict" and "warnings".
>
Well, first -- I wouldn't name your modules *.cgi .... *.pm is what
everyone expects to see, and in absence of a Good Overriding Reason
you should follow the Principle of Least Astonishment. Naming your
module "module" is also a terrible idea - unless you expect only to
have one ever in your life. Give it a meaningful name.
That said:
The simplest way to create and use fully qualified variables from
another package is just to fully qualify them.
So, you've got some module Segrio's First Module:
SergioPrimo.pm
------------------------------------------------------------
package SergioPrimo;
our ($foo, $bar, $baz);
1;
------------------------------------------------------------
Now, down in your .cgi file, you can use those variables by their
names $SergioPrimo::foo $SergioPrimo::bar etc.
If you want not to have to fully qualify the variable name, you can
use Exporter ... something like
------------------------------------------------------------
package SergioPrimo;
use base 'Exporter';
our @EXPORT_OK = qw / $foo $bar $baz /;
our %EXPORT_TAGS = ( all => \@EXPORT_OK );
our ($foo, $bar, $baz);
1;
------------------------------------------------------------
Now you can say down in your CGI
random.cgi
------------------------------------------------------------
use SergioPrimo (':all'); # import some variables
$foo = 123; # sets $SergioPrimo::foo
------------------------------------------------------------
NOW ... all that being said:
It looks like your more serious problem is: You're trying to store
state in Perl from different contexts, which is surely confusing you
no end.
If you're using just plain-old-CGI, then each and every time your web
server handles an inbound request, a brand new Perl interpreter is
instantiated, SergioPrimo::foo gets built fresh (as undef) and your
..cgi files may or may not set that variable and use them again later.
If you're using some persistent-perl-like product (e.g. FastCGI,
mod_perl) then you will find that SOMETIMES SergioPrimo::foo has the
last value it had, and sometimes it doesn't.
Perhaps you should take a step back and try to explain what you're
trying to do.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Lawrence Statton - lawrenabae@abaluon.abaom s/aba/c/g
Computer software consists of only two components: ones and
zeros, in roughly equal proportions. All that is required is to
sort them into the correct order.
| |
| Sergio Pires de Albuquerque 2005-04-14, 3:55 pm |
| Lawrence Statton wrote:
>
>Well, first -- I wouldn't name your modules *.cgi .... *.pm is what
>everyone expects to see, and in absence of a Good Overriding Reason
>you should follow the Principle of Least Astonishment. Naming your
>module "module" is also a terrible idea - unless you expect only to
>have one ever in your life. Give it a meaningful name.
>
>That said:
>
>The simplest way to create and use fully qualified variables from
>another package is just to fully qualify them.
>
>So, you've got some module Segrio's First Module:
>
> SergioPrimo.pm
>------------------------------------------------------------
>
>package SergioPrimo;
>
>our ($foo, $bar, $baz);
>
>1;
>
>------------------------------------------------------------
>
>Now, down in your .cgi file, you can use those variables by their
>names $SergioPrimo::foo $SergioPrimo::bar etc.
>
>If you want not to have to fully qualify the variable name, you can
>use Exporter ... something like
>
>------------------------------------------------------------
>
>package SergioPrimo;
>use base 'Exporter';
>
>our @EXPORT_OK = qw / $foo $bar $baz /;
>our %EXPORT_TAGS = ( all => \@EXPORT_OK );
>
>our ($foo, $bar, $baz);
>
>1;
>------------------------------------------------------------
>
>Now you can say down in your CGI
>
>random.cgi
>------------------------------------------------------------
>
>use SergioPrimo (':all'); # import some variables
>
>$foo = 123; # sets $SergioPrimo::foo
>
>------------------------------------------------------------
>
>NOW ... all that being said:
>
>It looks like your more serious problem is: You're trying to store
>state in Perl from different contexts, which is surely confusing you
>no end.
>
>If you're using just plain-old-CGI, then each and every time your web
>server handles an inbound request, a brand new Perl interpreter is
>instantiated, SergioPrimo::foo gets built fresh (as undef) and your
>.cgi files may or may not set that variable and use them again later.
>
>If you're using some persistent-perl-like product (e.g. FastCGI,
>mod_perl) then you will find that SOMETIMES SergioPrimo::foo has the
>last value it had, and sometimes it doesn't.
>
>Perhaps you should take a step back and try to explain what you're
>trying to do.
>
>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> Lawrence Statton - lawrenabae@abaluon.abaom s/aba/c/g
>Computer software consists of only two components: ones and
>zeros, in roughly equal proportions. All that is required is to
>sort them into the correct order.
>
>
>
>
>
>
>
>
>
>
>
>
>
Hi Lawrence,
It was a mistake. The module ends in .pm and not named "module", it was
only to demonstrate. And yes, I'm trying to save state information
across pages. I'll try a CGI::Session and, for now, I want only to thank
all of you for the help.
Yours,
| |
| Sergio Pires de Albuquerque 2005-04-14, 3:55 pm |
| David Dorward wrote:
>On Wed, Apr 13, 2005 at 05:14:31PM -0300, Sergio Pires de Albuquerque wrote:
>
>
>
>
>HTTP is stateless. Each time a user requests an HTTP resource provided
>by a script, that script is run from scratch. If you want to make data
>persistent from one HTTP request to another, you either have to get
>the browser to pass it back (by encoding the data in the URL
>(typically with the query string, or (with the help of a form) in a
>POST request - either way it can be accessed with the param method of
>the CGI module), or by storing it on the server and asking the client
>to pass a token about (typically in a Cookie) to identify which set of
>data belongs to the user (this is usually done with sessions:
>http://search.cpan.org/~sherzodr/CG...3.95/Session.pm )
>
>
>
>
Hi,
Thanks a lot David, I didn't know about that. I'll get that module and
try to do.
Yours,
|
|
|
|
|