This article describes the perl extension for PHP. It is intended for developers who use both languages in their projects, or who are migrating from one language to the other. It could be of general interest to other developers.
Introduction
PHP and perl are two very popular Web programming languages. They both have many libraries and extensions that can simplify the process of development, but often you can find a perl library you want, and not the corresponding library in PHP. (Perl is older then PHP, so naturally it has a larger selection of libraries and extensions.) This was the main reason that the perl extension for PHP was written.
Many large projects use both PHP and perl, with some subsystems implemented in PHP, and others in perl. Often these subsystems need to communicate with each other, and some perl modules - such as PHP::Include and PHP::Session - have been implemented to achieve this (see for more information). However, although they allow PHP session files to be read, PHP variables to be serialized and simple PHP code to be executed from within perl, there is no real communication between the two interpreters.
The PHP perl extension was implemented to allow the usage of perl code from within PHP. It is a wrapper that embeds the perl interpreter and converts data from PHP to perl and back. At the time of writing it only provides a one-way interface from PHP to perl, but in the future it could be extended to implement a full two-way interface. The perl extension allows the programmer to do the following from a PHP script:
- load and execute perl files
- evaluate perl code
- access perl variables
- call perl functions
- instantiate perl objects
- access properties of perl objects
- call methods of perl objects
All these features are accessible through a single API class called Perl
.
PHP's perl extension is available from the PECL web site at . The latest development version can be obtained with the following CVS command:
$ cvs -d :pserver:cvs.php.net:/repository co pecl/perl
|
If you have a full perl installation, the extension will work with it. If you don't have perl on board, you can still communicate with the perl interpreter through PHP by putting a copy of perl58.so or perl58.dll somewhere PHP can find it (in the PHP directory or in your system path).
Perl Interpreter in PHP
To access the perl interpreter from PHP, you must first create an instance of the Perl
class. Its constructor can receive some parameters, but we will omit
them at this point. They are necessary for working with perl objects,
but not for working with the interpreter itself.
$perl = new Perl();
|
This line of code creates an instance of the perl interpreter. It is
possible to create several instances of the interpreter, but all of
them will use the same one internally, so that all code and variables
will be shared across instances. The object $perl
can be used to execute external perl files, evaluate inline perl code, access perl variables and call perl functions.
External perl files can be loaded using the Perl::require()
method. Take a look at the following example:
Example 1 (test1.pl)
print "Hello from perl!
"
|
Example 1 (test1.php)
|
In this example perl outputs a string directly to the PHP output stream, but in some cases you will want to grab the output as a string and process it with your PHP code. This can be done using the PHP output buffering API:
Example 2 (test2.php)
|
As you can see, it works fine. Of course the same can be done with PHP's system call, but less efficiently. The system()
function will start the interpreter each time it's called, whereas $perl->eval()
uses the embedded interpreter in the same address space and doesn't need to create a new process.
As was said earlier, the PHP perl extension can evaluate inline perl
code. This method is more useful if you want to execute a small piece
of code. With the Perl::eval()
method you don't need to create several small perl files, but can instead simply embed perl code into PHP.
Example 3 (test3.php)
|
Perl::eval()
accepts only one argument - the perl code to
execute, in string format. PHP allows three different ways of writing
string literals; single quoted, double quoted or heredoc. Note that PHP
will act on the content of literal strings in the usual way before they
are passed to perl (see for details).
In the previous example we didn't receive any unexpected results from Perl::eval()
,
but we could do so. The perl interpreter can run the same code in
different contexts, and the result can be very different in those
different contexts. For example, a list returned in a scalar context
would be received as the final element of that list.
A Perl
object uses the scalar context by default, but evaluating in an array or hash context[1] requires the use of special tricks. The method eval()
should not be called directly on the perl interpreter object, but on the appropriate property (array or hash).
Example 4 (test4.php)
|
This example evaluates the same data - a list - in different contexts, and as you can see, there are three different results from that data.
Perl has several scopes of global variables (scalars $x
, arrays @x
, hashes %x
and code &x
).
PHP's perl extension allows you to access global scalar, array and hash
variables. To access scalar perl variables, just use the property with
the same name. To access array and hash variables, use the same trick
as for selecting the evaluation context.
Example 5 (test5.php)
|
As you see, here we have three variables with the same name but in different scopes, and of course all three have different values.
The perl extension allows not only reading but also writing to perl variables. You can do this by assigning a new value to the corresponding property; however, you cannot modify part of a perl array or hash. (The modification will not take effect.)
Evaluating perl variables is just one simple interaction between PHP and perl. More often we need to call a single perl function. PHP's perl extension provides a simple and elegant way to do this. You just need to call the method with the corresponding name via the interpreter, and pass parameters to it:
Example 6 (test6.php)
|
The function can receive parameters and return a scalar or complex value. As with eval()
,
any function call can be made in one of three different contexts
(scalar, array or hash), and the context can be specified in the same
way.
Perl uses packages to limit the name scope of variables and
functions, and sometimes we need to call functions or access variables
from these packages using qualified names. Such names doesn't confirm
to PHP syntax, but they can be used with the special construct ->{}
.
Example 7 (test7.php)
|
This example uses the external perl module md5
, which
is loaded during runtime. If you have a full perl installation,
downloading and installing CPAN modules is as easy as downloading a
tarball, extracting it to the perl top-level directory and typing:
cd perl
|
at the command prompt. On Windows systems you will need to replace make
with nmake
; however, this will only work if you have MSVS tools installed.
If you don't have a full perl installation - i.e. you're running
perl as a shared object - it is still possible to run perl modules once
they have been built elsewhere. The minimal environment necessary for
running them consists of the entire set of perl package management
(*.pm) files from perllib
, and the full perllibauto
and perllibDigest
directories.
The PHP Perl extension cannot call internal perl functions (print
, read
, etc); you will need to use Perl::eval()
in order to access these. For example, in order to include the minimal
module environment outlined above you would need to call:
$perl->eval("BEGIN {unshift( @INC, 'perlenv_dirpath'); }");
|
Using Perl Objects
In common with many other programming languages, perl uses an object-oriented approach, but it has no special syntax for classes. Classes are simply packages that happen to provide methods to deal with objects; methods are simply package functions that expect an object reference as the first argument; objects are simply references that 'know' which class they belong to.
The perl extension allows you to instantiate perl objects from a PHP
script, and to access their properties and methods. The same Perl
class is used for this, but this time you need to pass arguments to its
constructor. The first argument is a perl class (package) name, the
second is the optional constructor name, and any remaining arguments
are constructor-specific. If the constructor name is omitted then the
default constructor new
is used.
new Perl(string class_name [, string constructor_name [, mixed args]]);
|
The following example defines the perl class Point
with two constructors, new
and Point
.
The first constructor doesn't accept any special arguments; the second
receives initial coordinate values. The class has two properties, x
and y
, and two methods, move()
and get()
. As you can see, the method move()
moves a point to the offset specified in the arguments passed to it. The method get()
is more interesting. Depending on the context, it returns the current
coordinates as a string (in the scalar context) or as an array (in the
array context).
As with native PHP objects, you can call the methods of instantiated perl objects and access their properties. The only difference is the calling context. By default, methods are called in the scalar context. To call them in an array or hash context, use the same trick as before: the method should not be called directly on the perl object, but on a special property (array or hash).
All properties can be accessed directly (without the array or hash property). This is because perl objects can contain only scalar properties. Arrays and hashes are represented as references to them, and references are scalars in perl. Object properties can be read, written, modified and even undefined, but parts of a property cannot be modified. For example, we can't modify an element of an array property.
Example 8 (test8.php)
|
Error handling
The perl extension uses the PHP exception mechanism to report perl errors. A special exception class, PerlException
, is used for this. The following example tries to evaluate invalid perl code, and as a result Perl::eval()
throws a PerlException
:
Example 9 (test9.php)
|
Exceptions can be thrown by Perl::eval()
, Perl::require()
, or a call to a perl function, object method or constructor.
Summary
The PHP perl extension is a simple one-way binding from PHP to perl. It allows you to execute perl code from PHP, and has the ability to access perl variables, call perl functions, and instantiate perl objects.
Note that the extension is still marked EXPERIMENTAL, so your ideas and suggestions can help to make it stable and usable. Please report any problems you find with the extension to .
- Perl defines the scalar and array (list) contexts. The hash context is the same as the array (list) context, but the result is converted to an associative PHP array (hash array).
Comments
extention=perl.so to your php.ini file
What if I want to use /usr/local/bin/perl?
Do I have to decide this at pecl compile time?