argument('path'); $dry = $this->option('dry-run'); if (!file_exists($path)) { $this->error("CSV file not found: {$path}"); return 1; } $this->info('Reading CSV: ' . $path); if (($handle = fopen($path, 'r')) === false) { $this->error('Unable to open CSV file'); return 1; } $row = 0; $updates = 0; while (($data = fgetcsv($handle)) !== false) { $row++; // Skip empty rows if (count($data) === 0) { continue; } // Expect at least two columns: user_id, avatar_hash $userId = isset($data[0]) ? trim($data[0]) : null; $hash = isset($data[1]) ? trim($data[1]) : null; // If first row looks like a header, skip it if ($row === 1 && (!is_numeric($userId) || $userId === 'user_id')) { continue; } if ($userId === '' || $hash === '') { $this->line("[skip] row={$row} invalid data"); continue; } $userId = (int) $userId; if ($dry) { $this->line("[dry] user={$userId} would set avatar_hash={$hash}"); $updates++; continue; } try { $affected = DB::table('user_profiles') ->where('user_id', $userId) ->update([ 'avatar_hash' => $hash, 'avatar_updated_at' => now() ]); if ($affected) { $this->line("[ok] user={$userId} avatar_hash updated"); $updates++; } else { $this->line("[noop] user={$userId} no row updated (missing profile?)"); } } catch (\Throwable $e) { $this->error("[error] user={$userId} {$e->getMessage()}"); continue; } } fclose($handle); $this->info("Done. Processed rows={$row} updates={$updates}"); return 0; } }