A Laravel package for interacting with Shopify's GraphQL Admin API. Built on Saloon with automatic rate limiting and retry handling.
composer require luminarix/laravel-shopify-graphqlPublish the config file:
php artisan vendor:publish --tag="shopify-graphql-config"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',
],
]);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();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 instanceThe transformer is also equipped with the Macroable trait so you can add your own custom methods if needed.
Pass withExtensions: true to include cost and rate limit data:
$response = $client->query($query, withExtensions: true);
// Returns: ['data' => [...], 'extensions' => ['cost' => [...]]]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();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,
// ]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());// 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),
];composer testPlease see CHANGELOG for more information on what has changed recently.
The MIT License (MIT). Please see License File for more information.