PHPackages                             salesrender/plugin-component-api-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. salesrender/plugin-component-api-client

ActiveLibrary[API Development](/categories/api)

salesrender/plugin-component-api-client
=======================================

SalesRender plugin API client component

0.6.10(1y ago)01.1k↓100%3proprietaryPHPPHP ^7.4.0

Since Jul 26Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/SalesRender/plugin-component-api-client)[ Packagist](https://packagist.org/packages/salesrender/plugin-component-api-client)[ RSS](/packages/salesrender-plugin-component-api-client/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (6)Versions (27)Used By (3)

salesrender/plugin-component-api-client
=======================================

[](#salesrenderplugin-component-api-client)

GraphQL API client component for the SalesRender plugin ecosystem. Provides a fault-tolerant HTTP client with automatic retry logic, pagination support, and an abstract iterator for fetching large datasets page by page.

Installation
------------

[](#installation)

```
composer require salesrender/plugin-component-api-client
```

Requirements
------------

[](#requirements)

- PHP &gt;= 7.4
- Dependencies:

PackageVersionPurpose`salesrender/plugin-component-guzzle`^0.3Shared Guzzle HTTP client singleton`softonic/graphql-client`^1.2GraphQL response parsing`adbario/php-dot-notation`^2.2Dot-notation access to nested arrays`xakepehok/array-graphql`^0.0.1PHP array to GraphQL query conversionKey Classes
-----------

[](#key-classes)

### `ApiClient`

[](#apiclient)

**Namespace:** `SalesRender\Plugin\Components\ApiClient`

Sends GraphQL queries to the SalesRender API with automatic retry on server errors (5xx). Uses the shared Guzzle instance from [`plugin-component-guzzle`](https://github.com/SalesRender/plugin-component-guzzle).

Method / PropertySignatureDescription`__construct``(string $endpoint, string $token, int $maxRequestAttempts = 10, int $attemptsDelay = 10)`Create a client for the given API endpoint and auth token`query``(string $query, ?array $variables): Response`Execute a GraphQL query/mutation and return the parsed response`$lockId``public static ?string $lockId = null`Optional lock ID sent as `X-LOCK-ID` header for order locking**Retry behavior:** On a `ServerException` (HTTP 5xx), the client sleeps for `$attemptsDelay` seconds and retries. It performs up to `$maxRequestAttempts` attempts. After exhausting retries, the final request is made without catching exceptions. The request timeout is 60 seconds.

### `ApiFilterSortPaginate`

[](#apifiltersortpaginate)

**Namespace:** `SalesRender\Plugin\Components\ApiClient`

Value object that encapsulates filters, sorting, and pagination state for API fetcher queries.

MethodSignatureDescription`__construct``(?array $filters, ?ApiSort $sort, ?int $pageSize)`Create FSP with filters, optional sort, and page size`getFilters``(): ?array`Return the filters array`getSort``(): ?ApiSort`Return the sort configuration`getPageSize``(): ?int`Return items per page`getPageNumber``(): int`Return the current page number (starts at 1)`setPageNumber``(int $pageNumber): void`Set the current page number`incPageNumber``(): void`Increment the current page number by 1### `ApiSort`

[](#apisort)

**Namespace:** `SalesRender\Plugin\Components\ApiClient`

Value object representing a sort field and direction.

Method / ConstantSignatureDescription`__construct``(string $field, string $direction)`Create sort; direction must be `ASC` or `DESC``getField``(): string`Return the field name to sort by`getDirection``(): string`Return the sort direction`ASC``const 'ASC'`Ascending sort direction`DESC``const 'DESC'`Descending sort direction### `ApiFetcherIterator` (abstract)

[](#apifetcheriterator-abstract)

**Namespace:** `SalesRender\Plugin\Components\ApiClient`

Abstract iterator that automatically paginates through a GraphQL fetcher endpoint. Implements `Iterator` and `Countable`. Subclasses define the query shape and identity extraction.

MethodSignatureDescription`__construct``(array $fields, ApiClient $client, ApiFilterSortPaginate $fsp, bool $preventPaginationOverlay = true, int $limit = null)`Create iterator with field selection, client, and FSP`setOnBeforeBatch``(callable $onBeforeBatch): void`Set callback invoked before each page fetch`setOnAfterBatch``(callable $onAfterBatch): void`Set callback invoked after each page is consumed`count``(): int`Return total items count (respecting limit); triggers a count query on first call`current``(): mixed`Return the current item array`key``(): string`Return the identity of the current item`valid``(): bool`Check if the current position is valid`rewind``(): void`Reset the iterator to the first page**Abstract methods (must be implemented by subclasses):**

MethodSignatureDescription`getQuery``(array $fields): string`Return the GraphQL query string for the given fields`getQueryPath``(): string`Return the dot-notation path to the fetcher in the response (e.g. `'ordersFetcher'`)`getIdentity``(array $array): string`Extract a unique identity string from an item**Constants:**

ConstantValueDescription`SORT_LIMIT``5000`Sorting is only applied when the total count is at or below this threshold**Pagination overlay prevention:** When `$preventPaginationOverlay` is `true` (default), the iterator tracks seen item identities and filters out duplicates that may appear when data changes between page fetches.

Usage Examples
--------------

[](#usage-examples)

### Basic GraphQL Query

[](#basic-graphql-query)

From real plugin handlers (`plugin-macros-fields-cleaner`, `plugin-macros-excel`, `plugin-macros-status-changer`):

```
use SalesRender\Plugin\Components\Access\Token\GraphqlInputToken;
use SalesRender\Plugin\Components\ApiClient\ApiClient;
use Adbar\Dot;

$token = GraphqlInputToken::getInstance();
$client = new ApiClient(
    "{$token->getBackendUri()}companies/{$token->getPluginReference()->getCompanyId()}/CRM",
    (string) $token->getOutputToken()
);

// Query
$query = get('company.currency');
```

### GraphQL Mutation

[](#graphql-mutation)

From `plugin-macros-status-changer`:

```
$mutation =  [
        'id' => $orderId,
        'statusId' => $targetStatus,
    ]
]);

if ($response->hasErrors()) {
    foreach ($response->getErrors() as $error) {
        // handle error: $error['message']
    }
}
```

### Using the Lock ID

[](#using-the-lock-id)

From `plugin-core-logistic` (`BatchLockTrait`):

```
use SalesRender\Plugin\Components\Batch\Batch;
use Adbar\Dot;

// Set a lock ID on the API client to lock orders during batch processing
$batch->getApiClient()::$lockId = $this->lockId;
$client = $batch->getApiClient();

$query = '
    mutation($id: ID!, $timeout: Int!) {
      lockMutation {
        lockEntity(input: { entity: { entity: Order, id: $id }, timeout: $timeout })
      }
    }
';

$response = new Dot($client->query($query, [
    'id' => $orderId,
    'timeout' => $timeout,
])->getData());

$isLocked = $response->get('lockMutation.lockEntity', false);
```

### Implementing an OrdersFetcherIterator

[](#implementing-an-ordersfetcheriterator)

From `plugin-core-logistic` and `plugin-macros-example`:

```
use SalesRender\Plugin\Components\ApiClient\ApiFetcherIterator;
use XAKEPEHOK\ArrayGraphQL\ArrayGraphQL;

class OrdersFetcherIterator extends ApiFetcherIterator
{
    protected function getQuery(array $fields): string
    {
        return '
            query($pagination: Pagination!, $filters: OrderSearchFilter, $sort: OrderSort) {
                ordersFetcher(pagination: $pagination, filters: $filters, sort: $sort) '
                . ArrayGraphQL::convert($fields) .
            '}
        ';
    }

    protected function getQueryPath(): string
    {
        return 'ordersFetcher';
    }

    protected function getIdentity(array $array): string
    {
        return $array['id'];
    }
}
```

### Iterating Over Orders

[](#iterating-over-orders)

From `plugin-macros-excel` (`ExcelHandler`):

```
use SalesRender\Plugin\Components\Batch\Batch;

/** @var Batch $batch */
$orderFields = [
    'orders' => [
        'id',
        'status' => ['id'],
        'createdAt',
        'cart' => ['total'],
    ]
];

$ordersIterator = new OrdersFetcherIterator(
    $orderFields,
    $batch->getApiClient(),
    $batch->getFsp()
);

// Get total count (triggers a count-only query on first call)
$total = count($ordersIterator);

// Iterate through all pages automatically
foreach ($ordersIterator as $id => $order) {
    // $id is the order ID (from getIdentity)
    // $order is the full order data array
}
```

### Creating ApiFilterSortPaginate

[](#creating-apifiltersortpaginate)

From `plugin-core` (`BatchPrepareAction`):

```
use SalesRender\Plugin\Components\ApiClient\ApiFilterSortPaginate;
use SalesRender\Plugin\Components\ApiClient\ApiSort;

$filters = ['include' => ['ids' => [1, 2, 3]]];
$sort = new ApiSort('createdAt', ApiSort::DESC);
$fsp = new ApiFilterSortPaginate($filters, $sort, 100);

// Or without sort and filters
$fsp = new ApiFilterSortPaginate(null, null, 50);
```

API Reference
-------------

[](#api-reference)

### How ApiFetcherIterator Builds Variables

[](#how-apifetcheriterator-builds-variables)

The iterator automatically constructs GraphQL variables from the `ApiFilterSortPaginate` object:

```
{
  "pagination": {
    "pageNumber": 1,
    "pageSize": 100
  },
  "filters": { "...your filters..." },
  "sort": {
    "field": "createdAt",
    "direction": "DESC"
  }
}
```

- **Pagination** is always included.
- **Filters** are included only when `getFilters()` returns a non-empty value.
- **Sort** is included only when the total count is &lt;= `SORT_LIMIT` (5000) and sort is configured. This prevents expensive sorted queries on large datasets.

### Getting ApiClient from Batch

[](#getting-apiclient-from-batch)

The `Batch` model (from [`plugin-component-batch`](https://github.com/SalesRender/plugin-component-batch)) provides a convenience method that constructs an `ApiClient` pointed at the correct company CRM endpoint:

```
$client = $batch->getApiClient();
// Equivalent to:
// new ApiClient(
//     $token->getBackendUri() . "companies/{$token->getCompanyId()}/CRM",
//     (string) $token->getOutputToken()
// );
```

See Also
--------

[](#see-also)

- [salesrender/plugin-component-batch](https://github.com/SalesRender/plugin-component-batch) -- Batch processing (uses ApiClient and ApiFilterSortPaginate)
- [salesrender/plugin-component-guzzle](https://github.com/SalesRender/plugin-component-guzzle) -- Shared Guzzle HTTP client singleton
- [softonic/graphql-client](https://packagist.org/packages/softonic/graphql-client) -- Underlying GraphQL response builder
- [xakepehok/array-graphql](https://packagist.org/packages/xakepehok/array-graphql) -- PHP array to GraphQL field selection converter

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance70

Regular maintenance activity

Popularity17

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 57.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~77 days

Recently: every ~187 days

Total

26

Last Release

496d ago

PHP version history (3 changes)0.0.1PHP &gt;=7.1.0

0.5.0PHP &gt;=7.4.0

0.6.9PHP ^7.4.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/6140af7bf37913fbad3d596efa1376ede23a55ac226a15b61857f4e58fc26c22?d=identicon)[SalesRender](/maintainers/SalesRender)

---

Top Contributors

[![IvanKalashnikov](https://avatars.githubusercontent.com/u/6877306?v=4)](https://github.com/IvanKalashnikov "IvanKalashnikov (4 commits)")[![XAKEPEHOK](https://avatars.githubusercontent.com/u/3051649?v=4)](https://github.com/XAKEPEHOK "XAKEPEHOK (2 commits)")[![disami115](https://avatars.githubusercontent.com/u/45440000?v=4)](https://github.com/disami115 "disami115 (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/salesrender-plugin-component-api-client/health.svg)

```
[![Health](https://phpackages.com/badges/salesrender-plugin-component-api-client/health.svg)](https://phpackages.com/packages/salesrender-plugin-component-api-client)
```

###  Alternatives

[google/apiclient

Client library for Google APIs

9.8k186.9M887](/packages/google-apiclient)[webonyx/graphql-php

A PHP port of GraphQL reference implementation

4.7k75.4M276](/packages/webonyx-graphql-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k90.6M251](/packages/twilio-sdk)[knplabs/github-api

GitHub API v3 client

2.2k15.3M171](/packages/knplabs-github-api)[facebook/php-business-sdk

PHP SDK for Facebook Business

90121.1M31](/packages/facebook-php-business-sdk)[google/common-protos

Google API Common Protos for PHP

17399.4M36](/packages/google-common-protos)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
