Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Minecraft Query Laravel Package

xpaw/php-minecraft-query

A lightweight PHP library for querying Minecraft servers via the GameSpy4 Query Protocol. Retrieve server status, player counts, MOTD, version, plugins, and map data with a simple, dependency-free API.

View on GitHub
Deep Wiki
Context7

Getting Started

This package wraps the Minecraft server protocols: a TCP status ping (what the multiplayer server list shows) and the UDP GameSpy4 query (full player list, plugins, host info).

composer require <vendor>/<package>   # requires PHP >= 8.0 as of 5.0.0

Where to look first:

  1. MinecraftPing::Query($host, $port) — status ping. Works against any vanilla/Paper/Spigot/Proxy server with no server-side configuration. Returns MOTD, online/max players, version name, protocol, favicon.
  2. MinecraftQuery::Query($host, $queryPort) — full query. Requires enable-query=true (and usually an explicit query.port) in server.properties, and UDP open on that port. Returns the actual player name list, plugins, software version.

First use case — a status card on an admin dashboard:

use MinecraftPing;

$status = Cache::remember("mc:status:{$server->id}", 30, fn () => MinecraftPing::Query($server->host, $server->port));

return view('server.status', [
    'online'  => $status->getPlayers()->getOnlinePlayers(),
    'max'     => $status->getPlayers()->getMaxPlayers(),
    'motd'    => $status->getDescription(),
    'version' => $status->getVersion()->getRelease(),
]);

Start with the ping. Only reach for the query protocol when you genuinely need the per-player list or plugin inventory.

Implementation Patterns

Status widget / public server list. Cache aggressively (20–60s). Cache::remember around the ping call is the single biggest win — a dashboard with 20 servers otherwise fires 20 TCP round-trips per page load.

Monitoring with notifications. Run the ping from a scheduled command, not from a request. Compare getPlayers()->getOnlinePlayers() against your threshold, dispatch a ServerWentDown event, and notify via mail/Slack. Keep the timeout short (1–2s) so a hung server doesn't stall the scheduler.

Multi-server config. Put hosts in config/minecraft.php and resolve a configured client per server, rather than hardcoding host/port at call sites:

$status = Cache::remember("mc:{$key}", 30, fn () => MinecraftPing::Query($host, $port));

Query vs ping in one flow. Use ping for the always-on status card (no server config needed), and query only on a detail page or a queued job to populate the player roster:

try {
    $query = MinecraftQuery::Query($host, $queryPort);
    $players = $query->getPlayers();       // array|Collection depending on wrapper
    $plugins = $query->getPlugins();
} catch (\Throwable $e) {
    report($e);                            // query disabled or UDP blocked — degrade gracefully
    $players = [];
}

Favicon and MOTD rendering. Favicons come back as data:image/png;base64,.... Store or cache the base64 string; don't re-fetch on every render. MOTD contains legacy § colour codes — strip or convert them to HTML spans in a presenter, not in the Blade template.

Testing. Never hit a live server in the test suite. Bind a fake/stub client in the container (or use Http-style fakes if the wrapper offers them) and assert on your own presenter logic instead.

Gotchas and Tips

5.0.0 breaking changes to check before upgrading:

  • PHP 8.0 minimum. Update your CI matrix, composer.json platform constraint, and any Laravel version pinned to a PHP 7.4 runner. This is the change most likely to fail your build rather than your runtime.
  • MinecraftPing::Query now sends a handshake followed by the status ping packet, with protocol -1. This is the correct modern flow and fixes compatibility with 1.7+ servers, BungeeCord/Velocity proxies, and servers that reject a bare status request. But if you had a custom/old server or a mock that asserted on raw packet bytes, retest it. -1 means "protocol unknown"; most servers echo their own version back, but a few strict implementations may reject it — if you see handshake failures on an unusual fork, that's the first place to look.
  • Strings are now decoded from ISO-8859-1. If you previously ran utf8_encode() / mb_convert_encoding() over the MOTD or player names to fix mojibake, remove those hacks now — you'll get double-encoded garbage. Conversely, if you were relying on the raw bytes for anything, that data is no longer raw. Test with a non-ASCII MOTD and a non-ASCII player name before shipping.
  • Improved types means stricter return types. If you subclassed these classes, decorated them, or mocked them in tests, your overrides may now violate return-type covariance. Run PHPStan/Psalm and your test suite after the bump.

Protocol-level pitfalls (version-independent):

  • MinecraftQuery needs enable-query=true. It is off by default, uses UDP, and its port is query.port — which is frequently not the same as server.port. A ping succeeding while query fails almost always means this.
  • Offline/unreachable servers throw, they don't return false. Always wrap in try/catch or rescue() — an uncaught exception on a dashboard with a dead server is a 500.
  • Timeouts are your responsibility. Default socket timeouts are too long for web requests. Set 1–2s for anything user-facing, longer (5s+) only inside queued jobs.
  • SRV records. Clients resolve _minecraft._tcp. SRV for custom domains. If you support user-supplied addresses, resolve SRV yourself or you'll ping the wrong port.
  • Don't ping on user input. Unvalidated host/port from a request is an SSRF vector and a free port-scanner. Restrict to admin-configured servers, or strict-validate to a hostname + integer port range.
  • Cache on failure too. Cache::remember won't store a thrown exception, so a down server gets retried on every request — cache a sentinel "offline" result with a shorter TTL to avoid hammering it.
  • The UDP query can hang on some hosts even when the TCP port answers. If a job occasionally stalls, put the query behind a process timeout rather than trusting the library's default.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums