Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
johna69
Product and Topic Expert
Product and Topic Expert
0 Kudos
This weblog provides a simple implementation that uses both SAPRFC and PHP SOAP to get the list of active users on a target system. You might recognize the output as being similar to SM04.

PHPRFC

PHPRFC is a sourceforge project (http://saprfc.sourceforge.net/) that provides an RFC interface to SAP Function Module in PHP. Instructions on how to setup your system for SAPRFC are covered in the weblog Getting started with PHP.

PHP SOAP

With the release of PHP5 SOAP is now available as an extension.

You can find a nice critique of the SOAP extension by IBM.

The following sample script implements both an SAPRFC call and a SOAP call to the function module TH_USER_LIST. The active users determined from both calls are displayed in result tables.

Prerequisites

The function module TH_USER_LIST is already remote enabled so the RFC connection should be no problem. For the SOAP connection you need to make sure that the service is activated in SICF (soap and wsdl11).

You must have PHP5 installed and the corresponding SAPRFC. It is important that the version numbers match. For this example I have installed PHP5.03 and the matching saprfc-1.3.3-5.0.3.Win32.zip (assuming windows).

Source Code

This is a self contained script that implements the same call using both the PHP5 SOAP extension and SAPRFC.

This is an example of getting the user list similar to the transaction SM04.

The example first get the data using SAPRFC and then using the PHP5 SOAP extension. "ld0108.wdf.sap.corp", "SYSNR"=>"18", "CLIENT"=>"220", "USER"=>"ASTILL", "PASSWD"=>"Password", "R3NAME"=>"LSR", "GROUP"=>"PUBLIC", "LANG"=>"EN", "CODEPAGE"=>"1100"); // Open the connection to the R/3 Server $rfc = saprfc_open ($login ); if (! $rfc ) { echo "RFC connection failed
"; } else { //Discover interface for function module TH_USER_LIST $fce = saprfc_function_discover($rfc,"TH_USER_LIST"); if (! $fce ) { echo "Discovering interface of function module failed"; exit; } //Fill internal tables saprfc_table_init ($fce,"LIST"); //Do RFC call of function TH_USER_LIST, for handling exceptions use saprfc_exception() $rfc_rc = saprfc_call_and_receive ($fce); if ($rfc_rc != SAPRFC_OK) { if ($rfc == SAPRFC_EXCEPTION ) { echo ("Exception raised: ".saprfc_exception($fce)); } else { echo (saprfc_error($fce)); exit; } } //Retrieve export parameters $rows = saprfc_table_rows ($fce,"LIST"); echo "

"; echo ""; for ($i=1;$i<=$rows;$i++) { $LIST[] = saprfc_table_read ($fce,"LIST",$i); } // Get a key value pair for each row while(list($num,$row) = each($LIST)) { // Extract the variables from the array into the current symbol table extract($row); echo ""; } echo "
CountClientUsernameTIDTimeTerminalType
$num$MANDT$BNAME$TID$ZEIT$TERM$TYPE
"; saprfc_function_free($fce); saprfc_close($rfc); } flush(); echo "

Now use SOAP to make the call to the Web Service
"; // Same call using the PHP Web Service try { $client = new SoapClient("wsdl11.xml", array( "login" => "ASTILL", 'trace' => 1, "password" => "Password") ); // Create the complex array to match the structure defined in the WSDL. // The function __getTypes() can help describe this structure. $res = array( "LIST" => array( "UINFO"=>array("TID"=>"", "MANDT"=>"", "BNAME"=>"", "TCODE"=>"", "TERM"=>"", "ZEIT"=>"", "MASTER"=>"", "HOSTADR"=>"", "TRACE"=>"", "EXTMODI"=>"", "INTMODI"=>"", "TYPE"=>"", "STAT"=>"", "PROTOCOL"=>"", "GUIVERSION"=>"", "RFC_TYPE"=>""))); $res = $client->TH_USER_LIST($res); // At this point we have an object. $lst = $res->LIST->item; echo "

"; echo ""; // Get a key value pair for each row while(list($num,$row) = each($lst)) { // Extract the variables from the array into the current symbol table echo ""; } echo "
CountClientUsernameTIDTimeTerminalType
$num$row->MANDT$row->BNAME$row->TID$row->ZEIT$row->TERM$row->TYPE
"; } catch (SoapFault $exception) { echo "

Exception
"; echo $exception; echo "

Request :
", htmlspecialchars($client->__getLastRequest()), "
"; echo "Response :
", htmlspecialchars($client->__getLastResponse()), "
"; } ?>

If both calls were successful you will see that the connection for the user differs in type. Type 32 for the RFC call and type 202 for the Web service.

Implementation Details

For both approaches it is fairly simple to create the initial connection.
For SAPRFC an array (PHP uses arrays for complex structures) is created containing all the connection details, this is used in the open call.

$login = array ( "ASHOST"=>"ld0108.wdf.sap.corp", "SYSNR"=>"18", "CLIENT"=>"220", "USER"=>"ASTILL", "PASSWD"=>"Password", "R3NAME"=>"LSR", "GROUP"=>"PUBLIC", "LANG"=>"EN", "CODEPAGE"=>"1100"); // Open the connection to the R/3 Server $rfc = saprfc_open ($login );

For the SOAP approach I have used the wsdl from the Web Service Browser. The wsdl file provides a complete interface definition including the connection information. My authentication details and a flag to enable tracing are the only other parameters I pass when creating the client.
$client = new SoapClient("wsdl11.xml", array( "login" => "ASTILL", 'trace' => 1, "password" => "Password") );

The wsdl file for a remote enabled function module is available from the Web Service browser. In the browser you can search for the Web Service for the remote enabled function modules.

From the result list the wsdl for the service can be retrieved. For the sake of simplicity I downloaded the wsdl file and used the local copy (installed in the same directory as the script) in my example.

Now that we have the connections we need to make the calls to the remote system. SAPRFC provides the function saprfc_function_discover to make the job of defining the interface simpler, unfortunately for the SOAP interface in 5.0.3 it is necessary to create the interface by hand even though this information is available from the wsdl file. Maybe in a future release this will be simplified.

// Create the complex array to match the structure defined in the WSDL. // The function __getTypes() can help describe this structure. $res = array( "LIST" => array( "UINFO"=>array("TID"=>"", "MANDT"=>"", "BNAME"=>"", "TCODE"=>"", "TERM"=>"", "ZEIT"=>"", "MASTER"=>"", "HOSTADR"=>"", "TRACE"=>"", "EXTMODI"=>"", "INTMODI"=>"", "TYPE"=>"", "STAT"=>"", "PROTOCOL"=>"", "GUIVERSION"=>"", "RFC_TYPE"=>"")));

For the masochists among us, SAPRFC also offers the option to create the interface details by hand rather than using the discover option.
The data returned from the call comes back in different formats. SAPRFC sticks with complex arrays, whereas SOAP combines objects and arrays for its return type. Both approaches are simple enough.
During development, to help things along, it may be useful to dump the return value to the display. This will allow you to determine how the return structure of the call has been mapped to PHP and subsequently implement the client side code more easily. I used the print_r() function for this to help me understand the structure returned from the SOAP call.

The result tables are almost identical. Looking at the first entry it can be seen that the connection type is different. For the RFC connection we have type 32 and the Web Service we have 202. This is a simple means of identifying how the connection was made.

Summary

Looking at the two implementations it is immediately obvious that the RFC implementation was easier as the user is not required to determine the complex structure for the LIST array. The implementation shown here also does not give any clue that the RFC code can be automatically generated using the script saprfc_test.php that comes included with SAPRFC.

As a comparison, the RFC implementation was quicker and easier to develop than the SOAP version, however the SOAP version does have the advantage of being compatible with any Web Service that implements the same WSDL. If you know you are always going to use SAP as the target then RFCs may be your choice, but if you are to work in a heterogenous environment then you may prefer to use the SOAP implementation.

Currently SAPRFC supports only Non-Unicode R/3 systems. If you have a unicode environment then until there is unicode support in SAPRFC, SOAP would be your weapon of choice.

4 Comments