Wednesday, December 28, 2011

Calling a perl subroutine from PHP scripts

I spent a good part of my Christmas vacation in figuring out how to call a perl subroutine from a PHP script. There are several reasons why you would like to do that. The first and foremost may be because you don't want to replicate all your perl subroutines to PHP in order to use it. The other issues may be incompatibilities. The one I face is on incompatibility of my PHP version to run oracle queries which can only be solved at the sys admin level.On the other hand the perl/CGI interface for oracle just works fine.

There are 3 levels this task can be achieved:
1. We will see how to pass absolute values to perl subroutines.
2. Pass variables to perl subroutines and
3. Collect return values from the perl subroutine

Following are some points to be remembered:


1. If your perl subroutines are packed into perl packages then they are good to go (e.g; The file should begin with a package "name"; header and the end of the file should have a 1; )
2. Do not use <include "package name"> inside the PHP script.
3. Initialize a string with perl commands e.g; $command='perl -MpackageName -e "packageName::subroutine(arg,arg,arg)"'
4. Call system($command); from the php script. Do not use backticks (`)

Here is an example of passing absolute value to perl subroutine:

##Package Test ###
#!usr/bin/perl -w
package Test;

sub printNames
{
my $name1 = shift;
my $name2 = shift;

print "The names are $name1 and $name2\n";

}

1;

## save it as Test.pm

Level1: Passing an absolute value into the perl subroutine:

# test.php
<?
$command='perl -MTest -e "Test::printNames(Guest1,Guest2)"';
system($command);
?>
#Open browser and run test.php :

The names are Guest1 and Guest2



Level2: Passing a PHP variable into the perl subroutine:

<?


$arg   ="guest1 and guest2";
$arg1 ="guest3 and guest4";

$command = "perl -MTest -e 'Test::printNames("$arg","$arg1")'";
system($command);

?>

# Open browser and run the command:


The names are guest1 and guest2 and guest3 and guest4

Level3: Collecting the return values from perl subroutine as PHP array

Instead of running PHP "system" command, run "exec". Print the outputs from inside the perl subroutine, that can be captured by exec. Now the perl subroutine will undergo slight modification:

##Package Test ###
#!usr/bin/perl -w
package Test;

sub calculateVal
{
my $val1 = shift;
my $val2 = shift;

$val1 *= 20;
$val2 /= 3;

print $val1;
print $val2;

}

1;

---

<?



$arg   =10;
$arg1 =300;

$command = "perl -MTest -e 'Test::printVal($arg,$arg1)'";
$out = array();
$tmp = exec($command,$out);
print_r($out);
?>

# Output

Array 
(
[0] => 200
[1] => 100
)


NOTE: Multidimensional perl arrays can also be passed by printing the value from inside the perl subroutine.