The University of Mississippi runs SAP for its business and student systems.
We are early adopters of the NetWeaver Gateway product and are excited about its potential to easily expose and consume content from the SAP ERP environment. The objective of this post is to illustrate how we overcame the installation and performance related roadblocks we encountered when attempting to consume the Gateway services using PHP from an Apache web server.
Installation of OData
The platform we use for our PHP/Apache hosting is a Unix/Linux environment.
After installing per their instructions, if you are on a unix/linux system, you will receive the following error when trying to generate your proxy class:
PHP Fatal error: require_once(): Failed opening required ‘Resource\Messages.php’ (include_path=’.:/etc/php5/phplib/ODataphp’) in /etc/php5/phplib/ODataphp/Common/ACSUtil.php on line 17
This error occurs due to improper use of back-slashes as opposed to a more platform independent forward-slash. To fix this, you can directly modify the ACSUtil.php file in the Common folder. Starting with line 17, replace the back-slashes with forward-slashes so that the require_once block looks as follows:
php /etc/php5/phplib/ODataphp/PHPDataSvcUtil.php /uri=https://[USER]:[PASS]@[SAPSERVERADDRESS]/sap/opu/sdata/sap/CAMPUSDIRECTORY/ /out=/home/christopher/CAMPUSDIRECTORY.php
You will see the following output:
Done: OData Service Proxy File ‘CAMPUSDIRECTORY.php’ generated at /home/christopher
Unfortunately, the file path and name are not generated correctly, so your file does not exist under that name or in that location.
The tool will output a file in the parent folder of where you requested, with a garbled name. Since I requested the folder /home/christopher, the proxy was generated and stored in /home as you can see below:
To fix the OData library so it interprets output paths appropriately, you must modify PHPDataSvcUtil.php in the root folder of the library. Adjust the command starting with line 127 to match as follows:
A Simple Consumption Example
Our first use of NetWeaver Gateway was to allow our campus website directory to directly search and display results from our SAP system. Using the same NetWeaver Gateway services we generated a proxy from earlier, we can now achieve our goal. To test the web services, you can enter the address in a browser and verify the XML response is valid. For our service, I used the following:
Note that I am calling “zcm_campus_dir_searchCollection” with the search parameter of “name EQ ‘Reichley”.
The XML response I receive to my browser is the following:
Now that we have our service, we simply integrate the proxy we generated in the first step with the OData library. The following demonstrates one method to iterate through the data and maintain a hash array, people, of each of the results returned by our directory search.
At this point, all the SAP data returned has been consumed and resides in a PHP variable.
Performance Tuning and open_basedir
Using our test environment, we were seeing very fast response times. Pages were loading and returning our directory search results in a second or two. When we moved to our production environment, which has many user accounts with varying privileges, the average page load for an empty search was 14.3 seconds. This broke down to 12+ seconds to load the proxy element, and 2 seconds on average for the remaining including the query and response itself.
After some tracing and debugging, we were able to identify that the use of open_basedir in our production system was the element causing the OData library to run slowly. For each of the require_once PHP calls in the OData library, the system was having to pull the path from the list of system paths and then compare it against the list of open_basedir permitted folders.
To increase the performance, we adjusted the library so that we could define and pass the path from our code as an option. In the OData library, modify ./Context/ObjectContext.php so that the require_once block starting with line 18 matches the following:
Be sure and add the block shown directly above the require_once section, and add the $FILE_PATH. to all the require_once statements. This will check for the new define we will create and gracefully handle it if it is not included.
Repeat the above process for the files listed below. Add “$FILE_PATH.” in each require_once block keeping the original file names for each.
The library will now behave as usual, we have just given an extra check so that the user has the option of defining the “ODATA_PATH” manually to increase the speed but it is not required.
The next step is to modify the generated proxy class, which will have to be repeated each time a new proxy is generated. For this example, our generated proxy class is named “CAMPUSDIRECTORY.php“. Modify this file in the same fashion we did the library as seen below:
The final step is to update our PHP code that uses the generated proxy so that it defines the OData library path. Inside of our PHP file, we will add the following define statement above the require_once inclusion of CAMPUSDIRECTORY.php:
With the updates to the library implementation and integration, we were able to reduce the page load time from 14+ seconds to around 2 seconds. Loading the OData library which was taking 12+ seconds now completes in roughly 1 second and the remaining time is related to the query itself.
There are quite a few other options for defining the ODATA_PATH besides using it within the main PHP file. We have experimented using .htaccess files to define this value as well, but this method was not as strong a fit for our configuration.