navigation graphic

Resources

PHP Resources RPG Resources Debugging Resources RDi Resources Windows 10 & IBM i CL Resources Our Videos Hot Tips!

Resources

PHP

PHP & RPG Communicating Together

We recently had a request from one of our clients asking if we had any examples of calling an RPG program from a PHP script.

As you may know, PHP is an excellent programming language that coupled with our traditional programs, can provide functionality, that by default, can be difficult and at times frustrating to provide. For example, try sending an HTML email from RPG, or get RPG to use a webservice, umm….

PHP is an ideal programming language to complement our conventional programming languages, not replace them.

The majority of the examples in this article, will use the excellent XML Services, also known as the IBM i Toolkit developed by IBM and Zend.

The methods and functions included in the toolkit, really ease our development.

In the first example, we will show how we can call a RPG program, (can be any IBM i program object in fact) without passing any parameters.

Example 1

require_once 'ToolkitService.php'; /* * Setup the connection with parameters, these are: * 'InternalKey' – as says, used internally by the toolkit * 'debug' – switch on debug (always needed in my programs!) * 'plug' – the size of the XML behind the scenes */ // Create connection $conn = ToolkitService::getInstance('', '', ''); $conn->setToolkitServiceParams(array('stateless' => true)); // Seton Debug - just in case! $conn->setToolkitServiceParams(array('InternalKey' => "/tmp/fss", 'debug' => true, 'plug' => "iPLUG32K" )); $program = "FSS1"; $library = "POWERWIRE"; $parameters = NULL; // Call FSS1 in PowerWire Library $result = $conn->PgmCall($program, $library, $parameters, NULL, NULL); if ($result) { echo "Program $program successfully called "; } else { echo "Error calling $program, check logs"; }

To explain, firstly, we make a connection to our IBM i, using the XML Toolkit. This is achieved by the getInstance method of the Toolkit class.

The variable $conn is used as the Toolkit object and used to perform the methods of the toolkit.

Next we use the PgmCall method, passing the name of the program, the library it resides in, and thirdly, the parameter variable, which is null as we are not passing any variables into the program POWERWIRE/FSS1.

We could have omitted the last three parameters on our call as these are optional.

If we need to know if the call was successful we can check if there is any value in the parameter $result, returned from the program call.

How easy was that! All due to the XML Toolkit, that Zend and IBM provided.

Let us move on now and show how to pass parameters to our programs from a PHP script.

In this example, a call to our program will change the value of the User Profile parameter, so we can review it after the call.

This is contained in the array $outputParams[‘USER’].

The Toolkit will help us again with this. We have to create an array of the attributes of the parameters, type, size, etc. This can be seen using the array variable $param.

As in the previous example, we use the PgmCall method to run our program call FSS3 in library POWERWIRE.

Example 2

// Create Calling Variables $environment = "UAT"; $user = "ANDY"; $rc = ''; $program = "FSS3"; $library = "POWERWIRE"; // Leave blank for *LIBL // Add Parameters $param[] = $conn->AddParameterChar('input', 3, 'Environment', 'ENV', $environment); $param[] = $conn->AddParameterChar('both', 10, 'User Profile', 'USER', $user); $param[] = $conn->AddParameterChar('output', 1, 'Return Code', 'RC', $rc); // Execute Program $result = $conn->PgmCall($program, $library, $param); // Check the results form the call if ($result) { $outputParams = $result['io_param']; echo "User Profile: {$outputParams['USER']}. return code: {$outputParams['RC']} "; } else { echo "Error calling $program - check logs!"; }

Please note that in the above example, to save space I have not included the initial connection to our server, refer back to the first example, if you need to know how to do this.

Now we have that working as we intended, let’s get a bit more complicated.

This time we are going to pass a data structure for our RPG to receive.

Example 3

// Create Calling Variables $environment = "UAT"; $user = "ANDY"; $rc = ''; $emman = 4004; $emsur = "McKay"; $emfir = "Dave"; $program = "FSS4"; $library = "POWERWIRE"; // Leave blank for *LIBL // Add Parameters $param[] = $conn->AddParameterChar('input', 3, 'Environment', 'ENV', $environment); $param[] = $conn->AddParameterChar('both', 10, 'User Profile', 'USER', $user); $ds[] = $conn->AddParameterInt32('input', 'Employee No', 'EMMAN', $emman); $ds[] = $conn->AddParameterChar('input', 20, 'Surname', 'EMSUR', $emsur); $ds[] = $conn->AddParameterChar('input', 15, 'First Name', 'EMFIR', $emfir); $param[] = $conn->AddDataStruct($ds); $param[] = $conn->AddParameterChar('output', 1, 'Return Code', 'RC', $rc); // Execute Program $result = $conn->PgmCall($program, $library, $param, null, null);

In this example, we are passing four parameters to our RPG program. Two character strings, an integer and a data structure.

The data-structure is built, using an array, into the variable $ds, then added to the parameter list. Obviously, our RPG at the other end, must be expecting a data-structure.

All easier than you may have been expecting.

Now let us switch things around and show you how easy it is for RPG, or any other programming language on our favourite box, to call a PHP script.

In this example, our program will call a PHP script, without any parameters.

Before we continue, it is worth mentioning that the examples coming up, do not need any Apache, nor Zend, instances to be running.

This time, we have included a CL program, that performs this functionality, but could have used any program object.

Example 4

ChgVar &Msg 'Starting PHP Job - Please Wait' SndPgmMsg MsgID(Cpf9898) MsgF(QCpfMsg) MsgDta(&Msg) MsgType(*Status) ToPgmQ(*Ext) AddEnvVar EnvVar(QIBM_QSH_CMD_OUTPUT) Value('NONE') Replace(*Yes) AddEnvVar EnvVar(QIBM_QSH_CMD_ESCAPE_MSG) Value(Y) Replace(*Yes) OvrDbf StdOut ToFile( QTemp/Fss ) OvrScope(*Job) QSH Cmd('/usr/local/zendsvr6/bin/php-cli /php/followup.php') MonMsg MsgID(QSH0005 QSH0006 QSH0007) Exec(Do) SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA('QShell Command Failed!') RCVMSG MSGTYPE(*LAST) RMV(*YES) MSGDTA(&MSGDTA) MSGID(&MSGID) IF (&MSGID *EQ 'QSH0005') Do CHGVAR VAR(&RESULT) VALUE(%SST(&MSGDTA 1 4)) CHGVAR VAR(&STATUS) VALUE(%BIN(&RESULT)) CHGVAR VAR(&SIGNAL) VALUE(0) ENDDO IF (&MSGID *EQ 'QSH0006') Do CHGVAR VAR(&RESULT) VALUE(%SST(&MSGDTA 1 4)) CHGVAR VAR(&SIGNAL) VALUE(%BIN(&RESULT)) CHGVAR VAR(&STATUS) VALUE(-1) ENDDO IF (&MSGID *EQ 'QSH0007') DO CHGVAR VAR(&STATUS) VALUE(-1) CHGVAR VAR(&SIGNAL) VALUE(-1) ENDDO IF (&STATUS *NE 0) Do CHGVAR VAR(&CHARSTAT) VALUE(&STATUS) CHGVAR VAR(&CHARSIG) VALUE(&SIGNAL) SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA('QShell command failed with + status ' *CAT &CHARSTAT *CAT ' and signal ' *CAT &CHARSIG) EndDo EndDo ChgVar &Msg ( 'Training Reporting Completed' ) SndPgmMsg MsgID(Cpf9898) MsgF(QCpfMsg) MsgDta(&Msg) MsgType(*Comp)

We use the QShell command to execute our PHP script called followup.php.

This script is used by our training database to send an email of the training clients that need chasing this week. A lot easier than using RPG to try to send HTML emails even with all the OS enhancements!

And now onto the last example, our RPG program will call a PHP script passing parameters between the two.

This one is a bit different, but no more complicated thanks to the superb work by Scott Klement in allowing us to use his UNIXCMD facility. Which can be found here

My RPG program, using Scott’s examples included in his package, made life easy.

The RPG example is shown below.

Example 5

FUNIX CF F 1000 SPECIAL PGMNAME('UNIXCMD') F PLIST(UNIXPARM) USROPN FQSYSPRT O F 132 PRINTER D cmd s 5000a D Parm1 s 50 D record ds 1000 D outrec ds 132 C UNIXPARM PLIST C PARM CMD /free cmd = 'PATH=$PATH:/usr/local/zendsvr6/bin && + iconv -f 37 -t 819 | + php-cli /php/receive_parameters.php' ; open UNIX; // Send input parameters record = 'Input 1:Input 2:Input 3'; write UNIX record; // Pick up the returned parameters read UNIX record; dow not %eof(UNIX); outrec = record; write QSYSPRT outrec; read UNIX record; enddo; close UNIX; *inlr = *on;

From the code we can see that php-cli will run the PHP script /php/receive_parameters.php.

In this example, we send one parameter string, and retrieve all the parameters back.

The input parameters, are delimited with colons, and then sent to the PHP.

To receive the parameters back from the PHP, we loop back through the UNIX file to retrieve all the parameters.

The corresponding called PHP script has also been included to show what was required on the PHP side.

Example 6

// Pickup the input parameters & split into array $parm_string = fgets(STDIN); $parameters = explode(":", $parm_string); $i = 1 ; // Loop throuth each parameter & echo it back foreach ($parameters as $value) { echo "Parameter $i = " . $value . "\n"; $i ++ ; }

On the PHP side, the first thing we have to do is retrieve the parameters passed.

We use the FGETS PHP function to input the parameters to our script. As the server program used the STDIN file method, this is what we need to use.

As the RPG program passes all the parameters as a delimited string, we need to separate each element. The EXPLODE function is great for this. What a fantastic name for a function, can we have that in RPG please IBM?

Now the explode has created an array called parameters, I can loop through each of them, then, using the Echo function, return the values back to my RPG.

The spool file generated, shows the return values, which can be seen below.

File . . . . . : QSYSPRT Control . . . . . Find . . . . . . *...+....1....+....2....+... Parameter 1 = Input 1 Parameter 2 = Input 2 Parameter 3 = Input 3

Conclusion

As a general recommendation, we do not put our PHP programs we are calling from the IBM i in a web facing directory, for example www/php/htdocs.

We would suggest placing them anywhere else, for example /PHP off the IFS root. We can then place the appropriated security to these scripts knowing they cannot be accessed via Apache.

If you need a more thorough explanation of Scott’s UNIX command, visit his website.

If you have any problems with the toolkit, switch on the debugging feature and check the log, which by default is /usr/local/zendsvr6/var/log/tkit_debug.log, and don’t forget the PHP logs, they are your friend, use them.

Hopefully, this article will show you how easy it is to bring PHP into our applications.

PHP as a programming language is excellent in performing functions, that traditionally RPG program has had difficulty in processing, for example calling webservices, emails, writing to Excel etc.

Zend has done a fantastic job in providing an excellent PHP server stack on the IBM i, let us all embrace this and get on the PHP bandwagon.

  follow us on twitter   find us on facebook   follow us on linkedin   see our videos   find us on google+