akaunting/laravel-version
Akaunting's Laravel Version package offers a simple, config-driven way to manage and display your Laravel app's version number. Centralize release metadata, expose it via helpers, and keep version info consistent across your application. It's lightweight and easy to integrate.
Install and confirm compatibility first, not last. The package's last release is March 2021, so before writing a single line of integration code:
composer require akaunting/laravel-version
Then check composer.json in the installed package for illuminate/* constraints and the php requirement. If you're on Laravel 9+, the constraints will likely be too narrow and the install will fail or need --ignore-platform-reqs. Treat that as your go/no-go decision.
Let auto-discovery register the provider (the package ships a Laravel provider, so no manual config/app.php edit on 5.5+). If you don't see the service provider picked up, run php artisan package:discover and check the package's composer.json extra.laravel block — that tells you the exact provider and any aliases.
Publish the config before doing anything else:
php artisan vendor:publish --tag=version-config
# or, if the tag isn't defined:
php artisan vendor:publish --provider="Akaunting\Version\VersionServiceProvider"
Open config/version.php. This is where the package decides where the "current" version comes from — usually a composer.json path, a hard-coded string, or a config key. Get this pointed at the right source before testing anything else; a wrong path is the #1 reason getCurrent() returns null/empty.
First use case — read the current version and display it. Resolve the version service from the container (or use the facade if one is aliased) and render it in a footer or admin "About" panel:
$version = app(\Akaunting\Version\Version::class);
// Typical shape — verify names against the package source
$current = $version->getCurrent(); // e.g. "1.2.3"
$latest = $version->getLatest(); // remote/known-latest
$isNew = $version->isLatest(); // or an equivalent comparison helper
Confirm the actual method names by opening src/Version.php — this package is small enough to read end-to-end in five minutes, and you should, because the docs are thin.
Where to look first, in order:
src/Version.php — the public API and the comparison logic.config/version.php — the current-version source and remote endpoint.src/Providers/ — what's bound into the container and under what key.Console/ commands — there may be a version:show / version:check command that saves you writing glue code.Single source of truth for the current version. Point the config at composer.json (or a dedicated config('app.version') you keep in sync via CI). Do not hard-code the version in a Blade template and also read it from the package — you'll get drift and a false "update available" banner.
Update-available banner / admin widget. The canonical use case:
// app/Http/View/Composers/VersionComposer.php
public function compose(View $view)
{
$view->with('updateAvailable', app(Version::class)->isLatest());
}
Cache the remote check aggressively (see Gotchas) so the composer never blocks on network I/O.
Scheduled version check. Rather than checking on every request, run a scheduled job that resolves the latest version once and stores it:
// app/Console/Kernel.php
$schedule->call(function () {
Cache::put('latest_version', app(Version::class)->getLatest(), now()->addHours(12));
})->daily();
Then have the UI read Cache::get('latest_version'). This is the most robust integration and isolates you from the package's remote-fetch behaviour changing or breaking.
Semver comparison for upgrade gating. If you use the package to decide whether to show "upgrade to Pro" or to block a deprecated feature, wrap the comparison in your own service so your codebase doesn't depend on the package's exact comparison semantics:
class VersionGate
{
public function isAtLeast(string $minimum): bool
{
return version_compare(
app(Version::class)->getCurrent(),
$minimum,
'>='
);
}
}
CI/CD bump. If the package exposes a setter (e.g. setCurrent() or a version:bump command), use it in your release pipeline after composer install --no-dev, then commit the changed file. If it only reads, skip it and manage versions yourself with composer version or a Makefile target — the package gives you nothing on the write side.
Feature flags tied to version. For a package this small, prefer your own feature-flag table. Tying runtime behaviour to a detected version string is brittle once you ship patch releases; use the package only for displaying/announcing, not for gating logic.
The package is stale (last release March 2021). Laravel 9/10/11 projects will hit illuminate constraint conflicts and possibly ->getCurrent() returning null because the provider registers against a config key that was renamed. Decide early whether to (a) fork and update constraints, (b) copy the ~200 lines you actually need into app/Support/Version.php, or (c) use composer/semver directly. For a 38-star package that just wraps version_compare and a file_get_contents of composer.json, option (b) or (c) is usually the pragmatic call.
Remote fetch is synchronous and uncached by default. Whatever getLatest() does — GitHub API, file_get_contents, Guzzle — it will block the request. Always wrap in Cache::remember(). Watch for GitHub's unauthenticated rate limit (60 req/hr/IP) if it hits the GitHub releases endpoint.
file_get_contents() on URLs may be disabled. Many hosts set allow_url_fopen=0. If the package uses file_get_contents for the remote check, it will silently fail (returning false → null → "up to date"). Check for a config option to swap in a Guzzle-based client, or override the transport yourself.
Config file path resolution. The composer.json path in config is resolved relative to something — likely base_path(). In tests (phpunit.xml with a different root) this breaks. Use base_path() explicitly in your own wrapper, or point the config at an env var so tests can override it.
Semver edge cases. version_compare('1.2.3-beta', '1.2.3', '<') is true, but many home-grown comparisons in older packages assume three numeric segments and choke on v1.2.3, 1.2.3+meta, or dev-main. If your current version comes from composer.json and your package version starts with v, strip it before comparing.
No Laravel 9+ ServiceProvider API guarantees. If the package's provider calls $this->app->bind(...) or uses config_path() in a way that's fine, great — but it may also register a route or command that conflicts. If you get a BindingResolutionException or a duplicate route, manually register the provider as deferred or strip the offending registration in a subclass.
Publishing tags aren't guaranteed. Older packages often lack publishes() tags. If vendor:publish --tag=version-config silently does nothing, fall back to --provider= and, failing that, copy config/version.php out of vendor/ manually.
Extension points are thin. The clean spots to hook in are: the config (current-version source, remote endpoint), the container binding (swap the class for your own implementation implementing the same interface — if there isn't an interface, instance() bind your subclass), and Blade view composers. If you need more control than that, fork.
Debugging checklist when "nothing happens":
php artisan tinker → app(\Akaunting\Version\Version::class) — does it resolve?->getCurrent() — non-empty? If not, config path is wrong.->getLatest() — false/null? Network or allow_url_fopen.try/catch (\Throwable $e) {} — older packages swallow or don't catch transport exceptions, and you'll get a 500 on the footer of every page.Alternative worth considering: composer/semver for comparison, guzzlehttp/guzzle for the release check, plus a version column in a settings table or a config/app.php entry. That's roughly the whole package, minus the maintenance risk. Only adopt akaunting/laravel-version today if you're maintaining an Akaunting-derived codebase where its conventions are already in place.
How can I help you explore Laravel packages today?