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

System Information Bundle Laravel Package

kmi/system-information-bundle

kmi/system-information-bundle is a Symfony bundle that collects and exposes system information, making environment and runtime details available for diagnostics, monitoring, and admin dashboards.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package. kmi/system-information-bundle is a Symfony bundle built for Sonata Admin. It has no service provider, no facade, no config/system-information.php, and no Laravel auto-discovery entry. Add to that 0 stars, 0 dependents, archived status, and a 0.065 score, and the only defensible first step is to treat it as specification material, not a dependency.

Minimal steps to get value from it:

  1. Do not composer require it. Its symfony/* and sonata-project/* constraints will fight the Symfony components Laravel already pins, and Composer will almost certainly refuse resolution under PHP 8.1+.
  2. Read the source, not the docs. Open the bundle's DependencyInjection/ extension and the Sonata Admin subclass. That admin class is where the real data collection lives — the show/form mapper fields are the author's list of "systemically relevant" data points.
  3. Skim Resources/views/ to see which fields were rendered together and in what order. That is the layout you are porting.
  4. Inventory the data points and map each to a Laravel-native source. That inventory is your actual deliverable.

Your first use case should be a single Artisan command:

// app/Console/Commands/SystemInfo.php
public function handle(): int
{
    $this->table(['Key', 'Value'], [
        ['Environment', app()->environment()],
        ['Debug',       config('app.debug') ? 'on' : 'off'],
        ['PHP',         PHP_VERSION],
        ['Laravel',     app()->version()],
        ['Cache',       config('cache.default')],
        ['Queue',       config('queue.default')],
        ['Disk free',   $this->bytes(disk_free_space(base_path()))],
    ]);

    return self::SUCCESS;
}

Laravel already ships the direct analogue — php artisan about — which covers environment, drivers, PHP version, and loaded packages. Start there, then extend with the extra rows this bundle surfaces (disk headroom, extension list, DB reachability, debug flag) and gate the command behind an environment check.

Implementation Patterns

If you genuinely need it running (you maintain a legacy Symfony/Sonata service alongside Laravel work):

  • Register it in config/bundles.php, then wire sonata_admin and sonata_block. Grant an explicit role — ROLE_SUPER_ADMIN or a dedicated ROLE_SYSTEM_INFO — and never leave the route on IS_AUTHENTICATED_ANONYMOUSLY.
  • The extension point you will actually use is the admin class: subclass it, override the show/form mapper, and append your own rows (queue worker heartbeat, last deploy SHA, last migration timestamp).
  • Custom information providers are the sanctioned extension hook — implement the bundle's provider interface and tag it in your service config rather than editing vendor code.
  • Override Twig templates via app-level bundle inheritance (templates/bundles/...) so the archived vendor tree stays untouched and replaceable.

The Laravel port — the thing you should actually build. Map fields one-to-one:

Symfony bundle surfaces Laravel source
PHP / framework versions PHP_VERSION, app()->version()
Environment + debug flag app()->environment(), config('app.debug')
Loaded packages composer show --direct, composer audit
Disk headroom disk_free_space(), cached 5 min
DB reachability + size DB::select('select 1'), DB::select('select sum(data_length+index_length) from information_schema.tables')
Cache/queue drivers config('cache.default'), config('queue.default')
Loaded extensions get_loaded_extensions()
App version / commit config('app.version'), trim(shell_exec('git rev-parse --short HEAD'))

Then expose it three ways, in increasing order of exposure:

  1. Artisan command (system:info) — for ops and CI smoke tests.
  2. Blade partial or Filament/Nova widget — behind existing admin authorization, in the back-office only.
  3. /up health endpoint — a curated subset (200/500 only). Never the full panel.

Wrap the collection in a single service so all three consumers share it:

final class SystemInfo
{
    public function __construct(private Cache $cache) {}

    public function collect(): array
    {
        return $this->cache->remember('system-info', now()->addMinutes(5), fn () => [
            'php'         => PHP_VERSION,
            'laravel'     => app()->version(),
            'environment' => app()->environment(),
            'debug'       => config('app.debug'),
            'extensions'  => get_loaded_extensions(),
            'disk_free'   => @disk_free_space(base_path()),
            'db_ok'       => $this->dbReachable(),
        ]);
    }

    private function dbReachable(): bool
    {
        try { DB::select('select 1'); return true; }
        catch (\Throwable) { return false; }
    }
}

Gotchas and Tips

Installation will fail, and that is the expected finding. Attempt a composer require in a scratch Laravel 11 app once, record the resolution error, and move on. Do not "fix" it by pinning old Symfony components — the class-collision surface is unbounded.

Information disclosure is the real risk, not performance. The panel surfaces server paths, PHP config, extension lists, and possibly environment variables. Anything rendered from it belongs behind admin authorization and must never be reachable from a public route. Curate the field list — do not dump phpinfo() equivalents into a view.

Privilege errors are silent or fatal depending on host. disk_free_space(), /proc reads, and shell_exec('git ...') all behave differently under containerized, chrooted, or restricted-disable_functions PHP. Wrap every probe in try/catch (or @ where the failure is non-actionable) and render null as — rather than throwing inside a dashboard render.

Cache the payload. The panel is not a hot path, but a busy Sonata-style dashboard render will stat the filesystem on every load. A 5–15 minute cache TTL is correct; also clear it after deploys if you show the commit SHA.

Silent staleness is the failure mode of abandoned panels. An unmaintained renderer keeps returning plausible-looking data after a PHP upgrade — no error, just wrong rows. Pin your own collector to a test that asserts each key is non-null so drift surfaces in CI.

Do not confuse this with observability. It displays static facts ("what is installed"). It does not answer "what is happening" — that is spatie/laravel-health, Laravel Pulse, Sentry, or Prometheus. Keep the roadmap items separate.

If you fork the Symfony bundle anyway, own it explicitly: a named maintainer, a fork in your org, and a review cadence tied to your PHP upgrade cycle. Zero stars and zero dependents mean no upstream triage and no community corpus to search when it breaks.

Extension point worth copying: the bundle's provider-interface pattern — a taggable collection of information providers — is a good shape for your Laravel version too. A SystemInfoProvider interface with tagged implementations makes it trivial to add "last queue heartbeat" or "last deploy" later without touching the collector.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core