How to: PHP on the i5 – The i5 PHP API Toolkit and Calling RPG/CL Programs
Before I begin to talk about PHP on the i5, a little history is in order. PHP was created by Rasmus Lerdorf in 1994 to replace a personal set of Perl scripts he used to maintain his website. He officially released version 1.0 in 1995 as a set of CGI binaries written in C, under the GNU General Public License. In 1997 two developers at the Israel Institute of Technology, Zeev Suraski and Andi Gutmans, re-wrote the parser releasing PHP 3.0 in June 1998. Zeev and Andi went on to create Zend Technologies, a company focused on pushing PHP for mission critical business applications. Rasmus currently works for Yahoo! and is actively involved in the development of PHP.
PHP and RPG have one thing very much in common, when they first came about they were meant to do pretty simple tasks and their names reflected that, Personal Home Page and Report Program Generator. As the years went on, both languages evolved, with RPG and PHP gaining various built-in functions (BIFs), new programming constructs, XML support, and more.
Zend provides two main components to the i5, the Zend Core and the Zend Platform. The Zend Core provides, among many things, the essentials needed to run PHP on the i5. This includes the PHP runtime, the i5 PHP Toolkit, native DB2 support, automatic security updates, a web-based administration console, and more. The Zend Platform provides addition features to the Core, including run-time code optimization, dynamic content caching, PHP/Java integration, and more.
In this article I will begin by giving an overview of the Zend Core installation. Next I will explain what the i5 PHP API Toolkit is and conclude by going through an example of calling an RPG program through PHP.
Installation
The Zend Core makes the installation of PHP on the i5 painless. To start off, create a SAVF in QGPL under the name ZCOREPROD. Then download the Zend Core for the i5/OS to your computer and transfer (via FTP) the included SAVF to your i5. There are numerous open source FTP applications available online, FileZilla is one example. Remember to do a binary FTP upload. Once uploaded, perform a RSTLICPGM command to start the installation, i.e.:
RSTLICPGM LICPGM(1ZCORE5) DEV(*SAVF) SAVF(QGPL/ZCOREPROD)
Once the installation completes, you can test everything went OK by pointing your browser to: http://
Zend also provides the Zend Studio for the i5/OS, a Java based IDE to assist in the development of PHP applications. IBM and Zend are currently working on the Eclipse PHP IDE project, with version 1.0 set to be released December 2006. For the purposes of this article, I’ll be using WDSC to work with the i5.
i5 PHP API Toolkit
The i5 PHP API Toolkit (iPAT) is an extension built into the Zend Core, giving PHP developers easy access to their i5, natively though PHP. The toolkit is broken apart into seven parts; these include Connection Management, CL Commands, Program Calls, Data Retrieval, Native File Access, System Values and Data Areas. All functions in iPAT begin with ‘i5_’ to ensure no namespace problems come about. The figure below shows the iPAT organizational layout, along with the associated functions.
Calling RPG/CL program from PHP
The lifecycle of a PHP script calling an RPG/CL program has four main steps, these are connect, prepare, execute and close. A connection first needs to be made to the i5, this is done by using the i5_connect function, and passing in as parameters the i5 IP address, a username and password. The PHP code below shows this:
$conn = i5_connect("localhost", "gpapayia", "secret");
if (!$conn) {
throw_error("i5_connect");
exit();
}
If the connection returns false, then we know something went wrong. I created a function called throw_error, which takes as input a function name and outputs the error number and associated message from the last executed command. The PHP code below shows this function:
function throw_error($func) {
echo "Error in function: ".$func." --- ";
echo "Error Number: ".i5_errno()." --- ";
echo "Error Message: ".i5_errormsg()."<br>";
}
Next, the program in question needs to be loaded into memory and prepared to be run. This is done by executing the i5_program_prepare function and passing in as parameters the name of the i5 program and a description of the inputs expected by the RPG code. Before I continue to explain this, I’ll introduce the RPG program I plan on using. For the purposes of this article, the example code I made is simple and serves only as illustration as to what can be done. The program takes as input a product id, a store location, and a price. The program updates the price by adding 10.99 and finishes. The RPG code below shows the stored procedure:
C *ENTRY PLIST
C PARM prod_id 7
C PARM store_loc 10
C PARM price 5 2
/FREE
price = price + 10.99;
*INLR = *ON;
/END-FRE
Now back to the PHP coding, once the connection is made to the i5, we need to load the given RPG program into memory and get it ready to be executed. This is done by using the i5_program_prepare function, and passing in as parameters the name of the RPG program and a description of the inputs expected. Describing the input variables may seem complicated at first glance, but it’s really is quite intuitive and straight forward. Each input variable is enclosed in an associative array by specifying the Name of the input, the IO being performed, the variable Type being passed in, and finally the Length. The PHP code below shows how this would be done. Notice how the third input, PRICE, has an IO field of I5_INOUT, since I plan on modifying this value from within the RPG code. There is no real difference between calling an RPG or CL program, just specify the correct program name in i5_program_prepare function and everything else stays the same. Again, after i5_program_prepare is executed, I check to make sure no error occurred.
$description = array(
array(
"Name"=>"PROD_ID",
"IO"=>I5_IN,
"Type"=>I5_TYPE_CHAR,
"Length"=>"7"
),
array(
"Name"=>"STORE_LOC",
"IO"=>I5_IN,
"Type"=>I5_TYPE_CHAR,
"Length"=>"10"
),
array(
"Name"=>"PRICE",
"IO"=>I5_INOUT,
"Type"=>I5_TYPE_PACKED,
"Length"=>"5.2"
),
);
$pgm = i5_program_prepare("QGPL/GEOPGRM", $description);
if (!$pgm) {
throw_error("i5_program_prepare");
exit();
}
Notice the return value from the i5_program_prepare function is stored in the variable $pgm. From this point on, any time I want to refer to my RPG program GEOPGRM, I’ll use the variable $pgm. At this moment, the program is loaded into memory and is ready to be run. To execute the program, all I have to do is call the i5_program_call function and pass as parameters the prepared program ($pgm), my input parameters and where I want the output parameters to be stored. The PHP code below shows how this would be done. As above, the input and output parameters are stored in associative arrays. Notice in the $paramOut array, I specified for each given input to the RPG program, the variable names I want to refer to after the i5_program_call completes. For PRICE, I coded in AMOUNT, so after I execute my RPG program, I can get at the PRICE result by using a local PHP variable $AMOUNT. After I execute the RPG program, I check to see if an error occurred, assuming everything went OK, I output the input/output variables from my RPG program using the PHP echo function.
$parameter = array(
"PROD_ID"=>"xyz101",
"STORE_LOC"=>"a1001",
"PRICE"=>0.00
);
$parmOut = array(
"PROD_ID"=>"PROD_ID",
"STORE_LOC"=>"STORE_LOC",
"PRICE"=>"AMOUNT",
);
$ret = i5_program_call($pgm, $parameter, $parmOut);
if (!$ret) {
throw_error("i5_program_call");
exit();
}
echo "Product Id: ".$PROD_ID."<br>";
echo "Store Location: ".$STORE_LOC."<br>";
echo "Price: ".$AMOUNT."<br>";
At this point, my program executed correctly and I am ready to close my program (unload from memory) and close my connection to the i5. This is handled through the functions i5_program_close, taking as a parameter the prepared program, and i5_close, taking as a parameter the connection. The two lines of PHP code to handle this are listed below.
i5_program_close($pgm);
i5_close($conn);
One reason why PHP has become so popular is that it makes seemingly difficult tasks easy, this in turn frees the programmer to be innovative and spend more time thinking through ideas, rather than coding. Furthermore, resources to assist PHP developers are available all over the internet, including one of the best manuals for any programming language at php.net.
PHP Source Listing
RPG Source Listing
Have a second? Check out this great Canadian Health & Living Store based in Toronto


