headerDon’t let the title fool you, I’m not quite there yet. I’ve already written a few posts that dealt with integrating SAP and PHP (which you can find here and here to get you started), but I thought it was time to take it to another level. So what I’ve done here is to try and build a portal of sorts and bundled together scripts that will allow one to perform various request to a SAP system. All the scripts I’ve written so far deal with material masters in one way or another.

Controlling the access

Up till now, I have in all my scripts hard coded all the necessary logon parameters (system, user, password, etc…). Now this is fine because if I had to change my password in say 2-3 scripts that would be manageable. But let’s for a second imagine that I embark on a script writing frenzy and I write 20-30 scripts and for some reason I have to change one of the logon parameters….change 20-30 scripts – No thank you! So first up on the cards was to re-think how I pass those parameters to the various scripts so that I can correctly invoke all the necessary Remote Function Calls (RFC’s). Also if someone is going to use (God forbid) these scripts then they will probably want to have a user, use his credentials and not some generic user (and from a licensing point of view SAP will probably be happier too).

The answer to that question was easy: Ask a user to type in his SAP user and password, then check to see (SAP side) if that user exists. If yes, then he can access the portal and if not, then he can’t – simple. We also want for the user to type his credentials only once and pass them on from page to page. To this effect we’ll also start using PHP session variables so they are propagated throughout the session during which the user is logged on.

The logon parameters are now passed through PHP session variables as shown below:

  • $login = array (
  • "ASHOST"=>$_SESSION['ashost'],
  • "SYSNR"=>$_SESSION['sysnr'],
  • "CLIENT"=>$_SESSION['client'],
  • "USER"=>$_SESSION['user'],
  • "PASSWD" =>$_SESSION['passwd']);

logon

I’ve made a simple form (the server, system number and client fields have been pre-filled for the user) in which someone wishing to log on only has to input their SAP user and password. Also note that I’m trying to work at having a visually appealing content. The values typed in those fields will then be used to query SAP using the BAPI, BAPI_USER_GET_DETAIL. The script will query the SAP username. If it exists it will return the user’s firstname and lastname which we’ll use to greet him. If not it will return an error.


We’ll use the import parameter USERNAME

  • saprfc_import ($fce,”USERNAME”,$_SESSION[“user”]);

The information we want is in the export parameter ADDRESS

  • $result = saprfc_export ($fce, “ADDRESS”);

The firstname and lastname returned will be assigned to session variables also

  • $_SESSION[“lastname”] = $result[“LASTNAME”];
  • $_SESSION[“firstname”] = $result[“FIRSTNAME”];

logonokAssuming the SAP user input was correct, we will then be presented with the ‘portal’, from which we can execute all the scripts available. Notice that thanks to BAPI_USER_GET_DETAIL we can greet the user in more personalized fashion: By using his name.


The script I will be focussing on in this post is :

  • Material reports (this report allows you to query material numbers. This script (an early version of it) has already been covered in a previous post, but I will talk about it again because I’ve brought new interesting enhancements to it)
  • Material Detail I will cover in part 2 (this report allows you to have more detailed information for a given material)

The following two scripts have already been covered:

  • List material groups (You can find more information in this post)
  • Material stock requirements list (You can find more information in this post)

Last but not least the, the script Material Availability Check is still work in progress and will be part of part 3.

Material reports

As I said, this has already been partly covered in a previous post. However, what I’ve changed now is:

  • Made the script a function. I can now query material lists whenever I want
  • Made it possible to pass material codes that are numerical and alphanumerical (in the previous version only numerical values were possible). The script will auto detect if the material code is numerical or not.
  • The plant code is no longer hard coded but fetched from within SAP in real time.
  • Made the code a little faster

Numerical and non numerical values

In the previous version of this script it had been coded in such a way that you could only input numerical values. Passing numerical and non numerical material codes is now possible. This is achieved thanks to a nice PHP function is_numeric. Basically whatever the material number passed the script will check to see if it is numerical or not. If it is, it will append the material number by adding as many zeroes as necessary so as tho have the material number expressed on 18 characters. If it is not a numerical value it will pass the number to the script unaltered. So we have :

  • $matnumlength = 18;
  • if ( is_numeric($matnrlow) ){
  • for ($i = 0 ; $i = ($matnumlength – strlen($matnrlow)) ; $i++) {
  • $matnrlow = “0” . $matnrlow;
  • }

Needless to say that you can also mix numerical and alphanumerical values.

You can query numerical values

num

Or mix types.

mix

Making the code faster

I have no scientific proof to go with that statement, it’s just my impression that execution is improved. What I’ve done is to add supplementary statements in the ‘table_append’ section of the script. It now looks like this:

  • saprfc_table_append ($fce,”MATNRSELECTION”, array
  • (“SIGN”=>”I”,”OPTION”=>”BT”,”MATNR_LOW”=>$matnrlow,”MATNR_HIGH”=>$matnrhigh));
  • saprfc_table_append ($fce,”MATERIALSHORTDESCSEL”, array
  • (“SIGN”=>”E”,”OPTION”=>”CP”,”DESCR_LOW”=>”*”,”DESCR_HIGH”=>””));
  • saprfc_table_append ($fce,”PLANTSELECTION”, array
  • (“SIGN”=>”I”,”OPTION”=>”EQ”,”PLANT_LOW”=>$plant,”PLANT_HIGH”=>$plant));

Basically I’ve added the MATERIALSHORTDESCSEL table and I’ve added the PLANT_HIGH parameter to the PLANTSELECTION table.

Retrieving the plant code dynamically

The enhancement here is that the plant code is now retrieved dynamically from SAP. In my previous post I said that it could be retrieved from a MySQL database…but not everybody uses or wishes to use a database to store that information (especially considering that SAP has that information). Now I do not know of a function that allows to query specifically the plant code so I’ve had to resort to the function RFC_READ_TABLE (and before I get flamed for this, yes I know I should not use it – read OSS note 382318).
In SAP the plant code is stored in a table T001W. If I use the function RFC_READ_TABLE in SAP and query the table T001W we have.

Query the table:
query

And the result:
result

What we are interested in retrieving is the plant code and the plant description. The plant code we want because that is what we need to pass to the various BAPI’s and FM’s we are using and the plant description we want so as to build a select list that the user can better understand (but that could be changed).

So we have the following to query table T001W:

  • saprfc_import ($fce,”QUERY_TABLE”,”T001W”);
  • saprfc_import ($fce,”DELIMITER”,”/”);

And we return the following to build a select list with the plant code and description:

  • $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; }
  • $data_row = saprfc_table_rows ($fce,”DATA”);
  • for($i=1; $i<=$data_row ; $i++){
  • $DATA = saprfc_table_read ($fce,”DATA”,$i);
  • $plantinfo = SPLIT(“/”,$DATA[‘WA’]);
  • $plantcode = $plantinfo[1]; // This is the plant code
  • $plantname = $plantinfo[2]; // This is the plant description

In our script we have a nice list of plants that are valid in SAP!
plant.

Making a function file

At this point, I should also mention that one of the things I’ve changed here is to build a functions file. Literally, a file in which I will store all the functions that I will call upon, on a recurring basis. For example, say I need to to retrieve the plant code in 10 of my scripts, why copy/paste the same code 10 times when you can code the function once and make a call to it 10 times – makes sense right! All I have to do then is to call them by referencing them like function do_the_foo(). So easy, why did I not think of it sooner.

The code & feedback

As usual, the code is released under Creative Commons License:

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.

I should maybe also mention that these tests have been made using an HP (Compaq nc6220) laptop running on MS Windows XP Pro, the Apache server version 1.3.33 and the PHP scripting engine in version 4.3.10 and of course the SAPRfc library (the Apache/PHP install was that installed via the EasyPhp package). SAP side I was using SAP ERP ECC (ERP Central Component) 5.0.

Some code

You can grab my read_plant_code() function here. If you can improve on this code (which should not be too difficult), give back to the community and post your findings. Comments and suggestions are also very welcome.

If you want the complete codes to date with the images, then drop a comment at the bottom of this post (don’t use the contact page for that). You can safely leave your mail in the intended field as it will not be published .

Privacy Preference Center