utc(); $oneHourAgo = $now->copy()->subHours(1); $userFlights = UserFlight::whereBetween('arrival_date', [ $oneHourAgo->toDateTimeString(), $now->toDateTimeString(), ]) ->where('auto_update', true) ->whereNotNull('flight_number') ->get(); $this->info("Found {$userFlights->count()} flights."); foreach ($userFlights as $flight) { // Split "QF22" into ["QF", "22"] preg_match('/^([A-Z]{2,3})(\d+)$/i', $flight->flight_number, $matches); if (empty($matches)) { $this->warn("Could not parse flight number: {$flight->flight_number}"); continue; } $airlineCode = strtoupper($matches[1]); $flightNumber = $matches[2]; $arrivalDate = $flight->arrival_date->setTimezone($flight->arrivalAirport->timezone); $year = $arrivalDate->year; $month = $arrivalDate->month; $day = $arrivalDate->day; $url = "https://www.flightstats.com/v2/api-next/flight-tracker/{$airlineCode}/{$flightNumber}/{$year}/{$month}/{$day}"; $response = Http::get($url); if (!$response->successful()) { $this->warn("Failed to fetch data for {$flight->flight_number}: HTTP {$response->status()}"); continue; } $data = $response->json(); $flightData = $data['data'] ?? []; if (empty($flightData)) { $this->warn("No flight data returned for {$airlineCode}{$flightNumber}"); continue; } $tailNumber = $flightData['positional']['flexTrack']['tailNumber'] ?? null; $estimatedDepartureUtc = $flightData['schedule']['estimatedActualDepartureUTC'] ?? null; $estimatedArrivalUtc = $flightData['schedule']['estimatedActualArrivalUTC'] ?? null; $equipmentCode = $flightData['additionalFlightInfo']['equipment']['iata'] ?? null; $this->info("Flight {$airlineCode}{$flightNumber} — Tail: {$tailNumber}, Equipment: {$equipmentCode}"); $this->info("Departure: {$estimatedDepartureUtc} | Arrival: {$estimatedArrivalUtc}"); } } }