ocramius/package-versions
Fast, zero-I/O access to installed Composer package versions from composer.lock. Get dependency versions at runtime via PackageVersions\Versions::getVersion(), with versions compiled during install/update—ideal for building assets or artifacts based on dependency versions.
Installation:
composer require ocramius/package-versions
Ensure composer.json includes:
"config": {
"optimize-autoloader": true
}
Run:
composer dump-autoload --optimize
First Use Case: Access a package version in your Laravel application:
use PackageVersions\Versions;
$version = Versions::getVersion('laravel/framework');
// Returns: e.g., "10.0.0@sha256hash"
PackageVersions\Versions with static methods like getVersion().composer.lock (generated during composer install or composer update).Version Lookup in Controllers/Blades:
// In a Laravel controller or Blade template
$laravelVersion = Versions::getVersion('laravel/framework');
return view('app', ['version' => $laravelVersion]);
Render in Blade:
<p>Laravel Version: {{ $version }}</p>
Dependency-Aware Artifacts: Generate version-specific assets (e.g., config files, API docs) during deployment:
$version = Versions::getVersion('vendor/package');
file_put_contents(
storage_path("app/versioned-config/{$version}.json"),
json_encode(['version' => $version])
);
CI/CD Integration: Use in GitHub Actions or GitLab CI to validate dependencies:
# .github/workflows/validate-versions.yml
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install --optimize-autoloader
- run: php -r "echo \PackageVersions\Versions::getVersion('laravel/framework');"
Dynamic Configuration: Load environment-specific configs based on dependency versions:
$phpVersion = Versions::getVersion('php');
config([
'app.php_compatibility' => [
'8.2' => require __DIR__.'/config/php82.php',
'8.3' => require __DIR__.'/config/php83.php',
][$phpVersion],
]);
Service Providers: Register a service provider to preload versions into the container:
// app/Providers/PackageVersionsServiceProvider.php
public function register()
{
$this->app->singleton('package.versions', function () {
return new class {
public function get($package) {
return Versions::getVersion($package);
}
};
});
}
Use in controllers:
$version = app('package.versions')->get('laravel/framework');
Artisan Commands: Create a custom command to dump versions:
php artisan package:versions
// app/Console/Commands/DumpPackageVersions.php
public function handle()
{
$versions = collect(Versions::getAllVersions());
$this->info($versions->toJson());
}
Testing:
Mock versions in tests using PackageVersions\Versions::setVersions() (if available) or reset composer.lock between tests.
Missing composer.lock:
Class 'PackageVersions\Versions' not found or composer.lock not generated.composer install or composer update runs before accessing versions. Avoid running in --no-scripts mode unless configured (see changelog/1.1.0).Autoloader Issues:
Class not found despite installation.composer dump-autoload --optimize and clear Laravel cache:
php artisan config:clear
php artisan cache:clear
Root Package Confusion:
Versions::rootPackageName() returns the root package name (e.g., your project name), not a dependency.Versions::getVersion('vendor/package') for dependencies.Concurrent Autoloader Regeneration:
composer update, causing race conditions.--no-plugins or ensure plugins run sequentially.HHVM Incompatibility:
Version Format:
version@hash (e.g., 10.0.0@abc123). Trim the hash if only the version is needed:
$version = explode('@', Versions::getVersion('package'))[0];
Verify composer.lock:
cat composer.lock | grep 'laravel/framework'
Ensure the package exists in the lock file.
Check Autoloader:
composer show --installed | grep package-versions
composer dump-autoload --optimize --verbose
Log Versions: Add a temporary route to debug:
Route::get('/debug/versions', function () {
return Versions::getAllVersions();
});
Custom Version Sources:
Extend PackageVersions\Versions by overriding the getVersion() logic (though this is not officially supported). Create a decorator:
class CustomVersions extends Versions {
public static function getVersion($package) {
$version = parent::getVersion($package);
return $version ? "custom-{$version}" : null;
}
}
Event Listeners: Hook into Composer events to react to version changes (e.g., trigger rebuilds):
// In a Composer plugin or Laravel service provider
$composer = new \Composer\Composer();
$composer->getEventDispatcher()->addListener(
\Composer\Script\ScriptEvents::POST_INSTALL_CMD,
function () {
// Rebuild assets based on new versions
}
);
Performance Optimization:
$cacheKey = 'package_versions:laravel/framework';
$version = cache()->remember($cacheKey, 3600, function () {
return Versions::getVersion('laravel/framework');
});
Testing:
Use PackageVersions\Versions::setVersions() (if available in future versions) or mock the composer.lock file in tests:
// Example using Laravel's filesystem
Storage::fake('composer');
Storage::put('composer.lock', file_get_contents(__DIR__.'/tests/fixtures/composer.lock'));
optimize-autoloader:
Versions::getVersion() may trigger slow I/O operations.composer.json and run composer dump-autoload --optimize.--classmap-authoritative:
Dev Dependencies:
require-dev) are not included by default. Use Versions::getDevVersion() if available (check latest docs).Publish Config: If you need to expose versions via config:
// config/package_versions.php
return [
'versions' => Versions::getAllVersions(),
];
Publish the config:
php artisan vendor:publish --tag=config
API Responses: Include versions in API responses:
return response()->json([
'data' => $resource,
'metadata' => [
'laravel_version' => Versions::getVersion('laravel/framework'),
],
How can I help you explore Laravel packages today?