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.
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 http://www.cpan.org/modules/by-module/PHP/ 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
PHP’s perl extension is available from the PECL web site at http://pecl.php.net/package/perl. The latest development version can be obtained with the following CVS command:
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.
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)
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 http://www.php.net/manual/language.types.string.php 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.
Perl object uses the scalar context by default, but evaluating in an array or hash context 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 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:
at the command prompt. On Windows systems you will need to replace
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
The PHP Perl extension cannot call internal perl functions (
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:
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.
The following example defines the perl class
Point with two constructors,
Point. The first constructor doesn’t accept any special arguments; the second receives initial coordinate values. The class has two properties,
y, and two methods,
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)
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
Example 9 (test9.php)
Exceptions can be thrown by
Perl::require(), or a call to a perl function, object method or constructor.
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 http://bugs.php.net/.
 – 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).