http://www.perlmonks.org?node_id=510913

Spidy has asked for the wisdom of the Perl Monks concerning the following question:

I'm writing some database code that involves modules, but I'm having a strange issue.

Inside my module(Main.pm), I have this piece of code:
my $dbh; sub new { $dbh = @_; }

Which is ideally supposed to take the database connection passed to it, so that the module can use it. However, I'm having some issues. Inside my main script, I do this:
# $dbname, $uname, $pword have already been filled in. my $dbh = DBI->connect("DBI:mysql:$dbname:localhost","$uname","$pword" +);

and then later on,
Main::new($dbh);

However, I'm getting an error for Main.pm, which is
Can't locate object method "selectrow_array" via package "Main" at Mai +n.pm line ***.
Anyone have any ideas?
Spidy

Replies are listed 'Best First'.
Re: Passing a database connection
by dragonchild (Archbishop) on Nov 22, 2005 at 21:33 UTC
    You retyped, you didn't cut'n'paste. You're actually calling it as Main->new( $dbh ), not Main::new( $dbh ). Using Main->new() calls it as a method and passes the receiver (in this case, 'Main') in as the first parameter.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      If the rest of your code uses OO mechanisms, you might want to recode new() so it will work as a class method rather than calling it as a non OO sub (ie. Main::new). The example below also checks that the passed in var is a valid DBI object. If you had done that in your code, you would have received an error as soon as you called the new method.
      package Main; use strict; my $dbh; sub new { my $class = shift; my $dbh = shift; UNIVERSAL::isa($dbh, 'DBI') or die "Main->new() was invoked without a valid DBI object"; }
Re: Passing a database connection
by doob (Pilgrim) on Nov 22, 2005 at 21:35 UTC
    Hey! Shouldn't my $dbh; sub new { $dbh = @_; } actually be my $dbh; sub new { $dbh = @_[0]; } ? Try it! It might work! This is because when passing arguments, the @_ has to have an index, starting at 0. If you would have two arguments, one would be @_[0](this is equal to your first argument) and another would be @_1(this is equal to your second, which you luckily don't have).
      Actually
      $dbh = $_[0];
      or
      ($dbh) = @_;
      or
      $dbh = shift(@_);
      or
      $dbh = shift;
      but yes.
      It shouldn't be @_[0] because that's the arrayslice consisting of the 0th element. If you turn warnings on, it will tell you about this. Arrayslicing is really cool. Try the following snippet:
      my @x = 0 .. 9; print "@x[2..4]\n"; print "@x[3,5,7]\n"; my @y = 4..6; print "@x[@y]\n"; @x[7..9] = @y; print "@x\n";

      The reason why you don't want to use the arrayslice form when you want to extract a single element is, while it has been special-cased to work in the case of my $x = @x[2]; (it should assign 1 and not 2), it won't work in this case:

      sub foo { wantarray ? 3 : 5; } my @x; @x[2] = foo(); my $x = foo(); print "$x[2] <-> $x\n";
      @x[2] is list context, not scalar context.

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        I see what you are saying. I made a mistake. It should've been $_[0], no?

        =d(o_o)b=

Re: Passing a database connection
by techcode (Hermit) on Nov 24, 2005 at 00:10 UTC
    I also had similar problem (needed to pass DBH around).

    The other thing you might want to look for is Singleton design pattern.

    By using it, you could connect just once in your program (on first need to do so) and every other call to function/method (get_instance or similar is prefered) would just give you your old DBH (instance of object that would contain your DBH to be precise) - no need to pass DBH around.

    You could check out Class::Singleton on CPAN. I also imagine lot's of DB abstraction modules use this ...


    Have you tried freelancing? Check out Scriptlance - I work there.