In diesem Artikel möchte ich euch zeigen, wie man gezielt eine RFC-Funktion bzw. genauer gesagt ein BAPI über PHP aufruft und das Ergebnis verarbeitet.
In meinem
letzten Artikel bin ich bereits darauf eingegangen, wie man grundsätzlich ein PHP-Script mit einem SAP-Server verbinden kann. Dabei habe ich als SAP-Server das Test-System von SAP verwendet. Wobei ich mit dem Begriff Test-System vorsichtig sein muss, weil damit in einer typischen SAP Drei-System-Landschaft meist auch das Qualitätssicherungs-System gemeint ist. Also ihr braucht dagegen so eine kostenlose 90-Tage Ausprobier-Version, entweder Mini-SAP oder Mini-WAS, die ihr z. B. im SAP Developer Network downloaden könnt.
Wenn man ein Datenbank-Anwendung kennenlernen will, benötigt man Testdaten. Was die Nordwind-Datenbank bei MS Access ist, ist die Flugdatenbank bei SAP Mini-WAS. Unter
diesem Link findet man übrigens eine Übersicht über die Tabellen der Flugdatenbank.
Als Ziel setzen wir uns, die Kundendaten aus Tabelle
SCUSTOM auszulesen. Dabei können wir mit PHP natürlich nicht direkt auf die Datenbanktabelle zugreifen. Stattdessen benötigen wir einen ABAP-Funktionsbaustein, den wir über RFC aufrufen und der uns die Ergebnisse zurück liefern soll. So einen FuBa könnten wir natürlich selber in ABAP programmieren. Das Problem ist, eigene Programme liegen im sog. Z-Namensraum und weichen vom SAP-Standard ab. Besser ist es, wenn man Standard-Funktionen von SAP aufrufen kann. Außerdem, warum das Rad neu erfinden? Wir haben Glück. Für die Ausgabe einer Kundenliste existiert die BAPI-Funktion
BAPI_FLCUST_GETLIST.
BAPI steht für Business Application Programming Interfaces. BAPIs gehören zum SAP Business Frameworks und stellen eine Kommunikations-Schnittstelle nach außen dar. Während klassische Funktionsbausteine explizit als Remote-Baustein deklariert werden müssen, damit sie von extern aufgerufen werden können, sind BAPIs automatisch Remote-fähig.
Nun zu unserem Script. Damit wir auf den SAP-Server zugreifen können, brauchen wir wieder die Verbindungs- und Logindaten. Für eine leichtere Wiederverwendung habe ich diese Daten in ein externes Script conf/sap_connection.conf.php ausgelagert:
//
// Verbindungsdaten zum SAP-Server
//
$sapServer = array();
// NSP
$sapServer["NSP"] = array( 'USER' => 'bcuser', // SAP User
'PASSWD' => 'minisap', // SAP User Passwort
'NSP' => 'NSP', // SAP SID
'ASHOST' => '127.0.0.1', // SAP Application Server
'SYSNR' => '00', // System Nummer
'CLIENT' => '000' // Mandant
);
?>
Im Haupt-Script wird diese Datei mit
include("conf/sap_connection.conf.php");
eingebunden.
Danach führen wir einige Vorbelegungen durch:
define("RFC_FUNCTION_NAME", "BAPI_FLCUST_GETLIST");
$rfcReturnTable = "CUSTOMER_LIST";
$rfcCon = null;
$rfcResult = array();
Zunächst mal geben wir die gewünschte BAPI-Funktion BAPI_FLCUST_GETLIST an. Diese BAPI gibt ihr Ergebnis u.a. in die Tabelle CUSTOMER_LIST zurück. Danach verbinden wir uns mit dem SAP-Server.
$rfcCon = saprfc_open($sapServer["NSP"]); // Verbindungsdaten als Array
if( !$rfcCon ) // Verbindung fehlgeschlagen
{
die( "RFC Verbindung fehlgeschlagen: " . saprfc_error() );
}
Die Variable $rfcCon erhält das Connection-Handle und muss in den folgenden Funktionen mit angegeben werden. Als nächstes registrieren wir die RFC-Funktion (also unser BAPI), die Rückgabe-Tabelle und den Import-Parameter. Wobei der Import-Parameter als Übergabe-Parameter an die RFC-Funktion zu verstehen ist.
$rfcFunction = saprfc_function_discover( $rfcCon, RFC_FUNCTION_NAME );
if( !$rfcFunction )
{
die( "RFC Funktion konnte nicht ermittelt werden" );
}
@saprfc_table_init( $rfcCon, $rfcReturnTable );
saprfc_import( $rfcFunction, "MAX_ROWS", 20 );
Es gibt zwei Möglichkeiten, die Signatur einer RFC-Funktion festzulegen. Entweder man definiert die Signatur einer RFC-Funktion direkt über saprfc_function_define() oder man ermittelt die Signatur über saprfc_function_discover() automatisch. Die erste Variante ist aufwändiger dafür schneller, die zweite Variante bequemer, dafür aber etwas weniger performant. Wie man sieht, mag ichs bequem
Ist alles korrekt festgelegt, können wir den RFC-Aufruf ausführen:
$rfcStatus = saprfc_call_and_receive( $rfcFunction );
if( $rfcStatus != SAPRC_OK )
{
if( $rfcStatus == SAP_EXCEPTION )
{
die( "RFC Exception: " . saprfc_exception( $rfcFunction ) );
}
else
{
die( "Fehler RFC-Aufruf: " . saprfc_error( $rfcFunction ) );
}
}
Hat alles geklappt, können wir die Ergebnismenge zeilenweise auslesen. Dazu ermitteln wir mit saprfc_table_rows() die Anzahl der Reihen in der Ergebnistabelle und verarbeiten dann die Tabelle über eine for-Schleife. Die einzelnen Zeilen lesen wir mit saprfc_table_read() aus und speichern diese in einem Array.
$rows = saprfc_table_rows($rfcFunction, $rfcReturnTable);
for( $i = 1; $i <= $rows; $i++ )
{
$rfcResult[$i] = saprfc_table_read( $rfcFunction, $rfcReturnTable, $i );
}
Ab jetzt können wir die Daten mit PHP so verarbeiten wie gewünscht. Z. B. könnten wir die Daten in einer Tabelle ausgeben:
<table border="0" cellpadding="3" cellspacing="0">
<tr>
<th>Kunden-ID</th>
<th>Kunden-Name</th>
<th>Straße</th>
<th>PLZ</th>
<th>Ort</th>
<th>Telefon</th>
<th>eMail</th>
</tr>
<?php
foreach( $rfcResult as $record )
{
echo "<tr>";
echo "<td>" . $record["CUSTOMERID"] . "</td>";
echo "<td>" . $record["CUSTNAME"] . "</td>";
echo "<td>" . $record["STREET"] . "</td>";
echo "<td>" . $record["POSTCODE"] . "</td>";
echo "<td>" . $record["CITY"] . "</td>";
echo "<td>" . $record["PHONE"] . "</td>";
echo "<td>" . $record["EMAIL"] . "</td>";
echo "</tr>";
}
?>
</table>
Das Ergebnis sollte dann im Browser in etwa so aussehen (Ok, ich hab hier etwas das SAP-GUI nachgebaut

):
In der
Erweiterten Ansicht dieses Artikels ist der komplette Code nochmal dargestellt.
Links:
Allgemeine Einführung in die BAPIs (CA-BFA)
BAPI List
Absicherung der SAP RFC-Schnittstelle (BSI)
Komplettes Script:
conf/sap_connection.conf.php
<?php
//
// Verbindungsdaten zum SAP-Server
//
$sapServer = array();
// NSP
$sapServer["NSP"] = array( 'USER' => 'bcuser', // SAP User
'PASSWD' => 'minisap', // SAP User Passwort
'NSP' => 'NSP', // SAP SID
'ASHOST' => '127.0.0.1', // SAP Application Server
'SYSNR' => '00', // System Nummer
'CLIENT' => '000' // Mandant
);
?>
get_flight_customers.php
<?php
// ========================================================================================================================
// Aufruf von BAPI_FLCUST_GETLIST - Liste von Flugkunden ermitteln
// ========================================================================================================================
//
// 1. Include der Verbindungsdaten
//
include("conf/sap_connection.conf.php");
//
// 2. Werte vorbelegen
//
define("RFC_FUNCTION_NAME", "BAPI_FLCUST_GETLIST");
$rfcReturnTable = "CUSTOMER_LIST";
$rfcCon = null;
$rfcResult = array();
//
// 3. Verbindung zum SAP-Server aufbauen
//
$rfcCon = saprfc_open($sapServer["NSP"]); // Verbindungsdaten als Array
if( !$rfcCon ) // Verbindung fehlgeschlagen
{
die( "RFC Verbindung fehlgeschlagen: " . saprfc_error() );
}
//
// 4. RFC-Funktion Rückgabe-Tabelle und IMPORT-Parameter registrieren
//
$rfcFunction = saprfc_function_discover( $rfcCon, RFC_FUNCTION_NAME );
if( !$rfcFunction )
{
die( "RFC Funktion konnte nicht ermittelt werden" );
}
@saprfc_table_init( $rfcCon, $rfcReturnTable );
saprfc_import( $rfcFunction, "MAX_ROWS", 20 );
//
// 5. RFC-Aufruf ausführen
//
$rfcStatus = saprfc_call_and_receive( $rfcFunction );
if( $rfcStatus != SAPRC_OK )
{
if( $rfcStatus == SAP_EXCEPTION )
{
die( "RFC Exception: " . saprfc_exception( $rfcFunction ) );
}
else
{
die( "Fehler RFC-Aufruf: " . saprfc_error( $rfcFunction ) );
}
}
//
// 6. Ergebnis verarbeiten
//
$rows = saprfc_table_rows($rfcFunction, $rfcReturnTable);
for( $i = 1; $i <= $rows; $i++ )
{
$rfcResult[$i] = saprfc_table_read( $rfcFunction, $rfcReturnTable, $i );
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<title>Liste von Flugkunden</title>
<style type="text/css">
table
{
font-family: arial, sans-serif;
font-size: 12px;
border: 1px solid #6289ae;
}
th
{
text-align: left;
background: #f2e1af;
border-bottom: 2px solid #666666;
border-right: 2px solid #666666;
border-top: 1px solid #ffffd6;
border-left: 1px solid #ffffd6;
}
td
{
background: #d9e5f2;
border-bottom: 1px solid #aeaeae;
border-right: 1px solid #aeaeae;
}
body
{
background: #cbdbea;
}
</style>
</head>
<body>
<table border="0" cellpadding="3" cellspacing="0">
<tr>
<th>Kunden-ID</th>
<th>Kunden-Name</th>
<th>Straße</th>
<th>PLZ</th>
<th>Ort</th>
<th>Telefon</th>
<th>eMail</th>
</tr>
<?php
foreach( $rfcResult as $record )
{
echo "<tr>";
echo "<td>" . $record["CUSTOMERID"] . "</td>";
echo "<td>" . $record["CUSTNAME"] . "</td>";
echo "<td>" . $record["STREET"] . "</td>";
echo "<td>" . $record["POSTCODE"] . "</td>";
echo "<td>" . $record["CITY"] . "</td>";
echo "<td>" . $record["PHONE"] . "</td>";
echo "<td>" . $record["EMAIL"] . "</td>";
echo "</tr>";
}
?>
</table>
</body>
</html>