Serializing Data to Pass between Perl and PHP

The objective of this task was to determine if data serialized by PHP could be decoded by Perl.

The first step was to create some serialized data.

In this case, the data is being used to define an interface. An associative array was used, with the first element serving to identify the type of data, and the second to contain the details of the interface. The details is an associative array where each element includes a validation string, label, help or error string, default value, and entered value. This could be extended to include i18n and l10n information, as well as a wide variety of other data.

The PHP code serializes the array, echos it, and then does a var_dump.

<?php
$aData=array(
'type'=>'Magic',
'details'=>array(
'url'=>array(
        'validation'=>'/^[\.\w\-]{1,255}$/',
        'label'=>'URL',
        'help'=>'Valid URL is letters, digits, dashes, periods',
        'default'=>'http://default.com',
        'value'=>'http://domain.com'),
'authid'=>array(
        'validation'=>'/^[\.\w\-]{1,255}$/',
        'label'=>'AuthId',
        'help'=>'Valid Id is letters, digits, dashes, periods',
        'default'=>'',
        'value'=>'')
));
$sSerialized=serialize($aData);
echo $sSerialized.PHP_EOL;
var_dump(unserialize($sSerialized));
echo PHP_EOL;

I took the serialized data echoed by PHP and pasted it into a Perl script.

It uses the PHP::Serialization module to unserialize the data. The code posted here is based on http://www.ohmpie.com/serialization, although this is a more limited example, the ohmpie.com page offers serveral differ serialization approaches.

The printAll method prints all the attributes and values for the class. Note that the values can be reached directly through the object.


#!/usr/bin/perl
# Thanks to: http://www.ohmpie.com/serialization/
use strict;
use PHP::Serialization;
use TestClass;
my $encoded='a:2:{s:4:"type";s:8:"Magic";s:7:"details";a:2:{s:3:"url";a:5:{s:10:"validation";s:19:"/^[\.\w\-]{1,255}$/";s:5:"label";s:3:"URL";s:4:"help";s:45:"Valid URL is letters, digits, dashes, periods";s:7:"default";s:18:"http://default.com";s:5:"value";s:17:"http://domain.com";}s:6:"authid";a:5:{s:10:"validation";s:19:"/^[\.\w\-]{1,255}$/";s:5:"label";s:6:"AuthId";s:4:"help";s:44:"Valid Id is letters, digits, dashes, periods";s:7:"default";s:0:"";s:5:"value";s:0:"";}}}';
my $data = PHP::Serialization::unserialize($encoded);
bless($data,'TestClass');
$data->printAll;

print "URL: ".$data->{'details'}->{'url'}->{'value'}."\n";

print "\n";

This is the TestClass package or module. It only includes the top two elements, type and details, PHP::serialize populates the object with the unserialize call.


#!/usr/bin/perl
# Thanks to: http://www.ohmpie.com/serialization/
#       http://www.perlhowto.com/iterate_through_a_hash
#       http://perl.about.com/od/packagesmodules/qt/perlcpan.htm
#       http://search.cpan.org/~bobtfish/PHP-Serialization-0.34/lib/PHP/Serialization.pm
package TestClass;
use strict; 

#The Constructor
sub new {

        my $obj = {
                type => undef,
                details => undef };
        bless($obj);

        return $obj;
}

sub printAll {
        my $key=undef;
        my %hash=undef;
        my $innerkey=undef;
        my %innerhash=undef;
        my $self=shift;
        my $value=undef;
        my $innervalue=undef;
        print "Type: " .
        $self->{'type'}."\n";
        %hash=%{$self->{'details'}};
        while (($key,$value) = each %hash )
        {
                print "key: $key\n";
                %innerhash = %{$value};
                while (($innerkey,$innervalue) = each %innerhash )
                {
                        print "\t$innerkey: $innervalue\n";
                }
        }
        print "\n";
}

1;

This approach allows data to be stored serialized in a database and read and updated by either Perl or PHP. The structure of the data can change, but the database schema would remain the same.