luminarix/laravel-shopify-graphql
GraphQL client for Shopify
A Laravel package for interacting with Shopify's GraphQL Admin API. Built on Saloon with automatic rate limiting and retry handling.
Installation
composer require luminarix/laravel-shopify-graphql
Publish the config file:
php artisan vendor:publish --tag="shopify-graphql-config"
Basic Usage
use Luminarix\Shopify\GraphQLClient\Facades\GraphQLClient;
use Luminarix\Shopify\GraphQLClient\Authenticators\ShopifyApp;
$authenticator = new ShopifyApp($shopDomain, $accessToken);
$client = GraphQLClient::factory()->create($authenticator);
// Query
$response = $client->query('
query {
shop {
name
email
}
}
');
$data = $response->toArray();
// Mutation
$response = $client->mutate('
mutation orderMarkAsPaid($input: OrderMarkAsPaidInput!) {
orderMarkAsPaid(input: $input) {
order {
id
}
userErrors {
field
message
}
}
}
', [
'input' => [
'id' => 'gid://shopify/Order/123456789',
],
]);
Eloquent Model Integration
Create a service class to manage client instances:
namespace App\Services;
use App\Models\ShopifyShop;
use Luminarix\Shopify\GraphQLClient\Facades\GraphQLClient;
use Luminarix\Shopify\GraphQLClient\Authenticators\ShopifyApp;
use Luminarix\Shopify\GraphQLClient\GraphQLClientMethods;
class ShopifyGraphQLService
{
public function with(ShopifyShop $shop): GraphQLClientMethods
{
$authenticator = new ShopifyApp($shop->domain, $shop->access_token);
return GraphQLClient::factory()->create($authenticator);
}
}
Create a trait for your models:
namespace App\Traits;
use App\Services\ShopifyGraphQLService;
use Luminarix\Shopify\GraphQLClient\GraphQLClientMethods;
trait InteractsWithShopifyGraphQL
{
public function graphql(): GraphQLClientMethods
{
return app(ShopifyGraphQLService::class)->with($this);
}
}
Use on your Shopify shop model:
namespace App\Models;
use App\Traits\InteractsWithShopifyGraphQL;
use Illuminate\Database\Eloquent\Model;
class ShopifyShop extends Model
{
use InteractsWithShopifyGraphQL;
}
Now you can call GraphQL directly from your model:
$shop = ShopifyShop::find(1);
$result = $shop->graphql()->query('
query {
shop {
name
}
}
')->toArray();
Response Handling
All query and mutation methods return a GraphQLClientTransformer:
$response = $client->query($query);
$response->toArray(); // array
$response->toCollection(); // Illuminate\Support\Collection
$response->toFluent(); // Illuminate\Support\Fluent
$response->toJson(); // string
$response->toDTO(MyDTO::class); // Custom DTO instance
The transformer is also equipped with the Macroable trait so you can add your own custom methods if needed.
Getting Response with Extensions
Pass withExtensions: true to include cost and rate limit data:
$response = $client->query($query, withExtensions: true);
// Returns: ['data' => [...], 'extensions' => ['cost' => [...]]]
Bulk Operations
For large data exports, use bulk operations:
// Start a bulk operation
$result = $client->createBulkOperation('
{
products {
edges {
node {
id
title
}
}
}
}
');
// Check current bulk operation status
$status = $client->getCurrentBulkOperation();
// Get a specific bulk operation by ID
$operation = $client->getBulkOperation($numericId);
// Cancel running bulk operation
$client->cancelBulkOperation();
Rate Limiting
The package automatically handles Shopify's rate limits:
- Tracks query costs from response extensions
- Waits when throttled before retrying
- Configurable retry attempts
Get current rate limit info:
$info = $client->getRateLimitInfo();
// [
// 'requestedQueryCost' => 10,
// 'actualQueryCost' => 8,
// 'maxAvailableLimit' => 1000,
// 'lastAvailableLimit' => 992,
// 'restoreRate' => 50,
// 'isThrottled' => false,
// ]
Custom Rate Limit Service
Implement RateLimitable to customize rate limit handling:
use Luminarix\Shopify\GraphQLClient\Contracts\RateLimitable;
class CustomRateLimitService implements RateLimitable
{
public function getRateLimitInfo(): array { /* ... */ }
public function updateRateLimitInfo(array $data): void { /* ... */ }
public function calculateWaitTime(float $requestedQueryCost): float { /* ... */ }
public function waitIfNecessary(float $requestedQueryCost): void { /* ... */ }
}
$client = GraphQLClient::factory()->create($authenticator, new CustomRateLimitService());
Configuration
// config/shopify-graphql.php
return [
// Shopify API version (format: YYYY-MM)
'api_version' => env('SHOPIFY_API_VERSION', '2025-01'),
// Fail immediately when throttled (vs. waiting and retrying)
'fail_on_throttled' => env('SHOPIFY_FAIL_ON_THROTTLED', true),
// Max retry attempts when throttled
'throttle_max_tries' => env('SHOPIFY_THROTTLE_MAX_TRIES', 5),
];
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
License
The MIT License (MIT). Please see License File for more information.
Related Packages
Powerful PHP database abstraction layer (DBAL) with many features for database s...
Version History
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v4.0.3 | ^8.3 | ^12.0| | MIT | |
| v4.0.2 | ^8.3 | ^12.0 | MIT | |
| v4.0.1 | ^8.3 | ^12.0 | MIT | |
| v4.0.0 | ^8.3 | ^11.0| | MIT | |
| v3.2.1 | ^8.3 | ^11.0| | MIT | |
| v3.2.0 | ^8.3 | ^11.0| | MIT | |
| v3.1.2 | ^8.3 | ^11.0| | MIT | |
| v3.1.1 | ^8.3 | ^11.0| | MIT | |
| v3.1.0 | ^8.3 | ^11.0 | MIT | |
| v3.0.4 | ^8.3 | ^11.0 | MIT | |
| v3.0.3 | ^8.3 | ^11.0 | MIT | |
| v3.0.2 | ^8.3 | ^11.0 | MIT | |
| v3.0.1 | ^8.3 | ^11.0 | MIT | |
| v3.0.0 | ^8.3 | ^11.0 | MIT | |
| v2.1.0 | ^8.3 | ^11.0 | MIT | |
| v2.0.0 | ^8.3 | ^11.0 | MIT | |
| v1.3.0 | ^8.3 | ^11.0 | MIT | |
| v1.2.1 | ^8.3 | ^11.0 | MIT | |
| v1.2.0 | ^8.3 | ^11.0 | MIT | |
| v1.1.0 | ^8.3 | ^11.0 | MIT | |
| v1.0.0 | ^8.3 | ^11.0 | MIT | |
| v0.4.0 | ^8.3 | ^11.0 | MIT | |
| v0.3.0 | ^8.3 | ^11.0 | MIT | |
| v0.2.0 | ^8.3 | ^11.0 | MIT | |
| v0.1.1 | ^8.3 | ^11.0 | MIT | |
| v0.1.0 | ^8.3 | ^11.0 | MIT |
Pre-releases (2)
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v2.0.0-rc2 | ^8.3 | ^11.0 | MIT | |
| v2.0.0-rc1 | ^8.3 | ^11.0 | MIT |