abragen-web-api-wrapper

Intuitive fluent interface for AbraGEN WebAPI, written in PHP

Author: Lukáš Křehula

Source: Github

Part 1: Installation of AbraGEN WebAPI wrapper

Install wrapper using composer:

composer require kaczmi/abragen-web-api-wrapper

PHP 7.0 or higher is required.

Once you installed WebAPI wrapper, you can start using it.
Don´t forget to include autoloaded files (vendor/autoload.php file)

Now, you need to specify WebAPI endpoint to create AbraApi class (facade of whole library)

It accepts four arguments (in this order):

string $host (where your Worker/Server is located, for example http://192.168.0.120:8080)
string $database (what database are we working with)
string $userName (marked as API account)
string $password

include_once(__DIR__."/vendor/autoload.php");

use AbraApi;

$abraApi = new AbraApi\AbraApi(
		"http://192.168.0.120:8080",
		"testingDatabase",
		"API",
		"secretPassword"
	);

If you are using Nette framework, there exists extension for DI container.

config.neon

extensions:
	abraConnection: AbraApi\DI\AbraApiExtension

config.local.neon

abraConnection:
	host: http://192.168.0.120:8080
	database: testingDatabase
	userName: API
	password: secretPassword

Then, you can require AbraApi class from container.
For example:

use AbraApi;

class ExampleClass {
	/** @var AbraApi\AbraApi **/
	private $abraApi;

	public function __construct(AbraApi\AbraApi $abraApi) {
		$this->abraApi = $abraApi;
	}
}

Part 2: Get() command and examples

This is propably command you´ll use most.

It has a very elegant syntax, in which:

  • You specify BO (bussiness object) to query into
  • You specify columns you need to get
  • You can specify other stuff, like condition, limit of rows, how to order your result and aggregation

So, let´s start with first example.
I need to find all store cards, which code starts with X, but i need maximum of 100 rows. Also, they should be ordered by name in ascending order (A - Z)

First, we specify BO using class($className) command

$abraApi->get()
		->class("storecards")

Now, we should select some columns. Let´s say we need to get id, name and code

$abraApi->get()
		->class("storecards")
		->select("id", "name", "code")

Then, we need to add condition - we want only storecards, which code starts with X

$abraApi->get()
		->class("storecards")
		->select("id", "name", "code")
		->where("code LIKE ?", "X*")

Also, we want to limit number of rows by 100..

$abraApi->get()
		->class("storecards")
		->select("id", "name", "code")
		->where("code LIKE ?", "X*")
		->limit(100)

..and ordered by name in ascending order

$abraApi->get()
		->class("storecards")
		->select("id", "name", "code")
		->where("code LIKE ?", "X*")
		->limit(100)
		->orderBy("name")

And that´s it, now we only need to fetch result. We will use fetchAll() command

$storecards = $abraApi->get()
		->class("storecards")
		->select("id", "name", "code")
		->where("code LIKE ?", "X*")
		->limit(100)
		->orderBy("name")
		->fetchAll();

Isn´t that easy and beautiful? :)

Of course, this is the simplest example I thought of. You can create much complex queries, and I´ll show you how.

->select(...$selects)

As you can see, I used very simple example of how to use this command.
Sometimes you want to rename column you are fetching (it could be because default name is long, confusing, etc.)

Example: I need to rename column "name" to "storecardName"
Solution: there are more ways to achieve this, every single one is valid and it depends on programmer how he uses it

->select("id", [ "storecardName" => "name" ], "code")
->select([ "id", "storecardName => "name", "code" ])
->select([ "id", "code" ], [ "storecardName" => "name" ])
->where($query, …$params)

Here, you can specify your condition. In query parameter, you can use question marks as placeholders. It supports array as parameter (useful with in() condition for example) You must also remember, selecting data is case sensitive. You need to use lower() or upper().
Also, when you want specify condition for date, you need to use expression timestamp in condition (see below in example)

->where("lower(code) LIKE ?", "x*")
->where("code in (?)", [ "XCODE001", "XCODE002" ])
->where("CreatedAt\$DATE < timestamp?", date("Y-m-d H:i:s", strtotime("-1 month")))
->where("lower(code) LIKE ? AND id in(?)", "x*", [ "XCODE001", "XCODE002" ])

There also exists an alternative - ->whereId($ids) command
Usage:

->whereId("1010000010");
->whereId([ "1010000010", "2010000010" ]);
->orderBy(...$orderBy)

So, I showed you a simplest form of ordering rows. But, what am I supposed to do when I need rows sorted in descending order?
Easy!

->orderBy([ "name" => true ])

Multiple ordering? No problem.

->orderBy([ "name" => true ], "code")

(First ordered by name in descending order, then by code in ascending order)
Or equal expression

->orderBy([ "name" => true, "code" ])
->skip($skip) and ->limit($limit)

Useful commands for pagination.

->limit(10)
->skip(10)

(Skips first 10 rows and selects another 10)

->groupBy(...$groupBy)

For data aggregation.

->groupBy("firm_id")
->groupBy("firm_id", "someOtherColumn")
->fulltext(string $fulltext) * since v1.0.1

You can also search for results via fulltext. It works just like in Abra. But you need to setup fulltext search in Abra, otherwise it won´t work.

->fulltext("my search")

Expand() command and subquering

Expand command is used for quering into other BO´s, collections or expanding referenced records.

->expand($name, $value = null)

Example: we need to expand rows of issued invoice with specific ID

$abraApi->get()
	  ->class("issuedinvoices")
	  ->select("displayname")
	  ->expand("rows")
		->select([ "productName" => "storecard_id.name" ])
		->end()
	  ->whereId("1010000010")
	  ->fetchAll()

If you want to rename "rows" collection into "issuedInvoiceRows" for example, use this syntax:

->expand("issuedInvoiceRows", "rows")

Remember, is is very important to tell command builder to ->end() expanded command (it will return you into parent query)

Example: I want to query into other BO, but there is no direct reference.

Very common - I want to get price of some StoreCard. But there is no direct reference to PriceList from StoreCard. Solution is - we use expand command and specify class().

$abraApi->get()
	  ->class("storecards")
	  ->select("name", "id")
	  ->expand("price") 
		->class("PriceLists")
		->expand("rows", "PriceRows")
			->select("amount", [ "code" => "Price_ID.Code" ])
			->orderBy("Price_ID.Code")
			->end()
		->where("storecard_id = :id")
		->end()
	  ->whereId("1010000010")
	  ->fetchAll()

Fetching data

When we declare our query, there are four available commands for fetching data.

->fetchAll()

Returns full result from API, we need to iterate through it (because it is an array)

->fetch()

Returns first result (or null) as \stdClass.

->fetchField($fieldName)

Returns specified field from first record (or null).
Example:

$storecardName = $abraApi->get()
	  ->class("storecards")
	  ->select("name")
	  ->whereId("1010000010")
	  ->fetchField("name"); // now we have name of storecard with ID 1010000010 saved in variable $storecardName
->fetchFlat($fieldName)

Returns flat array of values according to specified field in parameter.
Example:

$storecards = $abraApi->get()
			  ->class("storecards")
			  ->select("id")
			  ->where("name LIKE ?", "*test*")
		  	  ->fetchFlat("id");

Value of $storecards variable could be for example:

[ "1010000010", "2010000010", "3010000010" ]

Part 3: GetDocument() and Qr() commands

GetDocument() commands

GetDocument query available commands:

->class() *Required
->whereId() *Required
->b2b() Optional

Tells API, you need b2b export

->report($reportId) * Optionally required

specifies print report ID

->export($exportId) * Optionally required

specifies export ID

For fetching documents, you must always specifiy class and whereId, and then specify report or export ID.

GetDocument() results

There are three available outputs

->getPdf()
->getXlsx()
->getCsv()

Examples:

$pdfDoc = $abraApi->getDocument()
		        ->class("issuedinvoices")
		        ->whereId("1010000010")
		        ->report("2010000010")
		        ->getPdf();
$csvDoc = $abraApi->getDocument()
		        ->class("issuedinvoices")
		        ->whereId([ "1010000010", "2010000010" ]) // multiple invoices in one document
		        ->b2b()
		        ->export("3010000010")
		        ->getCsv();

Qr() command

Qr command has only one command available:

->expr($expression, …$params)

And then you call ->getResult()

Example:

$result = $abraApi->qr()
		     ->expr("NxSQLSelect(‘SELECT ID FROM Storecards WHERE Name LIKE ?’)", "*test*")
		     ->getResult();

Part 4: Insert(), Update() and Delete() commands

The only difference between insert() and update() commands is that you need to specify ID of row to be updated.

Both commands contains ->data(...$data) command, where you specify new values.

You can use ->data() command multiple times in query.

There are two ways you can specify data.

->data("columnName", "columnValue")

or

->data([ "columnName" => "columnValue" ])

In first example you can specify only one value.
Multiple columns specification examples:

->data([ "columnName" => "columnValue" ], [ "columnName2" => "columnValue2" ])
->data([ "columnName" => "columnValue", "columnName2" => "columnValue2" ])

Insert and update examples:

$insertResult = $abraApi->insert()
	   ->class("storecards")
	   ->data([ "name" => "new storecard", "code" => "test123" ])
	   ->execute();

$insertedId = $insertResult->getInsertedId();

$update = $abraApi->update()
		       ->class("storecards")
		       ->select("id", "name")
		       ->data("name", "old storecard")
		       ->whereId($insertedId)
	                   ->execute();

$updatedName = $update->getResult()->name;
$updatedId = $update->getUpdatedId();

You might have noticed that I used select() command in update query. Select command is available in both commands, but not required. When you don´t specify columns to be returned, wrapper automatically selects only ID of row, due to performance purposes. If you need to get some other column, remember, you always have to select id (otherwise API will return an error)

Delete() command

Delete command requires you to specify BO and ID of row to be deleted.
It also contains one specific command ->setSource(), where you can explicitly specific, which row is supposed to be deleted.

Example:

$abraApi->delete()
  ->class("storecards")
  ->whereId("3010000010")
  ->execute();

Or:

$abraApi->delete()
  ->setSource("storecards/3010000010")
  ->execute();

Part 5: Import() - importing manager * since v1.0.2

Importing manager is very useful tool - it helps you create documents.

Your number one helper will propably be GenDoc.chm, where you can easily see, what imports does Abra support.

Also you can find there a parameters you can use for importing data.

Let´s have a look at functions:

->from(string $fromBussinesObjectId, array $documentIds)

First, you specify, from what BO and what documents you want to import

->into(string $intoBussinessObjectId, ?string $documentId)

Then you specify target BO. You can also specify second parameter. It means that you are importing data into already existing BO.

->params(...$params) * Optionally required

You specify parameters during import. Available parameters can be found at GenDoc.chm

->outputDocumentData(...$data) * Optionally required

You can update new document before it is saved. This action is required when new BO has some required fields, and you cannot specify them with ->params(..)

Examples:

$abraApi->import()
		->from("receivedorders", [ "1000000001" ])
		->into("billsofdelivery")
		->params("docqueue_id", "1000000001")
		->execute();

Imports received order with ID 1000000001 into new bill of delivery. Also specifies bill of delivery document queue ID.

$abraApi->import()
		->from("ReceivedOrders", [ "1000000001" ])
		->into("IssuedInvoices")
		->params([
					"ImportDocuments" => true,
					"UndeliveredQuantity" => true,
					"DeliveryDate" => date("Y-m-d H:i:s"),
					"DocQueue_ID" => "2000000001"
				 ])
		->outputDocumentData([
					"StoreDocQueue_ID" => "3000000001"
		]);
		->execute();

Creates new issued invoice for received order and specify new issued invoice StoreDocQueue_ID.