DbFramework::Persistent - Persistent Perl object base class


DbFramework documentation Contained in the DbFramework distribution.

Index


Code Index:

NAME

Top

DbFramework::Persistent - Persistent Perl object base class

SYNOPSIS

Top

  package Foo;
  use base qw(DbFramework::Persistent);

  package main;
  $foo = new Foo($table,$dbh,$catalog);
  $foo->attributes_h(\%foo};
  $foo->insert;
  $foo->attributes_h(\%new_foo);
  $foo->update(\%attributes);
  $foo->delete;
  $foo->init_pk;
  @foo     = $foo->select($condition,$order);
  $hashref = $foo->table_qualified_attribute_hashref;
  $code    = DbFramework::Persistent::make_class($name);

DESCRIPTION

Top

Base class for persistent objects which use a DBI database for storage. To create your own persistent object classes subclass DbFramework::Persistent (see the make_class() class method.)

SUPERCLASSES

Top

DbFramework::Util

CLASS METHODS

Top

new($table,$dbh,$catalog)

Create a new persistent object. $table is a DbFramework::Table object or the name of a database table. $dbh is a DBI database handle which refers to a database containing a table associated with $table. $catalog is a DbFramework::Catalog object.

make_class($name)

Returns some Perl code which can be used with eval() to create a new persistent object (sub)class called $name.

OBJECT METHODS

Top

Attributes in a persistent object which relate to columns in the associated table are made available through the attribute ATTRIBUTES_H. See AUTOLOAD() in DbFramework::Util for the accessor methods for this attribute.

delete()

Delete this object from the associated table based on the values of it's primary key attributes. Returns the number of rows deleted if supplied by the DBI driver.

insert()

Insert this object in the associated table. Returns the primary key of the inserted row if it is a Mysql 'AUTO_INCREMENT' column or -1.

update(\%attributes)

Update this object in the associated table. %attributes is a hash whose keys contain primary key column names and whose values will be concatenated with 'ANDs' to form a SQL 'WHERE' clause. The default values of %attributes is the hash returned by attributes_h(). Pass the current primary key attributes as an argument in %attributes when you need to update one or more primary key columns. Returns the number of rows updated if supplied by the DBI driver.

select($conditions,$order)

Returns a list of objects of the same class as the object which invokes it. Each object in the list has its attributes initialised from the values returned by selecting all columns from the associated table matching $conditions ordered by the list of columns in $order.

as_html_form()

Returns an HTML form representing the object, filled with the object's attribute values.

init_pk()

Initialise an object by setting its attributes based on the current value of the its primary key attributes.

table_qualified_attribute_hashref()

Returns a reference to a hash whose keys are the keys of %ATTRIBUTES_H with a prefix of $table, where $table is the table associated with the object and whose values are values from %ATTRIBUTES_H. This is useful for filling a template (see fill() in DbFramework::Template.)

SEE ALSO

Top

DbFramework::Util, DbFramework::Table and DbFramework::Template.

AUTHOR

Top

Paul Sharpe <paul@miraclefish.com>

COPYRIGHT

Top


DbFramework documentation Contained in the DbFramework distribution.
package DbFramework::Persistent;
use strict;
use vars qw( $TABLE $_DEBUG $VERSION %ATTRIBUTES_H $CATALOG );
$VERSION = '1.10';
use base qw(DbFramework::Util);
use Alias;
use DbFramework::Table;

## CLASS DATA

my $Debugging = 0;

my %fields = (
	      TABLE        => undef,
	      ATTRIBUTES_H => undef,
	      CATALOG      => undef,
);

##-----------------------------------------------------------------------------
## CLASS METHODS
##-----------------------------------------------------------------------------

sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my($table,$dbh,$catalog) = @_;
  my $self = bless { _PERMITTED => \%fields, %fields, }, $class;
  $table = new DbFramework::Table($table,undef,undef,$dbh)
    unless (ref($table) eq 'DbFramework::Table');
  $self->table($table->init_db_metadata($catalog));
  $self->catalog($catalog);
  return $self;
}

##-----------------------------------------------------------------------------

sub make_class {
  my($proto,$name) = @_;
  my $class = ref($proto) || $proto;

  my $code = qq{package $name;
use strict;
use base qw(DbFramework::Persistent);
};
}

##-----------------------------------------------------------------------------
## OBJECT METHODS
##-----------------------------------------------------------------------------

sub delete {
  my $self = attr shift;
  return $TABLE->delete($self->_pk_conditions);
}

#------------------------------------------------------------------------------

sub insert {
  my $self = attr shift;
  return $TABLE->insert($self->attributes_h);
}

#------------------------------------------------------------------------------

sub update {
  my $self = attr shift;
  my %attributes = defined($_[0]) ? %{$_[0]} : %{$self->attributes_h};
  # get pk attributes
  my %pk_attributes;
  for ( $TABLE->is_identified_by->attribute_names ) {
    $pk_attributes{$_} = $attributes{$_};
  }
  return $TABLE->update($self->attributes_h,$self->where_and(\%pk_attributes));
}

#------------------------------------------------------------------------------

sub select {
  my $self = attr shift;

  my @things;
  my @columns = $TABLE->attribute_names;
  for ( $TABLE->select(\@columns,shift,shift) ) {
    print STDERR "\@{\$_} = @{$_}\n" if $_DEBUG;
    # pass Table *object* to new to retain any fk relationships
    my $thing = $self->new($TABLE,$TABLE->dbh,$CATALOG);
    my %attributes;
    for ( my $i = 0; $i <= $#columns; $i++ ) {
      print STDERR "assigning $columns[$i] = $_->[$i]\n" if $_DEBUG;
      $attributes{$columns[$i]} = $_->[$i];
    }
    $thing->attributes_h([%attributes]);
    push(@things,$thing);
  }
  return @things;
}

##-----------------------------------------------------------------------------

#=head2 validate_required()

#Returns a list of attribute names which must B<not> be NULL but are
#undefined.  If I<@attributes> is undefined, validates all attributes.

#=cut

#sub validate_required {
#  my $self  = attr shift; my $table = $self->table;
#  my($attribute,@invalid);

#  my @attributes = @_ ? @_ : sort keys(%STATE);
#  foreach $attribute ( @attributes ) {
#    my $column = $table->get_column($attribute);
#    if ( ! $column->null && ! defined($self->get_attribute($attribute)) ) {
#      my $heading = $column->heading;
#      if ( $heading ) {
#	push(@invalid,$heading)
#      } else {
#	push(@invalid,$attribute);
#      }
#    }
#  }   
#  return @invalid;
#}

##-----------------------------------------------------------------------------

# return a SQL 'WHERE' clause condition consisting of primary key
# attributes and their corresponding values joined by 'AND'

sub _pk_conditions {
  my $self       = attr shift;
  my @attributes = @{$TABLE->is_identified_by->incorporates_l};
  my %values     = %{$self->attributes_h};
  my %pk_attributes;
  for ( @attributes ) {
    my $column = $_->name;
    $pk_attributes{$column} = $values{$column};
  }
  return $self->where_and(\%pk_attributes);
}

##-----------------------------------------------------------------------------

# return a SQL 'WHERE' clause condition consisting of attributes named
# after keys in %attributes and their corresponding values joined by
# 'AND'
 
sub where_and {
  my $self       = attr shift;
  my %attributes = %{$_[0]};
  my $conditions;
  for ( keys %attributes ) {
    my($attribute) = $TABLE->get_attributes($_);
    $conditions .= ' AND ' if $conditions;
    my($name,$type) = ($attribute->name,$attribute->references->type);
    $conditions .= "$name = " . $TABLE->dbh->quote($attributes{$name},$type);
  }
  print STDERR "$conditions\n" if $_DEBUG;
  $conditions;
}

##-----------------------------------------------------------------------------

#=head2 fill_template($name)

#Returns the template named I<$name> in the table associated with this
#object filled with the object's attribute values.  See
#L<DbFramework::Table/"fill_template()">.

#=cut

sub fill_template {
  my($self,$name) = (attr shift,shift);
  $TABLE->fill_template($name,$self->attributes_h);
}

##-----------------------------------------------------------------------------

sub as_html_form {
  my $self = attr shift;
  my %attributes = %{$self->attributes_h};
  my $html;
  for ( @{$self->table->contains_l} ) {
    next if $self->table->in_foreign_key($_);
    my $name = $_->name;
    $html .= "<TR><TD><STRONG>$name</STRONG></TD><TD>"
          . $_->as_html_form_field($attributes{$name})
          .  "</TD></TR>\n";
  }
  return $html;
}

#------------------------------------------------------------------------------

sub init_pk {
  my $self = attr shift;
  my @loh  = $TABLE->select_loh(undef,$self->_pk_conditions);
  $self->attributes_h([ %{$loh[0]} ]);
}

#------------------------------------------------------------------------------

sub table_qualified_attribute_hashref {
  my $self   = attr shift;
  my $t_name = $TABLE->name;
  my %tq;
  for ( keys %ATTRIBUTES_H ) { $tq{"$t_name.$_"} = $ATTRIBUTES_H{$_} }
  return \%tq;
}

1;