adezandee/shopify-bundle
Symfony2 bundle for interacting with a Shopify store via the Shopify API. Configure with your shop’s private app credentials, then map Shopify objects and create, update, or delete resources like products through simple exporter services.
Installation:
composer require adezandee/shopify-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Adezandee\ShopifyBundle\AdezandeeShopifyBundle::class => ['all' => true],
];
Configuration:
Add credentials to .env (or config/packages/adezandee_shopify.yaml):
SHOPIFY_API_KEY=your_api_key
SHOPIFY_PASSWORD=your_password
SHOPIFY_SECRET=your_secret
SHOPIFY_DOMAIN=your-store.myshopify.com
Ensure config/packages/adezandee_shopify.yaml exists with:
shopify:
api_key: "%env(SHOPIFY_API_KEY)%"
password: "%env(SHOPIFY_PASSWORD)%"
secret: "%env(SHOPIFY_SECRET)%"
domain: "%env(SHOPIFY_DOMAIN)%"
First API Call: Fetch products in a controller:
use Adezandee\ShopifyBundle\Service\ShopifyService;
class ProductController extends AbstractController
{
public function index(ShopifyService $shopify)
{
$products = $shopify->getProducts();
return $this->json($products);
}
}
CRUD Operations:
$shopify->createProduct($productData)$shopify->updateProduct($id, $productData)$shopify->deleteProduct($id)$shopify->getProduct($id) or $shopify->getProducts(['limit' => 10])Bulk Operations:
Use getProducts() with query params (e.g., ['limit' => 50, 'fields' => 'id,title']) for pagination.
Webhooks:
Configure webhooks via ShopifyService:
$shopify->createWebhook(
'products/create',
'https://your-app.com/webhook-handler',
['topic' => 'products/create']
);
Order Management:
$orders = $shopify->getOrders(['status' => 'any']);
$order = $shopify->getOrder($orderId);
Laravel-Specific:
Bind the service in AppServiceProvider:
public function register()
{
$this->app->bind('shopify', function ($app) {
return new \Adezandee\ShopifyBundle\Service\ShopifyService(
$app['config']['shopify']
);
});
}
Use dependency injection in controllers:
public function __construct(private ShopifyService $shopify) {}
Event Listeners:
Subscribe to Shopify webhook events in EventDispatcher:
$dispatcher->addListener('shopify.webhook', function ($event) {
// Handle webhook payload
});
API Rate Limiting:
Implement retry logic for 429 Too Many Requests:
try {
$shopify->getProducts();
} catch (\RuntimeException $e) {
if (strpos($e->getMessage(), '429') !== false) {
sleep(5); // Retry after delay
retry();
}
}
Authentication:
secret is only used for webhook verification (not API calls).Rate Limits:
$products = Cache::remember("shopify_products_{$limit}", now()->addHours(1), function () use ($shopify, $limit) {
return $shopify->getProducts(['limit' => $limit]);
});
Data Mapping:
variants under products). Flatten data before saving:
$productData = [
'title' => 'T-Shirt',
'variants' => [
['price' => '29.99', 'sku' => 'TSHIRT001'],
],
];
Webhook Verification:
$shopify->verifyWebhook(
$_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'],
file_get_contents('php://input')
);
Enable Debug Mode:
Set debug: true in config to log API requests/responses:
shopify:
debug: true
Common Errors:
Invalid API Key: Double-check .env and Shopify app credentials.Resource Not Found: Use getProducts() to verify IDs before getProduct($id).Invalid Request: Validate payloads against Shopify’s API docs.Custom Endpoints:
Extend ShopifyService to add missing endpoints:
class CustomShopifyService extends \Adezandee\ShopifyBundle\Service\ShopifyService
{
public function getCustomersByTag($tag)
{
return $this->callApi('GET', "/admin/api/2023-01/customers.json", [
'tags' => $tag,
]);
}
}
Response Transformers: Override response handling in a decorator:
$shopify->setResponseTransformer(function ($response) {
return json_decode($response, true)['products'] ?? [];
});
Testing:
Use ShopifyService with a mock client in PHPUnit:
$mockClient = $this->createMock(\GuzzleHttp\Client::class);
$mockClient->method('request')->willReturn(new \GuzzleHttp\Psr7\Response(200, [], '{}'));
$service = new \Adezandee\ShopifyBundle\Service\ShopifyService($config, $mockClient);
How can I help you explore Laravel packages today?