On Jul 13, Scott R. Godin said:

The original object itself is at http://www.webdragon.net/miscel/Subscriber.pm

(the Subscriber::DB object will need $database, $username, $password, a DBI $dbh handle, and possibly a $hostname as well, in addition to the data stored in the Subscriber object, that I wish to make persistent by storing and retrieving it from the mysql database. )

The first thing you need to do is figure out the mapping from the old methods to the new methods.

One gripe I have with Subscriber.pm is that you can't set fields after the new() method, without knowing the construction of the object. It'd be nice to have a set_XXX() method which set the field to a given value. You could do this with AUTOLOAD and it'd be magic:

  AUTOLOAD {
    my $obj = shift;
    (my $method = $AUTOLOAD) =~ s/.*:://;
    if ($method =~ /^set(_\w+)/) {
      $obj->{$1} = shift;
    }
    else {
      die "no such method '$method'"
    }
  }

Then you could do

  my $who = Subscriber->new;
  $who->set_zipcode('08536');

Or you could have a set() method:

  sub set {
    my $self = shift;

    while (@_) {
      my ($field, $value) = @_;
      if (exists $self->{$field}) { $self->{$field} = $value }
      else { die "no such field '$field'" }
    }
  }

Maybe you'd want to warn() there instead of die(), I don't know. The point is, then you could write:

  my $person = Subscriber->new;
  $person->set(
    _firstname => "Jeff",
    _lastname => "Pinyan",
  );

All Subscriber::DB objects would share the DBI object -- there's no need for a billion database handles. I would also make Subscriber::DB inherit from Subscriber... for a reason I'll show you in a moment.

If you're making a NEW object (that is, not loading from the DB), perhaps you should make that the function of the 'new' method, and leave restoring objects from the DB to a different method, such as 'load' or 'restore'.

  my $x = Subscriber::DB->new(fname => "Jean", lname => "Valjean");

  # vs.

  my $y = Subscriber::DB->load(id => 24601);
  # or
  my $y = Subscriber::DB->new_from_id(24601);

These objects themselves should be hollow -- that is, they should only contain as much as is needed to retrieve their data from the database. In your case, I would guess that means just their id.

Then, when you do $y->get_greeting(), perhaps you want to do something like:

  # here's a global variable for all of Subscriber::DB
  my $greeting_sql = $DBH->prepare(q{
    SELECT salutation, firstname, lastname
    FROM subscriber_db
    WHERE id = ?
  });

  # Subscriber::DB::get_greeting
  sub get_greeting {
    my ($self) = @_;
    my $id = $self->{_id};

    $greeting_sql->bind_columns(
      \$self->{_salutation},
      \$self->{_firstname},
      \$self->{_lastname},
    );
    $greeting_sql->execute($id);

    # now here is the magic!
    return $self->SUPER::get_greeting;
  }

This is where the inheritence counts. Subscriber::DB::get_greeting merely populates enough of the hash for Subscriber::get_greeting to operate correctly. The bind_columns() call tells the SQL statement to populate those values (values in a hash) when it gets executed.

Now, if you had your Subscriber::AUTOLOAD set up, we could rewrite this as:

  sub get_greeting {
    my ($self) = @_;
    my $id = $self->{_id};

    $greeting_sql->bind_columns(\my ($salut, $fname, $lname));
    $greeting_sql->execute($id);
    $self->set_salutation($salut);
    $self->set_firstname($fname);
    $self->set_lastname($lname);

    # magic as usual
    return $self->SUPER::get_greeting;
  }

*OR*, if you had Subscriber::set() like I showed, you could do:

  sub get_greeting {
    my ($self) = @_;
    my $id = $self->{_id};

    $greeting_sql->bind_columns(\my ($salut, $fname, $lname));
    $greeting_sql->execute($id);
    $self->set(
      _salutation => $salut,
      _firstname => $fname,
      _lastname => $lname,
    );

    # magic as usual
    return $self->SUPER::get_greeting;
  }

If you want to hear more, I can give you more. Let me know if this has gone over your head though. I have a system in mind that would greatly reduce the amount of code in each of Subscriber::DB's methods that link to Subscriber's methods.

--
Jeff "japhy" Pinyan         %  How can we ever be the sold short or
RPI Acacia Brother #734     %  the cheated, we who for every service
http://japhy.perlmonk.org/  %  have long ago been overpaid?
http://www.perlmonks.org/   %    -- Meister Eckhart

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to