$registrations */ public static function forRegistrations(QrCode $qrCode, Collection $registrations): string { $content = $qrCode->content(); $eventName = self::sanitize($content['name'] ?? $qrCode->label); $size = $content['badge_size'] ?? '4x3'; // Label dimensions in dots @ 203 dpi. [$widthDots, $heightDots] = match ($size) { '4x6' => [812, 1218], 'cr80' => [685, 431], default => [812, 609], // 4x3 }; $labels = []; foreach ($registrations as $reg) { $name = self::sanitize($reg->attendee_name); $tier = self::sanitize($reg->tier_name); $extra = collect($reg->badge_fields ?? []) ->map(fn ($v, $k) => self::sanitize($k . ': ' . $v)) ->implode(' | '); $zpl = "^XA\n"; $zpl .= "^PW{$widthDots}\n"; $zpl .= "^LL{$heightDots}\n"; $zpl .= "^CI28\n"; // UTF-8 // Event name (top) $zpl .= "^FO40,40^A0N,40,40^FB" . ($widthDots - 80) . ",1,0,C^FD{$eventName}^FS\n"; // Attendee name (large, centered) $zpl .= "^FO40,150^A0N,80,80^FB" . ($widthDots - 80) . ",2,0,C^FD{$name}^FS\n"; // Tier $zpl .= "^FO40,320^A0N,40,40^FB" . ($widthDots - 80) . ",1,0,C^FD{$tier}^FS\n"; // Extra fields if ($extra !== '') { $zpl .= "^FO40,375^A0N,28,28^FB" . ($widthDots - 80) . ",2,0,C^FD{$extra}^FS\n"; } // QR of the badge code (bottom) $qrX = (int) (($widthDots / 2) - 70); $zpl .= "^FO{$qrX}," . ($heightDots - 200) . "^BQN,2,5^FDLA,{$reg->badge_code}^FS\n"; // Badge code text $zpl .= "^FO40," . ($heightDots - 60) . "^A0N,34,34^FB" . ($widthDots - 80) . ",1,0,C^FD{$reg->badge_code}^FS\n"; $zpl .= "^XZ\n"; $labels[] = $zpl; } return implode("\n", $labels); } private static function sanitize(string $value): string { // Escape ZPL control chars (^ and ~) and collapse whitespace. $value = str_replace(['^', '~'], [' ', ' '], $value); return trim(preg_replace('/\s+/', ' ', $value) ?? ''); } }