From 9ee67dfb697662178ad8960bc53b484b260050d7 Mon Sep 17 00:00:00 2001 From: Malek Tellissi Date: Fri, 11 Sep 2026 15:08:01 +0200 Subject: [PATCH] Download and store Shopify product images locally on import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Images are fetched from Shopify CDN, stored in storage/app/public/product-images/ as UUIDs, and saved in the Product.images array — matching Filament's FileUpload format. Co-Authored-By: Claude Sonnet 4.6 --- app/Console/Commands/ShopifyImport.php | 28 ++++++++++++++++++++++++++ app/Services/ShopifyService.php | 4 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/ShopifyImport.php b/app/Console/Commands/ShopifyImport.php index 94d3787..45d510e 100644 --- a/app/Console/Commands/ShopifyImport.php +++ b/app/Console/Commands/ShopifyImport.php @@ -9,6 +9,9 @@ use App\Models\ProductSize; use App\Services\ShopifyService; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; class ShopifyImport extends Command { @@ -57,6 +60,7 @@ class ShopifyImport extends Command ); if ($product->wasRecentlyCreated) { $stats['products']++; + $this->downloadImages($product, $variant['image_urls']); } $size = ProductSize::firstOrCreate( @@ -102,6 +106,30 @@ class ShopifyImport extends Command return self::SUCCESS; } + private function downloadImages(Product $product, array $urls): void + { + if (empty($urls) || ! empty($product->images)) { + return; + } + + $paths = []; + foreach ($urls as $url) { + $response = Http::get($url); + if ($response->failed()) { + continue; + } + + $ext = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg'; + $filename = 'product-images/' . Str::uuid() . '.' . $ext; + Storage::disk('public')->put($filename, $response->body()); + $paths[] = $filename; + } + + if (! empty($paths)) { + $product->update(['images' => $paths]); + } + } + private function parsePacking(string $option, string $sku): ?array { // "Standbodenbeutel 100 g" / "Metalldose 40 g" diff --git a/app/Services/ShopifyService.php b/app/Services/ShopifyService.php index 2866036..e5f074d 100644 --- a/app/Services/ShopifyService.php +++ b/app/Services/ShopifyService.php @@ -25,7 +25,7 @@ class ShopifyService public function getAllVariants(): array { $variants = []; - $url = "{$this->baseUrl}/products.json?limit=250&fields=id,title,variants"; + $url = "{$this->baseUrl}/products.json?limit=250&fields=id,title,variants,images"; while ($url) { $response = Http::withHeader('X-Shopify-Access-Token', $this->token)->get($url); @@ -48,6 +48,7 @@ class ShopifyService } foreach ($response->json('products', []) as $product) { + $imageUrls = collect($product['images'] ?? [])->pluck('src')->all(); foreach ($product['variants'] as $variant) { $variants[] = [ 'id' => (string) $variant['id'], @@ -55,6 +56,7 @@ class ShopifyService 'inventory_quantity' => (int) ($variant['inventory_quantity'] ?? 0), 'product_title' => $product['title'], 'option1' => $variant['option1'] ?? '', + 'image_urls' => $imageUrls, ]; } }