Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Shopify Laravel Package

phpclassic/php-shopify

Lightweight PHP SDK for the Shopify API. Configure with shop URL and API key/password or an app access token, then access resources in an object-oriented style. Uses cURL by default and lets you pass extra cURL options for requests.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**
   ```bash
   composer require phpclassic/php-shopify

Add to config/services.php:

'shopify' => [
    'api_key' => env('SHOPIFY_API_KEY'),
    'api_secret' => env('SHOPIFY_API_SECRET'),
    'store_url' => env('SHOPIFY_STORE_URL'),
    'access_token' => env('SHOPIFY_ACCESS_TOKEN'),
    'scope' => env('SHOPIFY_SCOPE', 'read_write'),
    'debug' => env('SHOPIFY_DEBUG', false), // Enable for logging
],
  1. First Use Case: Fetching Products (with Error Handling)

    use Phpclassic\Shopify\Facades\Shopify;
    
    try {
        $products = Shopify::product()->all();
    } catch (\Exception $e) {
        // Errors now properly include JSON-encoded error info
        \Log::error('Shopify API Error:', [
            'message' => $e->getMessage(),
            'response' => Shopify::getLastResponse()
        ]);
    }
    
  2. Key Files to Review

    • config/shopify.php (default settings, including debug mode)
    • vendor/phpclassic/php-shopify/src/Shopify.php (core class with improved error handling)
    • vendor/phpclassic/php-shopify/src/Facades/Shopify.php (facade usage)
    • vendor/phpclassic/php-shopify/src/Exceptions/ShopifyException.php (new error handling logic)

Implementation Patterns

Common Workflows

  1. CRUD Operations with Error Handling

    // Create with error handling
    try {
        $product = Shopify::product()->create([
            'title' => 'New Product',
            'body_html' => '<p>Description</p>',
        ]);
    } catch (\Phpclassic\Shopify\Exceptions\ShopifyException $e) {
        // Parse JSON error response if available
        $errorData = json_decode($e->getResponse()->getBody(), true);
        \Log::error('Shopify Error:', $errorData);
    }
    
  2. Webhook Handling (Updated Validation)

    Route::post('/shopify/webhook', function (Request $request) {
        // Verify HMAC signature (unchanged)
        $hmac = $request->header('X-Shopify-Hmac-Sha256');
        $data = $request->getContent();
        $computedHmac = hash_hmac('sha256', $data, config('shopify.api_secret'));
    
        if (!hash_equals($hmac, $computedHmac)) {
            abort(401, 'Invalid webhook signature');
        }
    
        // Handle webhook with improved error logging
        try {
            $topic = $request->input('topic');
            $data = $request->input('data');
            // Process webhook...
        } catch (\Exception $e) {
            \Log::error('Webhook Processing Failed', [
                'topic' => $topic,
                'error' => $e->getMessage()
            ]);
        }
    });
    
  3. Bulk Operations with Debugging

    // Export products with debug logging
    if (config('shopify.debug')) {
        \Log::info('Starting product export');
    }
    
    $products = Shopify::product()->all();
    $csv = new \League\Csv\Writer($stream);
    $csv->insertOne(['Title', 'Vendor']);
    
    foreach ($products as $product) {
        $csv->insertOne([$product->title, $product->vendor]);
    
        if (config('shopify.debug') && $csv->tell() % 10 === 0) {
            \Log::debug('Exported ' . $csv->tell() . ' products');
        }
    }
    
  4. GraphQL Queries with Error Handling

    $query = '
        query {
            products(first: 10) {
                edges {
                    node {
                        title
                        id
                    }
                }
            }
        }
    ';
    
    try {
        $results = Shopify::graphql()->query($query);
    } catch (\Phpclassic\Shopify\Exceptions\ShopifyException $e) {
        $error = json_decode($e->getResponse()->getBody(), true);
        \Log::error('GraphQL Error:', [
            'query' => $query,
            'error' => $error
        ]);
        throw new \RuntimeException('GraphQL query failed', 0, $e);
    }
    

Integration Tips

  • Enhanced Debugging: Enable SHOPIFY_DEBUG=true in .env to log:

    • All API requests/responses
    • Error details with JSON payloads
    • Webhook processing steps
  • Error Handling Middleware: Create middleware to catch Shopify exceptions:

    class HandleShopifyErrors
    {
        public function handle($request, Closure $next)
        {
            try {
                return $next($request);
            } catch (\Phpclassic\Shopify\Exceptions\ShopifyException $e) {
                $errorData = json_decode($e->getResponse()->getBody(), true);
                \Log::error('Shopify API Error', [
                    'status' => $e->getResponse()->getStatusCode(),
                    'error' => $errorData ?? $e->getMessage()
                ]);
                abort(502, 'Shopify API Error');
            }
        }
    }
    
  • Testing with Mocks: Use the improved error handling in tests:

    $mock = Mockery::mock('overload:' . \Phpclassic\Shopify\Shopify::class);
    $mock->shouldReceive('get')->andThrow(new \Phpclassic\Shopify\Exceptions\ShopifyException(
        new \GuzzleHttp\Psr7\Response(422, [], '{"errors": ["Invalid field"]}')
    ));
    
    try {
        Shopify::product()->find(123);
        $this->fail('Expected exception not thrown');
    } catch (\Phpclassic\Shopify\Exceptions\ShopifyException $e) {
        $this->assertEquals(['Invalid field'], json_decode($e->getResponse()->getBody(), true)['errors']);
    }
    

Gotchas and Tips

Pitfalls

  1. HTTP Error Response Handling (FIXED)

    • Issue (v1.2.15 and below): HTTP errors (4xx/5xx) were not properly parsed when JSON error info was present.
    • Fix (v1.2.16): Errors now correctly include JSON-encoded error details from Shopify's API.
    • Action: Update error handling to parse JSON responses:
      try {
          $product = Shopify::product()->find(999999); // Non-existent product
      } catch (\Phpclassic\Shopify\Exceptions\ShopifyException $e) {
          $error = json_decode($e->getResponse()->getBody(), true);
          // Handle $error['errors'] array
      }
      
  2. Webhook Verification Still Required

    • Reminder: While error handling is improved, webhook HMAC verification remains critical. Always validate:
      $hmac = $request->header('X-Shopify-Hmac-Sha256');
      $computedHmac = hash_hmac('sha256', $request->getContent(), config('shopify.api_secret'));
      if (!hash_equals($hmac, $computedHmac)) {
          abort(401);
      }
      
  3. Pagination Edge Cases

    • Tip: For large datasets, combine pagination with error handling:
      $allProducts = [];
      $link = Shopify::product()->getLink();
      
      do {
          try {
              $page = Shopify::product()->all(['link' => $link]);
              $allProducts = array_merge($allProducts, $page);
              $link = $page->getNextLink();
          } catch (\Exception $e) {
              \Log::error('Pagination failed', ['link' => $link, 'error' => $e->getMessage()]);
              break;
          }
      } while ($link);
      
  4. GraphQL vs REST Tradeoffs

    • Tip: Use REST for simple operations (better error handling in this version) and GraphQL for complex queries:
      // REST (recommended for simple cases)
      $product = Shopify::product()->find(123);
      
      // GraphQL (for complex nested data)
      $query = 'query { products(first: 10) { edges { node { title variants { price } } } } }';
      $results = Shopify::graphql()->query($query);
      

Debugging

  • Enable Debug Mode:
    SHOPIFY_DEBUG=true
    
    This logs:
    • All API requests (URL, headers, payload)
    • Responses (status, body)
    • Error details
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
baks-dev/finances
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle