Jump to content

Recommended Posts

Posted

Destinations Map


Destinations Map for phpVMS v7
 

Destinations Map is a lightweight, modern module for phpVMS v7 that helps pilots explore where they can fly from any origin, discover direct and connecting destinations, and quickly review matching schedules.

It also features a comprehensive ACARS Flight Board to display live flights that can be toggled on or off.

 

Built to drop into any phpVMS v7 site, tested with Seven/Beta themes in a vanilla phpVMS installation

Thanks to the phpVMS community for the inspiration. Enjoy exploring your network with Destinations Map!

.

Highlights

  • Interactive map
  • Pick an origin and see all available connecting destinations in your schedules
  • Focus on connecting destinations (through second-click to reveal schedules)
  • Filter by airline (through drop-down menu)
  • Schedules table revealed on connecting Airports
  • Compact visual cues (small airline logo + ident, departure/arrival icons, and times)
  • BID button follows your site’s existing platform settings (Rank-lock & Departure lock)
  • ACARS Live Flight Board (through ON/OFF toggle button)
  • Airline logo, Pilot, Flight, Aircraft, Dep/Arr, Altitude, GS, Distance, Status
  • No database changes required - No migrations; reads existing routes and ACARS data
  • Theme-safe - Easy adaptations
  • Minimal blade markup; module does not require caches

 

Requirements

  • phpVMS v7 (current)
  • Logged-in access (module routes are behind web + auth by default)
  • Existing schedules (for the map/table) and running ACARS live flights (for the Flight Board)

 

Installation (less than 2 minutes)

  • Unzip DestinationsMap.zip into your phpVMS /modules folder. Do not rename the folder so it remains /modules/DestinationsMap
  • Clear your application caches (via Admin → Maintenance or artisan).
  • Visit /destinations-map to use the module or use the link exposed in the Dashboard.
  • Full details are in DestinationsMap - README.md.

 

Theme Integration

  • Seven/Beta: Registers a generic frontend link and appears with other logged-in module links.
  • Routes & Endpoints 
  • Main page: /destinations-map (route name: destinationsmap.index).
  • JSON endpoints are exposed under a /destinations-map prefix for airlines, origins, destinations, connecting routes, and schedules.

 

Customization

  • Map height: adjustable in the controller.
  • Icons and table columns: editable in the blade view.
  • ACARS badges: optionally add color-coding by phase.

 

What’s Included

  • Service providers (module wiring)
  • Web and API routes
  • Frontend and API controllers
  • Blade view (Leaflet UI, schedules table, optional Flight Board)
  • README with setup and usage notes

 

Download

  • DestinationsMap.zip from this thread.
  • The source and README are inside the zip file.

 

Support & Feedback

Questions or suggestions? Reply in this thread.
Limited support is provided here or in the Discord server

 

Changelog

v1.0.0 – Initial community release

 

Map One.png

Map 5.png

Map 4.png

Map 3.png

Map 2.png

Screenshot 2025-09-07 001546.png

Map 6.png


 

  • Like 1
  • 1 month later...
Posted (edited)

Hi William,

 

As I wrote before, many thanks for the module...

 

I just have a suggestion, like not listing airlines without flights in the dropdown. As the map focuses on destinations of airlines we have, a training airline, or a historic one without scheduled flights should not be there :) 

 

Also, if the map is getting all flights, including 3rd party module owned flights, it may be risky (as they may be not available to the pilot inspecting the map)

 

I will work on these suggestions on my end and can share the controller with you later if you wish to implement too.

 

Safe flights

Edited by DisposableHero
  • Like 1
Posted (edited)

image.png.afedc4b9419f05ee846b7ac0a0a70b6e.png

 

// Gets only active airlines with active and not owned flights (of 3rd party addons)

    public function airlines(Request $request): JsonResponse
    {
        $airlines = Airline::withCount(['flights' => function ($query) {
            $query->whereNull('owner_id')->whereNull('user_id')->where('active', 1);
        }])->where('active', 1)->having('flights_count', '>', 0)->orderBy('icao')->get();

        return response()->json(['data' => $airlines]);
    }

 

Similar approach regarding checking owner_id and user_id of flights can be applied to other parts of the code too.

 

 

Edited by DisposableHero
  • Thanks 1
Posted

Following my own suggestion, refactored the code a little bit and made it more "Laravel"ish :) Getting only not owned flights and building up the airline dropdown with airlines which are active, have active and visible flights.

 

End result should be same (except the airline dropdown contents) while reducing the resource usage and speeding up the load.

 

<?php

namespace Modules\DestinationsMap\Http\Controllers\Api;

use App\Contracts\Controller;
use App\Models\Airline;
use App\Models\Airport;
use App\Models\Flight;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class MapController extends Controller
{
    public function airlines(Request $request): JsonResponse
    {
        $airlines = Airline::withCount(['flights' => function ($query) {
            $query->whereNull('owner_id')->whereNull('user_id')->where(['active' => 1, 'visible' => 1]);
        }])->where('active', 1)->having('flights_count', '>', 0)->orderBy('icao')->get();

        return response()->json(['data' => $airlines]);
    }

    public function origins(Request $request): JsonResponse
    {
        $airlineId = $request->get('airline_id');

        $origins = Flight::where(['active' => 1, 'visible' => 1])->whereNull('owner_id')->whereNull('user_id')->when($airlineId, function ($query) use ($airlineId) {
            $query->where('airline_id', $airlineId);
        })->orderBy('dpt_airport_id')->groupBy('dpt_airport_id')->pluck('dpt_airport_id')->toArray();

        $airports = Airport::whereIn('id', $origins)->orderBy('icao')->get();

        return response()->json(['data' => $airports]);
    }

    public function destinations(Request $request): JsonResponse
    {
        $origin = $request->get('origin');
        $airlineId = $request->get('airline_id');

        if (!$origin) {
            return response()->json(['data' => []]);
        }

        $destinations = Flight::where(['dpt_airport_id' => $origin, 'active' => 1, 'visible' => 1])->whereNull('owner_id')->whereNull('user_id')->when($airlineId, function ($query) use ($airlineId) {
            $query->where('airline_id', $airlineId);
        })->orderBy('arr_airport_id')->groupBy('arr_airport_id')->pluck('arr_airport_id')->toArray();

        $airports = Airport::whereIn('id', $destinations)->orderBy('icao')->get();

        return response()->json(['data' => $airports]);
    }

    public function connecting(Request $request): JsonResponse
    {
        $airport = $request->get('airport');
        $exclude = $request->get('exclude'); // origin to exclude
        $airlineId = $request->get('airline_id');

        if (!$airport) {
            return response()->json(['data' => []]);
        }

        $connecting = Flight::where(['dpt_airport_id' => $airport, 'active' => 1, 'visible' => 1])->whereNull('owner_id')->whereNull('user_id')->when($exclude, function ($query) use ($exclude) {
            $query->where('arr_airport_id', '!=', $exclude);
        })->when($airlineId, function ($query) use ($airlineId) {
            $query->where('airline_id', $airlineId);
        })->orderBy('arr_airport_id')->groupBy('arr_airport_id')->pluck('arr_airport_id')->toArray();

        $airports = Airport::whereIn('id', $connecting)->orderBy('icao')->get();

        return response()->json(['data' => $airports]);
    }

    public function schedules(Request $request): JsonResponse
    {
        $origin = $request->get('origin');
        $destination = $request->get('destination');
        $airlineId = $request->get('airline_id');

        if (!$origin || !$destination) {
            return response()->json(['data' => []]);
        }

        $schedules = Flight::with(['airline', 'dpt_airport', 'arr_airport', 'subfleets'])
            ->where([
                'dpt_airport_id' => $origin,
                'arr_airport_id' => $destination,
                'active'         => 1,
                'visible'        => 1,
            ])->whereNull('owner_id')->whereNull('user_id')->when($airlineId, function ($query) use ($airlineId) {
                $query->where('airline_id', $airlineId);
            })->orderBy('flight_number')->limit(200)->get()->map(function ($f) {
                return [
                    'id'           => $f->id,
                    'ident'        => $f->airline?->icao . $f->flight_number,
                    'airline'      => $f->airline?->icao,
                    'airline_logo' => $f->airline?->logo,
                    'dpt'          => $f->dpt_airport?->icao,
                    'arr'          => $f->arr_airport?->icao,
                    'dpt_time'     => $f->dpt_time,
                    'arr_time'     => $f->arr_time,
                    'route'        => $f->route,
                    'aircraft'     => $f->subfleets?->pluck('type')->filter()->values()->implode(', '),
                ];
            });

        return response()->json(['data' => $schedules]);
    }
}

 

Safe flights.

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...