Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
SPOPS::Tie(3)	      User Contributed Perl Documentation	 SPOPS::Tie(3)

       SPOPS::Tie - Simple class implementing tied hash	with some goodies

	# Create the tied hash
	use SPOPS::Tie;
	my ( %data );
	my @fields = qw( first_name last_name login birth_date );
	tie %data, 'SPOPS::Tie', $class, \@fields;

	# Store	some simple properties
	$data{first_name} = 'Charles';
	$data{last_name}  = 'Barkley';
	$data{login}	  = 'cb';
	$data{birth_date} = '1957-01-19';

	# Store	a temporary property
	$data{tmp_rebound_avg} = 11.3;

	while (	my ( $prop, $val ) = each %data	) {
	  printf( "%-15s: %s\n", $prop,	$val );

	# Note that output does	not include 'tmp_rebound_avg'
	>first_name	: Charles
	>login		: cb
	>last_name	: Barkley
	>birth_date	: 1957-01-19

	print "Rebounding Average: $data{tmp_rebound_avg}\n";

	# But you can access it	still the same
	>Rebounding Average: 11.3

       Stores data for a SPOPS object, and also	some accompanying materials
       such as whether the object has been changed and any temporary

   Checking Changed State
       You can check whether the data have changed since the last fetch	by
       either calling the method of the	SPOPS object (recommended) or asking
       for the '_changed' key from the "tied()"	object:

	# See if this object has changed
	if (tied %data){_changed} ) {; stuff...

	# Tell the object that it has changed (force)
	(tied %data){_changed} = 1;

       Note that this state is automatically tracked based on whether you set
       any property of the object, so you should never need to do this.	See
       SPOPS for more information about	the changed methods.

   Tracking Temporary Variables
       Note that this section only holds true if you have field-checking
       turned on (by passing an	arrayref of fields in the 'field' key of the
       hashref passed as the second parameter in the "tie" call).

       At times	you might wish to keep information with	the object that	is
       only temporary and not supposed to be serialized	with the object.
       However,	the 'valid property' nature of the tied	hash prevents you from
       storing information in properties with names other than those you pass
       into the	initial	call to	tie(). What to do?

       Have no fear! Simply prefix the property	with 'tmp_' (or	something
       else, see below)	and SPOPS::Tie will keep the information at the	ready
       for you:

	my ( %data );
	my $class = 'SPOPS::User';
	tie %data, 'SPOPS::Tie', $class, [ qw/ first_name last_name login / ];
	$data{first_name} = 'Chucky';
	$data{last_name}  = 'Gordon';
	$data{login}	  = 'chuckg';
	$data{tmp_inoculation} = 'Jan 16, 1981';

       For as long as the hash %data is	in scope, you can reference the
       property	'tmp_inoculation'. However, you	can only reference it
       directly. You will not see the property if you iterate through hash
       using keys or each.

   Lazy	Loading
       You can specify you want	your object to be lazy loaded when creating
       the tie interface:

	 my $fields = [	qw/ first_name last_name login life_history / ];
	 my $params = {	is_lazy_load  => 1,
			lazy_load_sub => \&load_my_variables,
			field	      => $fields };
	 tie %data, 'SPOPS::Tie', $class, $params;

   Storing Information for Internal Use
       The final kind of information that can be stored	in a SPOPS object is
       'internal' information. This is similar to temporary variables, but is
       typically only used in the internal SPOPS mechanisms -- temporary
       variables are often used	to store computed results or other information
       for display rather than internal	use.

       For example, the	SPOPS::DBI module could	allow you to create validating
       subroutines to ensure that your data conform to some sort of

	push @{	$obj->{_internal_validate} }, \&ensure_consistent_date;

       Most of the time	you will not need to deal with this, but check the
       documentation for the object you	are using.

   Field Mapping
       You can setup a mapping of fields to make an SPOPS object look like
       another SPOPS object even though	its storage is completely different.
       For instance, say we were tying a legacy	data management	of system of
       book data to a website. Our web designers do not	like to	see FLDNMS LK
       THS since they are used to the more robust capabilities of modern data

       So we can use the field mapping capabilities of "SPOPS::Tie" to make
       the objects more	palatable:

	my $obj	= tie %data, 'SPOPS::Tie', 'My::Book',
			     { field_map => { author	     =>	'AUTH',
					      title	     =>	'TTL',
					      printing	     =>	'PNUM',
					      classification =>	'CLSF' } };

       (See the	SPOPS documentation for	how to declare this in your SPOPS

       So your web designers can use the objects:

	print "Book author: $book->{author}\n",
	      "Title: $book->{title}\n";

       But the data are	actually stored	in the object (and retrieved by	an
       "each" query on the object -- be	careful) using the old,	ugly names
       'AUTH', 'TTL', 'PNUM' and 'CLSF'.

       This can	be extremely helpful not only to rename	fields for aesthetic
       reasons,	but also to make objects conform to the	same interface.

   Multivalue Fields
       Some data storage backends -- such as LDAP -- can store multiple	values
       for a single field, and "SPOPS::Tie" can	represent it.

       Three basic rules when dealing with multivalue fields:

       1.  No duplicate	values allowed.

       2.  Values are not sorted. If you need sorted values, use the tools
	   perl	provides you.

       3.  Values are always retrieved from a multivalue field as an array

       The interface for setting values	is somewhat different, so sit up
       straight	and pay	attention.

       (0) Telling SPOPS::Tie

	my $obj	= tie %data, 'SPOPS::Tie', 'My::LDAP::Person',
			     { multivalue => [ 'objectclass' ] };

       This means only the field 'objectclass' will be treated as a multivalue

       (1) Creating a new object

	my $person = My::LDAP::Person->new();
	$person->{objectclass} = [ 'inetOrgPerson', 'organizationalPerson',
				   'person' ];
	$person->{sn}	       = 'Winters';
	$person->{givenname}   = 'Chris';
	$person->{mail}	       = '';

       The property 'objectclass' here is multivalued and currently has	three
       values: 'inetOrgPerson',	'organizationalPerson',	and 'person'.

       (2) Fetching and	displaying an object

	my $person = My::LDAP::Person->fetch( '' );
	print "Person info: $person->{givenname} $person->{sn} ",
	      "(mail: $person->{mail})\n";
	print "Classes:	", join( ', ', @{ $person->{objectclass} } ), "\n";


	> Person info: Chris Winters (mail:
	> Classes: inetOrgPerson, organizationalPerson,	person

       Note that if there were no values for defined for "objectclass",	the
       value retrieval would return an arrayref. Value retrievals always
       return an array reference, even if there	are no values. This is to
       provide consistency of interface, and so	you can	always use the value
       as an array reference without cumbersome	checking to see	if the value
       is "undef".

       (3) Setting a single value

	my $person = My::LDAP::Person->fetch( '' );
	$person->{objectclass} = 'newSchemaPerson';

       The property 'objectclass' now has four values: 'inetOrgPerson',
       'organizationalPerson', 'person', and 'newSchemaPerson'.

       (4) Setting all values

	my $person = My::LDAP::Person->fetch( '' );
	$person->{objectclass} = [ 'newSchemaPerson', 'reallyNewPerson'	];

       The property 'objectclass' now has two values: 'newSchemaPerson',

       (5) Removing one	value

	my $person = My::LDAP::Person->fetch( '' );
	$person->{objectclass} = { remove => 'newSchemaPerson' };

       The property 'objectclass' now has one value: 'reallyNewPerson'.

	my $object_class_thingy	= $person->{objectclass};
	print "Object class return is a: ", ref	$object_class_thingy, "\n";


	> Object class return is a: ARRAY

       Again: when a multivalued property is retrieved it always returns an
       arrayref, even if there is only one value.

       (6) Modifying one value

	my $person = My::LDAP::Person->fetch( '' );
	$person->{objectclass} =
	     { modify => { reallyNewPerson => 'totallyNewPerson' } };

       The property 'objectclass' still	has one	value, but it has been changed
       to: 'totallyNewPerson'.

       Note: you could have gotten the same result in this example by doing:

	$person->{objectclass} = [ 'totallyNewPerson' ];

       (7) Removing all	values

	my $person = My::LDAP::Person->fetch( '' );
	$person->{objectclass} = undef;

       The property 'objectclass' now has no values.

       You can also get	the same result	with:

	$person->{objectclass} = [];

       See Tie::Hash or	perltie	for details of what the	different methods do.


       We should probably benchmark this thing to see what it can do

       None known.


       Copyright (c) 2001-2004, inc..	All rights reserved.

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

       Chris Winters  <>

perl v5.32.1			  2004-06-02			 SPOPS::Tie(3)


Want to link to this manual page? Use this URL:

home | help