Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^2: global var

by tultalk (Monk)
on Apr 05, 2017 at 20:51 UTC ( [id://1187185]=note: print w/replies, xml ) Need Help??


in reply to Re: global var
in thread global var

Hi: Did not want to post tooooo much.

package manageusers; use strict; use diagnostics -verbose; use warnings; use CGI; #use Carp::Always; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use CGI qw(:standard escapeHTML); use CGI qw/:standard/; use Data::Dumper; use Digest::MD5 qw(md5_hex); #use DB_File; # persistent hash database use CGI::Session; use CGI::Cookie; #use vars qw($session_cookie1 $session_cookie2 $login_timeout); #use vars qw($session); use Mail::Sendmail; use Time::HiRes qw(usleep); use Time::Local; BEGIN { use vars qw($VERSION @ISA @EXPORT); use DBI; # $ENV{DBI_TRACE}=1; # $ENV{PERL_DBI_DEBUG}=1; require Exporter; @ISA = qw(Exporter); # exported functions @EXPORT = qw( &OpenConnection &OpenSession &ProcessLoginRequest &ProcessLostDataRequest &LoginUser &decodeEncryptedPassName &UpdateUserData &GetUserLostData &LogoutUser &GetUserSessionCookie &CheckForAuthorizedUser &Expires $attempts $adminaccess $LoggedOn_user_id &Now &CheckValidLoginChar &CheckValidEmailChar &print_md5_javascript); $VERSION = '0.0.1'; }

A good read

How to Import In other files which wish to use your module there are three basic ways for them to load your module and import its symbols: use YourModule; This imports all the symbols from YourModule's @EXPORT into the namespace of the use statement. use YourModule (); This causes perl to load your module but does not import any symbols. use YourModule qw(...); This imports only the symbols listed by the caller into their namespace. All listed symbols must be in your @EXPORT or @EXPORT_OK , else an error occurs. The advanced export features of Exporter are accessed like this, but with list entries that are syntactically distinct from symbol names.

I assume you recommend @EXPORT_OK and YourModule qw(...);

Having clarified the code, is there anything you can see that would prevent my grabbing $userid_1 correctly?

Now in reading this:

When using Exporter with the standard strict and warnings pragmas, the our keyword is needed to declare the package variables @EXPORT_OK , @EXPORT , @ISA , etc.

So now my function calls that used to work: Undefined subroutine &main::ProcessLoginRequest called at manage_users.cgi line 86.

So now I have to change all these calls to $manageusers::ProcessLoginRequest. Is that correct? Or change use manageusers; to use manageusers qw(myimportlist);

I guess posting too much is better than posting too little.

Replies are listed 'Best First'.
Re^3: global var
by stevieb (Canon) on Apr 05, 2017 at 21:01 UTC

    See GotToBTru's post to create a proper example, but from your code, I see this:

    # exported functions

    That makes me think you copy/pasted something off of the Internet, and with the lines that follow that comment, it appears it closely resembles perl4 code (or someone coding perl5 that hasn't migrated to the perl5 mindset yet. This was nearly two decades ago!).

    I feel that you need some new resources to read, research and reflect upon. Is this a project that you were forced into and are trying to adjust by chance?

      I feel that you need some new resources to read, research and reflect upon. Is this a project that you were forced into and are trying to adjust by chance?

      Yes. From 2003

      Hi: Don't we all cut and paste from the internet or our own old code or code on CD's that come with textbooks? Yes we do.

      use manageusers qw(LoggedOn_user_id);

      Software error:

      "LoggedOn_user_id" is not exported by the manageusers module
      Can't continue after import errors at update_tables-development.cgi line 30
      BEGIN failed--compilation aborted at update_tables-development.cgi line 30.
      

      BEGIN { use vars qw($VERSION @ISA @EXPORT); use DBI; # $ENV{DBI_TRACE}=1; # $ENV{PERL_DBI_DEBUG}=1; require Exporter; @ISA = qw(Exporter); # exported functions our @EXPORT_OK = qw( &OpenConnection &OpenSession &ProcessLoginRequest &ProcessLostDataRequest &LoginUser &decodeEncryptedPassName &UpdateUserData &GetUserLostData &LogoutUser &GetUserSessionCookie &CheckForAuthorizedUser &Expires $attempts $adminaccess $LoggedOn_user_id <<<<<<---------------------- &Now &CheckValidLoginChar &CheckValidEmailChar &print_md5_javascript); $VERSION = '0.0.1'; }

        What you are trying to import is not a function.

        - use manageusers qw(LoggedOn_user_id); + use manageusers qw($LoggedOn_user_id);
        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        "Don't we all cut and paste from the internet or our own old code or code on CD's that come with textbooks? Yes we do."

        No. We don't. Especially stuff from 2003.

        Things change rapidly in the tech world. You can not build something for today's world using something that came from over a decade ago, no matter what.

        You can not expect something from 2003 to act and behave today like it did then. Even in 2003, the code you've posted was outdated. If you are creating something new, you'll need to get up-to-speed on today's technology. Being an auto-mechanic by trade (but out of the industry for many years), it's like showing an example of a carburetor from a vehicle, while asking for help on a brand new fuel injected, computerized ride. I'm also a licensed residential electrician by trade, and asking about the expansion of aluminum wires in a copper socket in today's world would also be akin.

        Help may come, but with 14 year old code, you're pretty much going to be kicking a dead horse (imho).

        To further, the code you did post was broken horribly, and wouldn't even compile back then. Even on the node I'm replying to, you still close off with a brace where a parens is required.

Re^3: global var
by GotToBTru (Prior) on Apr 05, 2017 at 20:55 UTC
Re^3: global var
by Marshall (Canon) on Apr 06, 2017 at 13:27 UTC
    To clarify (I hope) a few things about "use xxx;"
    use xxx; #imports all of the symbols in @EXPORT use xxx (); #imports none of the symbols in @EXPORT #this empty list is the same as: (updated) #BEGIN { require Module } use xxx qw(OpenConnection $LoggedOn_user_id); # imports # all of the symbols in @EXPORT AND subroutine OpenConnection # AND the scalar $LoggedOn_user_id from @EXPORT_OK
    Update: Another attempt at explaining "use".
    Case 1: A plain use xxx; #imports all of the symbols in @EXPORT.

    Case2: use xxx qw(OpenConnection $LoggedOn_user_id); #imports only the function OpenConnection and the scalar $LoggedOn_user_id. Once a list (the parens) after the "use" shows up, this has the effect of making @EXPORT the same as @EXPORT_OK. In other words, the symbols in @EXPORT are not imported by default and must be explicitly imported like the symbols in @EXPORT_OK. Any combination of symbols in @EXPORT or @EXPORT_OK can go in this list after the "use".

    Case 3: (consequence of case 2), use xxx (); There is an empty list of stuff to import and nothing is imported - the automatic importing of the @EXPORT list is "Overridden".

    When you import a symbol, you can use the "short" name, e.g. print $LoggedOn_user_id;. If we "used" the manageusers module, but did not import $LoggedOn_user_id, that variable can still be accessed with the fully qualified name, print $manageusers::LoggedOn_user_id; So if you use the fully qualified name, the variable or sub name does not need to be exported (provided that you have used the module to get it loaded). Only "our" variables can be exported or accessed from another module. A "my" lexical variable cannot be. "our" puts the symbol into the package's symbol table - that means among other things that the fully qualified name is going to work. Such an operation makes no sense for a lexical scope "my" variable.

    File: manageusers.pm

    #!/usr/bin/perl use warnings; use strict; package manageusers; BEGIN { use vars qw($VERSION @ISA @EXPORT); use DBI; # $ENV{DBI_TRACE}=1; # $ENV{PERL_DBI_DEBUG}=1; require Exporter; @ISA = qw(Exporter); # exported functions our @EXPORT_OK = qw( $attempts $adminaccess $LoggedOn_user_id Now CheckValidLoginChar CheckValidEmailChar print_md5_javascript); $VERSION = '0.0.1'; } our $LoggedOn_user_id=33; our $attempts = 99; 1;
    File: testManageUsers.pl
    #!/usr/bin/perl use strict; use warnings; use manageusers qw($LoggedOn_user_id); print "$LoggedOn_user_id\n"; #prints 33 print "$manageusers::attempts \n"; #prints 99 #Note that $attempts is NOT <strike>exported</strike> imported, but still #can be accessed by the fully qualified name!
    I hope this helps. Its really early in the morning here, but I think I did this right. Run my code and then pare further questions down to just the basics and variables involved.

    Corrected "use xx ();" comment. A bit twitchy with the CTL-V this morning. Also changed commend about $attempts in the mail program. Thanks shmem.

      use xxx (); #imports all of the symbols in @EXPORT use xxx qw(OpenConnection $LoggedOn_user_id); # imports # all of the symbols in @EXPORT AND subroutine OpenConnection # AND the scalar $LoggedOn_user_id from @EXPORT_OK

      Sorry, but those two are incorrect. As per use, use Foo (); is exactly equivalent to BEGIN { require Foo }, so nothing is exported at all. When you say use Foo qw/bar/;, Exporter exports only that, regardless of what's in @EXPORT.

      Update: Hm, my posting seems to have overlapped with an update to the node.

        Not impressed with EXPORT_OK. Have spent the last 4 hours adding functions to use xxx qw(....) and screwing lots of things up. Calls to cgi? action invoked functions calls that I then had to ad.

        Not worth it??

        My underlying problem still remains with one scalar value that will not import.

        Yuck!!!

      Hi:

      Thank you for this informative reply. I had not read anywhere this explanation:

      use xxx; #imports all of the symbols in @EXPORT use xxx (); #imports all of the symbols in @EXPORT use xxx qw(OpenConnection $LoggedOn_user_id); # imports # all of the symbols in @EXPORT AND subroutine OpenConnection # AND the scalar $LoggedOn_user_id from @EXPORT_OK [download]

      I was originally used the first example and calling all the subs with manageusers::sub and I guess that is why they worked and the scalars were imported also.

      I recently took a fellows advice and changed the export to our EXPORT_OK and am now having to put the called subs by name in use xxx qw(sub1 sub2... sub10) to get those calls working again.

      I guess its back to the drawing board on this.

      I did read that it is not good to use xxx; as it imports everything into that module, even subs/scalars that are only for other modules.

      Anyway thanks for the information and with that clarification I can probably resolve my issues.

      Best regards

        imports everything into that module, even subs/scalars

        The advice in What_Not_to_Export regarding scalars is this

        Do not export variable names. Just because Exporter lets you do that, it does not mean you should.
         @EXPORT_OK = qw($svar @avar %hvar); # DON'T!
        Exporting variables is not a good idea. They can change under the hood, provoking horrible effects at-a-distance that are too hard to track and to fix. Trust me: they are not worth it. To provide the capability to set/get class-wide settings, it is best instead to provide accessors as subroutines or class methods instead.

        Which is where I think this node started with the problem

        $userid = $manageusers::LoggedOn_user_id;

        and I think you were on the right path here in eliminating the global variables

        I also changed $LoggedOn_user_id to a function call &GetLoggedOn_user_id to deliver the number to the other module and it still does not work.

        I think you now know to make it work.

        poj
        Please see my 3rd attempt at explaining this "use" business.

        One problem with importing all of the @EXPORT stuff by default is that this can cause name conflicts. Also, if a program is large and uses a lot of modules, having an explicit import list can help with figuring out later what module something is in.

        Yes, if a variable is an "our" variable, the fully qualified name will work even if that particular symbol is not exported/imported. subs/functions go into the package symbol table in any event. One aspect of this is that there is no such thing as a truly private function in Perl. It is considered very bad form to call some function that is not part of the public interface, but Perl will not stop you from shooting yourself in the foot like that. If you know the function's name, you can call it.

        Oh, another point, in the @EXPORT list, you can ditch the leading & character (that's an old Perl 4 artifact). Put "someFunction" instead of "&someFunction".

      Checked out the code you suggested and runs exactly as expected.

      Looked at my code, made sure exactly the same for the export and use and it failed exactly as before.

      Something is blocking the importing of the data through not exporting the $LoggedOn_user_id.

      I set the LoggedOn+user_id to a number to test ant did not import.

        I am glad that you ran my code and you see that it works.

        The manageusers.pm file should have the "our" declaration of $LoggedON_user_id and this "our" declaration should not appear anywhere else.

        I am not sure what your remaining problem is, but I suspect that the solution will be simple once the problem is fully understood.

        Again, try to make a very, very simple example of the problem. Forget the web server for the moment. Get your script to work from the command line.

        Your "cgi" script doesn't even need to import $LoggedON_user_id as long as it does "use manageusers ();", (which imports nothing), you can still access $manageusers::LoggedON_user_id as long as manageusers.pm has something like our $LoggedON_user_id = "default";

        In your original post you wrote 'I have global var in main unit:' and 'In another unit I have: use manageusers;'

        What do you mean by 'unit' ?. Do you have the same variable name declared in both the cgi script and the manageuser module something like this

        # cgi script use strict; our $LoggedOn_user_id = 0; # # # use manageusers qw($LoggedOn_user_id); print $LoggedOn_user_id;
        # package package manageusers; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( $LoggedOn_user_id ); our $LoggedOn_user_id = 123; 1;

        The code prints 0 not 123

        poj

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1187185]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2024-10-15 04:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.