2017 © Pedro Peláez
 

library sapphp

SAP Remote Function Modules Calls made easy using sapnwrfc.

image

avadaneidanut/sapphp

SAP Remote Function Modules Calls made easy using sapnwrfc.

  • Monday, September 5, 2016
  • by avadaneidanut
  • Repository
  • 3 Watchers
  • 8 Stars
  • 40 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 4 Versions
  • 0 % Grown

The README.md

SapPhp package

SAP Remote Function Modules Calls made easy using sapnwrfc and PHP., (*1)

Latest Stable Version Total Downloads Latest Unstable Version License, (*2)

SAP and other SAP products and services mentioned herein are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries., (*3)

Summary

Welcome to SapPhp package. This packages is not a connector, it uses php-sapnwrfc extension to handle client - server communication. This package is intended to provide a clean object oriented interface to handle extensive data extraction using RFC calls. My development plan is to extend this class with PHP Interfaces to SAP FMs (check RfcReadTable interface), (*4)

This is an early version and I expect you to raise issues and bugs and maybe give me some suggestions., (*5)

Install

Make sure you have the php-sapnwrfc extension installed., (*6)

composer require avdaneidanut/sapphp

SAP Systems details

The package uses two methods for retrievieng SAP Systems details (ashost, sysnr, description and name) by parsing files using the \SapPhp\Repository class., (*7)

  1. Parsing saplogon.ini file from: C:/Users/{currentUser}/AppData/Roaming/SAP/Common/., (*8)

  2. Parsing sapphp.xml from package root folder., (*9)

If the first method fails or returns no result the second method will be performed., (*10)

Connecting to SAP

<?php

use SapPhp\Connection;
use SapPhp\Exceptions\BoxNotFoundException;

try {
    $connection = new Connection(
        'box', // SAP Box Name
        'user', // SAP Username
        'passwd', // SAP Password
        '500' // SAP Client Code
    );
} catch(sapnwrfcConnectionException $ex) {
    // Do something if login failed.
} catch(BoxNotFoundException $ex) {
    // Do something if box doesn't exist.
}

Perform Function Module call

Let's get details about an user:, (*11)

<?php

// ... connection

// Instantiate new Function Module interface.
$function = $connection->fm(
    'BAPI_USER_GET_DETAIL', // RFC Enable FM
    true // Parse result (trim all strings and decode GUIDs)
);

// Get function description.
print_r($function->description());

// Add import parameter.
// Will trigger an \SapPhp\Exceptions\ParamNotFoundException if param is not found in function description.
$function->param('USERNAME', 'USER');

// Perform function call and retrieve result.
$result = $function->invoke();

How about getting details about an user using RFC_READ_TABLE FM? Let's go:, (*12)

<?php

// ... connection

$function = $connection->fm('RFC_READ_TABLE');

$function->param('QUERY_TABLE', 'USR01')
    ->param('OPTIONS', [
        ['TEXT' => 'BNAME = \'USER\' OR BNAME = \'USER2\' OR BNAME LIKE \'USER5*\'']
    ])
    ->param('ROWCOUNT', 5)
    ->param('DELIMITER', '~')
;

$result = $function->invoke();

Very nice, we can query a table using a SQL statement. The result from this FM is dirty, fix it with explodes and array_merge, right?, (*13)

[
  "DATA" => [
    [
      "WA" => "500~USER2      ~                    ~    ~ ~H~K~1~ ~        ~   ~            ~ ~                    ~                    ~ ~ ~0",
    ],
    [
      "WA" => "500~USER5      ~                    ~    ~ ~H~K~1~ ~        ~   ~            ~ ~                    ~                    ~ ~ ~0",
    ],
    [
      "WA" => "500~USER55      ~                    ~    ~ ~H~K~1~ ~        ~   ~            ~ ~                    ~                    ~ ~ ~0",
    ],
  ],
  "FIELDS" => [
    [
      "FIELDNAME" => "MANDT",
      "OFFSET" => "000000",
      "LENGTH" => "000003",
      "TYPE" => "C",
      "FIELDTEXT" => "Client",
    ],
    [
      "FIELDNAME" => "BNAME",
      "OFFSET" => "000004",
      "LENGTH" => "000012",
      "TYPE" => "C",
      "FIELDTEXT" => "User Name in User Master Record",
    ],
    [
      "FIELDNAME" => "STCOD",
      "OFFSET" => "000017",
      "LENGTH" => "000020",
      "TYPE" => "C",
      "FIELDTEXT" => "Start menu (old, replaced by XUSTART)",
    ],
    [
      "FIELDNAME" => "SPLD",
      "OFFSET" => "000038",
      "LENGTH" => "000004",
      "TYPE" => "C",
      "FIELDTEXT" => "Spool: Output device",
    ],
    [
      "FIELDNAME" => "SPLG",
      "OFFSET" => "000043",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Print parameter 1",
    ],
    [
      "FIELDNAME" => "SPDB",
      "OFFSET" => "000045",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Print parameter 2",
    ],
    [
      "FIELDNAME" => "SPDA",
      "OFFSET" => "000047",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Print parameter 3",
    ],
    [
      "FIELDNAME" => "DATFM",
      "OFFSET" => "000049",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Date format",
    ],
    [
      "FIELDNAME" => "DCPFM",
      "OFFSET" => "000051",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Decimal notation",
    ],
    [
      "FIELDNAME" => "HDEST",
      "OFFSET" => "000053",
      "LENGTH" => "000008",
      "TYPE" => "C",
      "FIELDTEXT" => "Host destination",
    ],
    [
      "FIELDNAME" => "HMAND",
      "OFFSET" => "000062",
      "LENGTH" => "000003",
      "TYPE" => "C",
      "FIELDTEXT" => "Default host client",
    ],
    [
      "FIELDNAME" => "HNAME",
      "OFFSET" => "000066",
      "LENGTH" => "000012",
      "TYPE" => "C",
      "FIELDTEXT" => "Default host user name",
    ],
    [
      "FIELDNAME" => "MENON",
      "OFFSET" => "000079",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Automatic Start",
    ],
    [
      "FIELDNAME" => "MENUE",
      "OFFSET" => "000081",
      "LENGTH" => "000020",
      "TYPE" => "C",
      "FIELDTEXT" => "Menu name",
    ],
    [
      "FIELDNAME" => "STRTT",
      "OFFSET" => "000102",
      "LENGTH" => "000020",
      "TYPE" => "C",
      "FIELDTEXT" => "Start menu (old, replaced by XUSTART)",
    ],
    [
      "FIELDNAME" => "LANGU",
      "OFFSET" => "000123",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Language",
    ],
    [
      "FIELDNAME" => "CATTKENNZ",
      "OFFSET" => "000125",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "CATT: Test status",
    ],
    [
      "FIELDNAME" => "TIMEFM",
      "OFFSET" => "000127",
      "LENGTH" => "000001",
      "TYPE" => "C",
      "FIELDTEXT" => "Time Format (12-/24-Hour Specification)",
    ],
  ],
  "OPTIONS" => [
    [
      "TEXT" => "TEXT' => 'BNAME = 'USER' OR BNAME = 'USER2' OR BNAME LIKE 'USER5*'",
    ],
  ],
]

But wait, how about using a FunctionModule interface that has a query builder and parses the result?, (*14)

<?php

// ... connection

// fm method will check if RfcReadTable is an FunctionModule interface Class, if so will return a new instance.
$function = $connection->fm('RfcReadTable'); 

// Let's do the same thing as before.
$result = $function->table('usr01') // set the query table
    ->where('bname', ['USER', 'USER5']) // add multiple where clause (simulating where in )
    ->orWhere('bname', 'LIKE', 'USER5*') // add custom comparation operator
    ->limit(5) // limit the result to 5 rows
    ->get() // perform function call, parse the result and return a \Illuminate\Support\Collection object.
;

print_r($result->toArray());

And the result:, (*15)

[
    [
        "MANDT" => "500",
        "BNAME" => "USER2",
        "STCOD" => "",
        "SPLD" => "",
        "SPLG" => "",
        "SPDB" => "H",
        "SPDA" => "K",
        "DATFM" => "1",
        "DCPFM" => "",
        "HDEST" => "",
        "HMAND" => "",
        "HNAME" => "",
        "MENON" => "",
        "MENUE" => "",
        "STRTT" => "",
        "LANGU" => "",
        "CATTKENNZ" => "",
        "TIMEFM" => "0",
    ],
    [
        "MANDT" => "500",
        "BNAME" => "USER5",
        "STCOD" => "",
        "SPLD" => "",
        "SPLG" => "",
        "SPDB" => "H",
        "SPDA" => "K",
        "DATFM" => "1",
        "DCPFM" => "",
        "HDEST" => "",
        "HMAND" => "",
        "HNAME" => "",
        "MENON" => "",
        "MENUE" => "",
        "STRTT" => "",
        "LANGU" => "",
        "CATTKENNZ" => "",
        "TIMEFM" => "0",
    ],
    [
        "MANDT" => "500",
        "BNAME" => "USER55",
        "STCOD" => "",
        "SPLD" => "",
        "SPLG" => "",
        "SPDB" => "H",
        "SPDA" => "K",
        "DATFM" => "1",
        "DCPFM" => "",
        "HDEST" => "",
        "HMAND" => "",
        "HNAME" => "",
        "MENON" => "",
        "MENUE" => "",
        "STRTT" => "",
        "LANGU" => "",
        "CATTKENNZ" => "",
        "TIMEFM" => "0",
    ],
]

Take a look at RfcReadTable and QueryBuilder methods., (*16)

QueryBuilder usage.

<?php

$query->where('column', 'value') // Add WHERE clause
    ->andWhere('column2,' 'value2') // AND logical operarator
    ->orWhere('column3', '<>', 'value3') // OR logical operator
    ->orWhere(function ($query) { // WHERE group
        $query->where('column11', 'value11')
            ->andWhere('column22', 'value22');
    })
    ->orWhere('column5', '<>', [1, 2, 3, 4]); // Simulate WHERE IN clause

The previous code will generate the folowing SQL query:, (*17)

    WHERE
        COLUMN = 'value' 
        AND
        COLUMN2 = 'value2'
        OR
        COLUMN3 <> 'value3'
        OR
        (
            COLUMN11 = 'value11'
            AND
            COLUMN22 = 'value22'
        )
        OR 
        (
            COLUMN5 <> '1'
            OR
            COLUMN5 <> '2'
            OR
            COLUMN5 <> '3'
            OR
            COLUMN5 <> '4'
        )

To-do

  • Aggregate multiple table results in one Collection and share the same query over multiple tables.
<?php

// ... connection & function

$rfcReadTable->table(['table1', 'table2', 'table3'], function($agregatter) {
    $aggregate->table('table1')
        ->with('table2')
        ->on('column')
        ->as('aggregated_table');
    $aggregate->table('aggregated_table', 'table3')
        ->on('column2');
})->where('column', 'value');
  • Add mode FunctionModule interfaces as RfcReadTable - Please send suggestions!

Support

I will help you ASAP if you find any issues in using this package., (*18)

The Versions

05/09 2016

dev-master

9999999-dev

SAP Remote Function Modules Calls made easy using sapnwrfc.

  Sources   Download

MIT

The Requires

  • php >=5.5.9
  • ext-sapnwrfc *

 

by Avadanei Danut

29/06 2016

dev-php7

dev-php7

SAP Remote Function Modules Calls made easy using sapnwrfc.

  Sources   Download

MIT

The Requires

 

by Avadanei Danut

07/04 2016

v0.1.1

0.1.1.0

SAP Remote Function Modules Calls made easy using sapnwrfc.

  Sources   Download

MIT

The Requires

 

by Avadanei Danut

07/04 2016

v0.1.0

0.1.0.0

SAP Remote Function Modules Calls made easy using sapnwrfc.

  Sources   Download

MIT

The Requires

 

by Avadanei Danut