Intuitive fluent interface for AbraGEN WebAPI, written in PHP
Author: Lukáš Křehula
Source: Github
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;
}
}
This is propably command you´ll use most.
It has a very elegant syntax, in which:
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.
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" ])
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" ]);
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" ])
Useful commands for pagination.
->limit(10)
->skip(10)
(Skips first 10 rows and selects another 10)
For data aggregation.
->groupBy("firm_id")
->groupBy("firm_id", "someOtherColumn")
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 is used for quering into other BO´s, collections or expanding referenced records.
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()
When we declare our query, there are four available commands for fetching data.
Returns full result from API, we need to iterate through it (because it is an array)
Returns first result (or null) as \stdClass.
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
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" ]
GetDocument query available commands:
Tells API, you need b2b export
specifies print report ID
specifies export ID
For fetching documents, you must always specifiy class and whereId, and then specify report or export ID.
There are three available outputs
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 has only one command available:
And then you call ->getResult()
Example:
$result = $abraApi->qr()
->expr("NxSQLSelect(‘SELECT ID FROM Storecards WHERE Name LIKE ?’)", "*test*")
->getResult();
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 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();
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:
First, you specify, from what BO and what documents you want to import
Then you specify target BO. You can also specify second parameter. It means that you are importing data into already existing BO.
You specify parameters during import. Available parameters can be found at GenDoc.chm
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.