PHPackages                             zfr/zfr-shopify - 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. zfr/zfr-shopify

ActiveLibrary[API Development](/categories/api)

zfr/zfr-shopify
===============

PHP library for interacting with the Shopify REST API

6.9.0(2y ago)37198.8k↑126.2%29[2 issues](https://github.com/zf-fr/zfr-shopify/issues)[5 PRs](https://github.com/zf-fr/zfr-shopify/pulls)MITPHPPHP ^7.0|^8.0|^8.1

Since Jun 15Pushed 2y ago9 watchersCompare

[ Source](https://github.com/zf-fr/zfr-shopify)[ Packagist](https://packagist.org/packages/zfr/zfr-shopify)[ Docs](https://github.com/zf-fr/zfr-shopify)[ RSS](/packages/zfr-zfr-shopify/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (57)Used By (0)

ZfrShopify
==========

[](#zfrshopify)

[![Latest Stable Version](https://camo.githubusercontent.com/b2bdfd24c7d0227eab93ad871b7bc8410808b0bb571c2fa86e91d487940db686/68747470733a2f2f706f7365722e707567782e6f72672f7a66722f7a66722d73686f706966792f762f737461626c652e706e67)](https://packagist.org/packages/zfr/zfr-shopify)[![Build Status](https://camo.githubusercontent.com/1cb679b1364adcb6adfc6bc79d5a5271283f76dc99a5cf8b3297d7003bbe2e96/68747470733a2f2f7472617669732d63692e6f72672f7a662d66722f7a66722d73686f706966792e737667)](https://travis-ci.org/zf-fr/zfr-shopify)

ZfrShopify is a modern PHP library based on Guzzle for [Shopify](https://www.shopify.com).

Dependencies
------------

[](#dependencies)

- PHP 7
- [Guzzle](http://www.guzzlephp.org): ^6.1
- [Zend Diactoros](https://github.com/zendframework/zend-diactoros): &gt;=1.3

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

[](#installation)

Installation of ZfrShopify is only officially supported using Composer:

```
php composer.phar require 'zfr/zfr-shopify:6.0'
```

REST API
--------

[](#rest-api)

ZfrShopify provides a one-to-one mapping with API methods defined in [Shopify doc](https://docs.shopify.com/api/). Since the version 4, it also supports a basic integration with the new GraphQL admin API.

### Private app

[](#private-app)

In order to use ZfrShopify as a private app, you must first instantiate the client:

```
$shopifyClient = new ShopifyClient([
    'private_app' => true,
    'api_key'     => 'YOUR_API_KEY',
    'password'    => 'YOUR_PASSWORD',
    'shop'        => 'domain.myshopify.com',
    'version'     => '2019-04'
]);
```

> Make sure to always include a version. [More info about Shopify versioning](https://help.shopify.com/en/api/versioning)

### Public app

[](#public-app)

When using a public app, you instantiate the client a bit differently:

```
$shopifyClient = new ShopifyClient([
    'private_app'   => false,
    'api_key'       => 'YOUR_API_KEY', // In public app, this is the app ID
    'access_token'  => 'MERCHANT_TOKEN',
    'shop'          => 'merchant.myshopify.com',
    'version'       => '2019-04'
]);
```

> Make sure to always include a version. [More info about Shopify versioning](https://help.shopify.com/en/api/versioning)

### Using a container

[](#using-a-container)

ZfrShopify also provides built-in [container-interop](https://github.com/container-interop/container-interop) factories that you can use. You must make sure that your container contains a service called "config" that is an array with a key `zfr_shopify` containing the required config:

```
// myconfig.php

return [
    'zfr_shopify' => [
        'private_app'   => false,
        'api_key'       => 'YOUR_API_KEY', // In public app, this is the app ID
        'access_token'  => 'MERCHANT_TOKEN',
        'shop'          => 'merchant.myshopify.com',
    ],
];
```

If you're using Zend\\ServiceManager 3, you can use [Zend\\ComponentInstaller](https://zendframework.github.io/zend-component-installer/)to register our factories into Zend\\ServiceManager automatically.

However if you're using other framework or other container, you can still manually register our factories, they are under [src/Container](/src/Container) folder.

### Validating a request

[](#validating-a-request)

ZfrShopify client provides an easy way to validate an incoming request to make sure it comes from Shopify through the `RequestValidator`object. It requires a PSR7 requests and a shared secret:

```
use ZfrShopify\Exception\InvalidRequestException;
use ZfrShopify\Validator\RequestValidator;

$validator = new RequestValidator();

try {
    $validator->validateRequest($psr7Request, 'shared_secret');
} catch (InvalidRequestException $exception) {
    // Request is not valid
}
```

### Validating a webhook

[](#validating-a-webhook)

Similarily, you can use the `WebhookValidator` to validate your webhook:

```
use ZfrShopify\Exception\InvalidWebhookException;
use ZfrShopify\Validator\WebhookValidator;

$validator = new WebhookValidator();

try {
    $validator->validateWebhook($psr7Request, 'shared_secret');
} catch (InvalidWebhookException $exception) {
    // Request is not valid
}
```

### Validating an application request

[](#validating-an-application-request)

Finally, you can also use the `ApplicationProxyRequestValidator` to validate application proxy requests:

```
use ZfrShopify\Exception\InvalidApplicationProxyRequestException;
use ZfrShopify\Validator\ApplicationProxyRequestValidator;

$validator = new ApplicationProxyRequestValidator();

try {
  $validator->validateApplicationProxyRequest($psr7Request, 'shared_secret');
} catch {
  // Request is not valid
}
```

### Create an authorization response

[](#create-an-authorization-response)

ZfrShopify provides an easy way to create a PSR7 compliant `ResponseInterface` to create an authorization response:

```
use ZfrShopify\OAuth\AuthorizationRedirectResponse;

$apiKey         = 'app_123';
$shopDomain     = 'shop_to_authorize.myshopify.com';
$scopes         = ['read_orders', 'read_products'];
$redirectionUri = 'https://myapp.test.com/oauth/redirect';
$nonce          = 'strong_nonce';

$response = new AuthorizationRedirectResponse($apiKey, $shopDomain, $scopes, $redirectionUri, $nonce);
```

While the `nonce` parameter is required, ZfrShopify does not make any assumption about how to save the nonce and check it when Shopify redirects to your server. You are responsible to safely saving the nonce.

### Exchanging a code against an access token

[](#exchanging-a-code-against-an-access-token)

You can use the `TokenExchanger` class to exchange a code to a long-lived access token:

```
use GuzzleHttp\Client;
use ZfrShopify\OAuth\TokenExchanger;

$apiKey         = 'app_123';
$sharedSecret   = 'secret_123';
$shopDomain     = 'shop_to_authorize.myshopify.com';
$code           = 'code_123';

$tokenExchanger = new TokenExchanger(new Client());
$accessToken    = $tokenExchanger->exchangeCodeForToken($apiKey, $sharedSecret, $shopDomain, $code);
```

ZfrShopify also provides a simple factory compliant with [container-interop](https://github.com/container-interop/container-interop)that you can register to the container of your choice, with the `ZfrShopify\Container\TokenExchangerFactory`.

### Exploiting responses

[](#exploiting-responses)

ZfrShopify returns Shopify response directly. However, by default, Shopify wrap the responses by a top-key. For instance, if you want to retrieve shop information, Shopify will return this payload:

```
{
    "shop": {
        "id": 123,
        "domain": "myshop.myshopify.com"
    }
}
```

This is a bit inconvenient to use as we would need to do that:

```
$shopDomain = $shopifyClient->getShop()['shop']['domain'];
```

Instead, ZfrShopify automatically "unwraps" response, so you can use the more concise code:

```
$shopDomain = $shopifyClient->getShop()['domain'];
```

When reading Shopify API doc, make sure you remove the top key when exploiting responses.

#### Count

[](#count)

Similarily, when you use one of the `count` endpoint, ZfrShopify will automatically extract the value from Shopify's response, so you do not need to manually access the count property:

`php $count = $shopifyClient->getOrderCount(); // $count is already an integer `

### Using iterators

[](#using-iterators)

For most "list" endpoints (`getProducts`, `getCollections`...), Shopify allows you to get up to 250 resources at a time. When using the standard `get**`method, you are responsible to handle the pagination yourself.

For convenience, ZfrShopify allows you to easily iterate through all resources efficiently (internally, we are using generators). Here is how you can get all the products from a given store:

```
foreach ($shopifyClient->getProductsIterator(['fields' => 'id,title']) as $product) {
   // Do something with product
}
```

ZfrShopify will take care of doing additional requests when it has reached the end of a given page.

### Executing multiple requests concurrently

[](#executing-multiple-requests-concurrently)

For optimization purposes, it may be desirable to execute multiple requests concurrently. To do that, ZfrShopify client allow you to take advantage of the underlying Guzzle client and execute multiple requests at the same time.

To do that, you can manually create the Guzzle commands, and execute them all. ZfrShopify will take care of authenticating all requests individually, and extracting the response payload. For instance, here is how you could get both shop info and products info:

```
$command1 = $client->getCommand('GetShop', ['fields' => 'id']);
$command2 = $client->getCommand('GetProducts', ['fields' => 'id,title']);

$results = $client->executeAll([$command1, $command2]);

// $results[0] represents the response of $command1, $results[1] represents the response of $command2
```

If a request has failed, it will contain an instance of `GuzzleHttp\Command\Exception\CommandException`. For instance, here is how you could iterate through all the results:

```
use GuzzleHttp\Command\Exception\CommandException;

foreach ($results as $singleResult) {
   if ($singleResult instanceof CommandException) {
      // Get the command that has failed, and eventually retry
      $command = $singleResult->getCommand();
      continue;
   }

   // Otherwise, $singleResult is just an array that contains the Shopify data
}
```

GraphQL API
-----------

[](#graphql-api)

In 2018, Shopify launched a new API, called the [GraphQL Admin API](https://help.shopify.com/en/api/graphql-admin-api). This new API comes with a lot of advantages compared to the REST API:

- It allows to access more efficiently to the various Shopify resources (you can for instance get a collection, with all its products and variants, by using a single request).
- It offers access to some resources that are not exposed through the REST API.

The version 4 of ZfrShopify now ships with a basic GraphQL client. It does not yet support the following features, though:

- Automatic pagination
- Automatic handling of Shopify rate limits

In order to use the client, you must instantiate it. Instead of the ShopifyClient, you must create a `ZfrShopify\ShopifyGraphQLClient`. If you are using a private app:

```
$client = new ShopifyGraphQLClient([
    'shop'        => 'test.myshopify.com',
    'version'     => '2019-04',
    'private_app' => true,
    'password'    => 'YOUR PASSWORD'
]);
```

> Make sure to always include a version. [More info about Shopify versioning](https://help.shopify.com/en/api/versioning)

If you are using a public app:

```
$client = new ShopifyGraphQLClient([
    'shop'         => 'test.myshopify.com',
    'version'      => '2019-04',
    'private_app'  => false,
    'access_token' => 'ACCESS TOKEN'
]);
```

> Make sure to always include a version. [More info about Shopify versioning](https://help.shopify.com/en/api/versioning)

### Queries

[](#queries)

To perform query, simply enter your query as an heredoc. For instance, here is a GraphQL query that get the title and id of the first 5 collections, as well as the 5 first products within those collections (this used to require several queries in the REST API, while everything can be done very efficiently with GraphQL):

```
$request = request($request, $variables);

var_dump($result);
```

### Mutations

[](#mutations)

Similarly, ZfrShopify supports mutation. To do this, you simply need to use a mutation query. Here is an example that is creating a product:

```
$request =  [
        'title' => 'My product'
    ]
];

$result = $client->request($request, $variables);

var_dump($result);
```

This request will create a new product whose title is "My product", and will return the id of the product.

> For better error handling, you should always include the userErrors object in your response.

### Error handling

[](#error-handling)

When using GraphQL requests, there are two kinds of errors that you can catch.

#### Request errors

[](#request-errors)

Those errors are for malformed GraphQL requests. You can catch them using the `\ZfrShopify\Exception\GraphQLErrorException` exception:

```
try {
    $result = $client->request($request);
} catch (\ZfrShopify\Exception\GraphQLErrorException $exception) {
    var_dump($exception->getErrors());
}
```

#### User errors

[](#user-errors)

Those errors are for requests that are missing data (like incorrect data, missing data...). You can catch them using the `\ZfrShopify\Exception\GraphQLUserErrorException` exception:

```
try {
    $result = $client->request($request);
} catch (\ZfrShopify\Exception\GraphQLUserErrorException $exception) {
    var_dump($exception->getErrors());
}
```

Implemented endpoints
---------------------

[](#implemented-endpoints)

Here is a list of supported endpoints (more to come in the future):

**ACCESS SCOPE RELATED METHODS:**

- array getAccessScopes(array $args = \[\])

**STOREFRONT ACCESS TOKEN RELATED METHODS:**

- array getStorefrontAccessTokens(array $args = \[\])
- array createStorefrontAccessToken(array $args = \[\])
- array deleteStorefrontAccessToken(array $args = \[\])

**APPLICATION CHARGE RELATED METHODS:**

- array getApplicationCharges(array $args = \[\])
- array getApplicationCharge(array $args = \[\])
- array createApplicationCharge(array $args = \[\])
- array activateApplicationCharge(array $args = \[\])
- array deleteApplicationCharge(array $args = \[\])

**ARTICLE RELATED METHODS:**

- array getArticles(array $args = \[\])
- int getArticleCount(array $args = \[\])
- array getBlogArticles(array $args = \[\])
- int getBlogArticleCount(array $args = \[\])
- array getArticle(array $args = \[\])
- array getArticleMetafields(array $args = \[\])
- array getBlogArticle(array $args = \[\])
- array getArticlesAuthors(array $args = \[\])
- array getArticlesTags(array $args = \[\])
- array createArticle(array $args = \[\])
- array createBlogArticle(array $args = \[\])
- array updateArticle(array $args = \[\])
- array updateBlogArticle(array $args = \[\])
- array deleteArticle(array $args = \[\])
- array deleteBlogArticle(array $args = \[\])

**ASSET RELATED METHODS:**

- array getAssets(array $args = \[\])
- array getAsset(array $args = \[\])
- array createAsset(array $args = \[\])
- array updateAsset(array $args = \[\])
- array deleteAsset(array $args = \[\])

**BLOG RELATED METHODS:**

- array getBlogs(array $args = \[\])
- array getBlogMetafields(array $args = \[\])
- int getBlogCount(array $args = \[\])
- array getBlog(array $args = \[\])
- array createBlog(array $args = \[\])
- array updateBlog(array $args = \[\])
- array deleteBlog(array $args = \[\])

**CUSTOM COLLECTION RELATED METHODS:**

- array getCustomCollections(array $args = \[\])
- int getCustomCollectionCount(array $args = \[\])
- array getCustomCollection(array $args = \[\])
- array createCustomCollection(array $args = \[\])
- array updateCustomCollection(array $args = \[\])
- array deleteCustomCollection(array $args = \[\])

**COLLECTION RELATED METHODS**

- array getCollection(array $args = \[\])
- array getCollectionProducts(array $args = \[\])
- array getCollectionMetafields(array $args = \[\])

**COLLECT RELATED METHODS:**

- array getCollects(array $args = \[\])
- int getCollectCount(array $args = \[\])
- array getCollect(array $args = \[\])
- array createCollect(array $args = \[\])
- array deleteCollect(array $args = \[\])

**CUSTOMER RELATED METHODS:**

- array getCustomers(array $args = \[\])
- int getCustomerCount(array $args = \[\])
- array searchCustomers(array $args = \[\])
- array getCustomer(array $args = \[\])
- array getCustomerMetafields(array $args = \[\])
- array createCustomer(array $args = \[\])
- array updateCustomer(array $args = \[\])
- array deleteCustomer(array $args = \[\])

**CUSTOMER ADDRESS RELATED METHODS:**

- array getCustomerAddresses(array $args = \[\])
- array getCustomerAddress(array $args = \[\])
- array createCustomerAddress(array $args = \[\])
- array updateCustomerAddress(array $args = \[\])
- array deleteCustomerAddress(array $args = \[\])
- array setDefaultCustomerAddress(array $args = \[\])

**DISCOUNT CODE RELATED METHODS:**

- array getDiscountCodes(array $args = \[\])
- array getDiscountCode(array $args = \[\])
- array createDiscountCode(array $args = \[\])
- array deleteDiscountCode(array $args = \[\])

**EVENT RELATED METHODS:**

- array getEvents(array $args = \[\])
- int getEventCount(array $args = \[\])
- array getEvent(array $args = \[\])

**FULFILLMENTS RELATED METHODS:**

- array getFulfillments(array $args = \[\])
- int getFulfillmentCount(array $args = \[\])
- array getFulfillment(array $args = \[\])
- array createFulfillment(array $args = \[\])
- array updateFilfillment(array $args = \[\])
- array completeFulfillment(array $args = \[\])
- array cancelFulfillment(array $args = \[\])

**FULFILLMENT ORDER RELATED METHODS:**

- array getFulfillmentOrders(array $args = \[\])
- array getFulfillmentOrder(array $args = \[\])
- array cancelFulfillmentOrder(array $args = \[\])
- array closeFulfillmentOrder(array $args = \[\])
- array moveFulfillmentOrder(array $args = \[\])
- array openFulfillmentOrder(array $args = \[\])
- array rescheduleFulfillmentOrder(array $args = \[\])

**GIFT CARD RELATED METHODS:**

- array getGiftCards(array $args = \[\])
- int getGiftCardCount(array $args = \[\])
- array getGiftCard(array $args = \[\])
- array createGiftCard(array $args = \[\])
- array updateGiftCard(array $args = \[\])
- array disableGiftCard(array $args = \[\])

**INVENTORY ITEM RELATED METHODS:**

- array getInventoryItems(array $args = \[\])
- array getInventoryItem(array $args = \[\])
- array updateInventoryItem(array $args = \[\])

**INVENTORY LEVEL RELATED METHODS:**

- array getInventoryLevels(array $args = \[\])
- array adjustInventoryLevel(array $args = \[\])
- array deleteInventoryLevel(array $args = \[\])
- array connectInventoryLevel(array $args = \[\])
- array setInventoryLevel(array $args = \[\])

**LOCATION RELATED METHODS:**

- array getLocations(array $args = \[\])
- array getLocation(array $args = \[\])
- int getLocationCount(array $args = \[\])
- array getLocationInventoryLevels(array $args = \[\])

**METAFIELDS RELATED METHODS:**

- array getMetafields(array $args = \[\])
- array getMetafield(array $args = \[\])
- array createMetafield(array $args = \[\])
- array updateMetafield(array $args = \[\])
- array deleteMetafield(array $args = \[\])

**ORDER RELATED METHODS:**

- array getOrders(array $args = \[\])
- int getOrderCount(array $args = \[\])
- array getOrder(array $args = \[\])
- array getOrderMetafields(array $args = \[\])
- array createOrder(array $args = \[\])
- array updateOrder(array $args = \[\])
- array closeOrder(array $args = \[\])
- array openOrder(array $args = \[\])
- array cancelOrder(array $args = \[\])

**DRAFT ORDER RELATED METHODS:**

- array getDraftOrders(array $args = \[\])
- array getDraftOrderMetafields(array $args = \[\])
- int getDraftOrderCount(array $args = \[\])
- array createDraftOrder(array $args = \[\])
- array updateDraftOrder(array $args = \[\])
- array getDraftOrder(array $args = \[\])
- array sendDraftOrderInvoice(array $args = \[\])
- array completeDraftOrder(array $args = \[\])
- array deleteDraftOrder(array $args = \[\])

**PAGE RELATED METHODS:**

- array getPages(array $args = \[\])
- int getPageCount(array $args = \[\])
- array getPage(array $args = \[\])
- array getPageMetafields(array $args = \[\])
- array createPage(array $args = \[\])
- array updatePage(array $args = \[\])
- array deletePage(array $args = \[\])

**PRICE RULE RELATED METHODS:**

- array getPriceRules(array $args = \[\])
- array getPriceRule(array $args = \[\])
- array createPriceRule(array $args = \[\])
- array updatePriceRule(array $args = \[\])
- array deletePriceRule(array $args = \[\])

**PRODUCT RELATED METHODS:**

- array getProducts(array $args = \[\])
- int getProductCount(array $args = \[\])
- array getProduct(array $args = \[\])
- array getProductMetafields(array $args = \[\])
- array createProduct(array $args = \[\])
- array updateProduct(array $args = \[\])
- array deleteProduct(array $args = \[\])

**PRODUCT IMAGE RELATED METHODS:**

- array getProductImages(array $args = \[\])
- int getProductImageCount(array $args = \[\])
- array getProductImage(array $args = \[\])
- array createProductImage(array $args = \[\])
- array updateProductImage(array $args = \[\])
- array deleteProductImage(array $args = \[\])

**RECURRING APPLICATION CHARGE RELATED METHODS:**

- array getRecurringApplicationCharges(array $args = \[\])
- array getRecurringApplicationCharge(array $args = \[\])
- array createRecurringApplicationCharge(array $args = \[\])
- array activateRecurringApplicationCharge(array $args = \[\])
- array deleteRecurringApplicationCharge(array $args = \[\])

**REFUND RELATED METHODS:**

- array getRefunds(array $args = \[\])
- array getRefund(array $args = \[\])
- array calculateRefund(array $args = \[\])
- array createRefund(array $args = \[\])

**SHOP RELATED METHODS:**

- array getShop(array $args = \[\])

**SMART COLLECTION RELATED METHODS:**

- array getSmartCollections(array $args = \[\])
- int getSmartCollectionCount(array $args = \[\])
- array getSmartCollection(array $args = \[\])
- array createSmartCollection(array $args = \[\])
- array updateSmartCollection(array $args = \[\])
- array deleteSmartCollection(array $args = \[\])

**THEME RELATED METHODS:**

- array getThemes(array $args = \[\])
- array getTheme(array $args = \[\])
- array createTheme(array $args = \[\])
- array updateTheme(array $args = \[\])
- array deleteTheme(array $args = \[\])

**PRODUCT VARIANT RELATED METHODS:**

- array getProductVariants(array $args = \[\])
- int getProductVariantCount(array $args = \[\])
- array getProductVariant(array $args = \[\])
- array getProductVariantMetafields(array $args = \[\])
- array createProductVariant(array $args = \[\])
- array updateProductVariant(array $args = \[\])
- array deleteProductVariant(array $args = \[\])

**REDIRECT RELATED METHODS:**

- array getRedirects(array $args = \[\])
- int getRedirectCount(array $args = \[\])
- array getRedirect(array $args = \[\])
- array createRedirect(array $args = \[\])
- array updateRedirect(array $args = \[\])
- array deleteRedirect(array $args = \[\])

**SCRIPT TAG RELATED METHODS:**

- array getScriptTags(array $args = \[\])
- int getScriptTagCount(array $args = \[\])
- array getScriptTag(array $args = \[\])
- array createScriptTag(array $args = \[\])
- array updateScriptTag(array $args = \[\])
- array deleteScriptTag(array $args = \[\])

**TRANSACTION RELATED METHODS:**

- array getTransactions(array $args = \[\])
- int getTransactionCount(array $args = \[\])
- array getTransaction(array $args = \[\])
- array createTransaction(array $args = \[\])

**USAGE CHARGE RELATED METHODS:**

- array getUsageCharges(array $args = \[\])
- array getUsageCharge(array $args = \[\])
- array createUsageCharge(array $args = \[\])

**WEBHOOK RELATED METHODS:**

- array getWebhooks(array $args = \[\])
- int getWebhookCount(array $args = \[\])
- array getWebhook(array $args = \[\])
- array createWebhook(array $args = \[\])
- array updateWebhook(array $args = \[\])
- array deleteWebhook(array $args = \[\])

**OTHER METHODS:**

- array createDelegateAccessToken(array $args = \[\])

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity49

Moderate usage in the ecosystem

Community26

Small or concentrated contributor base

Maturity86

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 75.4% 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 ~47 days

Recently: every ~158 days

Total

56

Last Release

1039d ago

Major Versions

1.5.0 → 2.0.02017-01-06

2.2.9 → 3.0.02017-06-07

3.5.0 → 4.0.02018-12-26

4.2.0 → 5.0.02019-04-15

5.5.0 → 6.0.02020-01-29

PHP version history (2 changes)1.0.0PHP ~7.0

6.7.0PHP ^7.0|^8.0|^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/9e3c74232d02a5fedbcef4650bac1d1103be292d4a013f6f9e692befcc9bb7ca?d=identicon)[bakura10](/maintainers/bakura10)

---

Top Contributors

[![bakura10](https://avatars.githubusercontent.com/u/1198915?v=4)](https://github.com/bakura10 "bakura10 (218 commits)")[![danizord](https://avatars.githubusercontent.com/u/1850941?v=4)](https://github.com/danizord "danizord (29 commits)")[![oojoe](https://avatars.githubusercontent.com/u/770712?v=4)](https://github.com/oojoe "oojoe (8 commits)")[![AndyJohnstonArkade](https://avatars.githubusercontent.com/u/31529835?v=4)](https://github.com/AndyJohnstonArkade "AndyJohnstonArkade (8 commits)")[![garthbrantley](https://avatars.githubusercontent.com/u/8466130?v=4)](https://github.com/garthbrantley "garthbrantley (5 commits)")[![efficientbit](https://avatars.githubusercontent.com/u/3807256?v=4)](https://github.com/efficientbit "efficientbit (4 commits)")[![dddbliss](https://avatars.githubusercontent.com/u/897034?v=4)](https://github.com/dddbliss "dddbliss (3 commits)")[![John-Dormevil](https://avatars.githubusercontent.com/u/18209197?v=4)](https://github.com/John-Dormevil "John-Dormevil (2 commits)")[![durmaj](https://avatars.githubusercontent.com/u/32449979?v=4)](https://github.com/durmaj "durmaj (2 commits)")[![Orkin](https://avatars.githubusercontent.com/u/1061903?v=4)](https://github.com/Orkin "Orkin (2 commits)")[![ryanadair](https://avatars.githubusercontent.com/u/60230815?v=4)](https://github.com/ryanadair "ryanadair (2 commits)")[![savchukoleksii](https://avatars.githubusercontent.com/u/18497036?v=4)](https://github.com/savchukoleksii "savchukoleksii (2 commits)")[![shaneferguson](https://avatars.githubusercontent.com/u/4074239?v=4)](https://github.com/shaneferguson "shaneferguson (1 commits)")[![jschaedl](https://avatars.githubusercontent.com/u/1880467?v=4)](https://github.com/jschaedl "jschaedl (1 commits)")[![MaksBrainiac](https://avatars.githubusercontent.com/u/355955?v=4)](https://github.com/MaksBrainiac "MaksBrainiac (1 commits)")[![dangreaves](https://avatars.githubusercontent.com/u/1036142?v=4)](https://github.com/dangreaves "dangreaves (1 commits)")

---

Tags

apishopify

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/zfr-zfr-shopify/health.svg)

```
[![Health](https://phpackages.com/badges/zfr-zfr-shopify/health.svg)](https://phpackages.com/packages/zfr-zfr-shopify)
```

###  Alternatives

[algolia/algoliasearch-client-php

API powering the features of Algolia.

69433.0M114](/packages/algolia-algoliasearch-client-php)[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.5k311.5k5](/packages/theodo-group-llphant)[rubix/server

Deploy your Rubix ML models to production with scalable stand-alone inference servers.

632.3k](/packages/rubix-server)[robwittman/shopify-php-sdk

PHP SDK for Shopify API

7098.9k1](/packages/robwittman-shopify-php-sdk)[los/los-rate-limit

Rate Limit Middleware for PHP

2737.9k1](/packages/los-los-rate-limit)[darthsoup/php-whmcs-api

WHMCS API client for PHP

2317.3k4](/packages/darthsoup-php-whmcs-api)

PHPackages © 2026

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