mattsches/version-eye-bundle
A Symfony bundle that surfaces installed Composer dependency versions and update status, helping you spot outdated packages and keep your project's dependencies current.
First, the reality check. mattsches/version-eye-bundle is a Symfony2 bundle (last tagged release August 2016, PHP 5.5/7.0-era constraints, zero dependents) that wraps the VersionEye SaaS API — a service that scanned composer.lock-style manifests and reported outdated dependencies, license violations, and known CVEs across 12+ languages. VersionEye shut down at the end of 2017. So the bundle is not something you "install and use" in a Laravel app; it is a reference implementation for the shape of a dependency-audit integration.
You cannot composer require it into a Laravel project — it depends on symfony/framework-bundle, the Symfony DI Extension/Configuration conventions, and a parameters.yml-style config. What you can do, and what a day-to-day assessment should focus on, is mine it for the pattern and replace the transport.
Where to look first, in order:
DependencyInjection/Configuration.php + MattschesVersionEyeExtension.php — the config tree (API key, base URL, defaults) and how the client service is constructed.Resources/config/services.xml — the actual service ids you'd inject in a legacy Symfony app.Command/ — the CLI entry points; this is where the day-to-day workflow lives (typically "check this project and print/exit non-zero on outdated or vulnerable packages").mattsches/version-eye-api package the bundle wraps) — this is the only genuinely reusable asset, because it encodes the endpoint contract: project CRUD, package lookups, and the composer.lock upload used for scanning.First use case. In Laravel, the honest first use case is a nightly artisan command that answers one question: "what's outdated or vulnerable in this app right now?" — and in 2024+ the answer should come from Composer itself, not from a defunct SaaS. Treat the bundle as a spec for the report you want (package, current version, latest version, severity, license), then implement it with composer outdated --format=json, composer audit --format=json, and local-php-security-checker.
Legacy Symfony2 app that already has it installed. The only place the bundle works as designed:
# app/config/config.yml
mattsches_version_eye:
api_key: "%versioneye_api_key%"
Then inject the client service into a custom command and schedule it via cron. The idiomatic cycle is: hash composer.lock → skip the API call if unchanged → otherwise create/update the remote project → persist the returned outdated and security arrays locally → notify on deltas only. Never call the API on every request or on every deploy.
Porting the pattern to Laravel. The mapping is one-to-one and cheap:
| Symfony bundle piece | Laravel equivalent |
|---|---|
Configuration.php |
a block in config/services.php |
DependencyInjection/*Extension |
AppServiceProvider::register() / singleton() |
| Client service (constructor-injected) | a small final class with a typed Http client |
Command/CheckCommand |
php artisan deps:audit |
| Monolog channel | Log::channel('deps') |
// app/Services/DependencyReport.php
final class DependencyReport
{
public function __construct(private readonly string $path) {}
public function collect(): array
{
$lockHash = md5_file($this->path);
return Cache::remember("deps:report:{$lockHash}", now()->addHours(12), function () {
return [
'outdated' => $this->json('composer outdated --direct --format=json --no-interaction'),
'audit' => $this->json('composer audit --format=json --no-interaction'),
];
});
}
private function json(string $cmd): array
{
exec($cmd . ' 2>/dev/null', $out, $code);
return json_decode(implode("\n", $out), true) ?: [];
}
}
Workflow integration tips.
Notification), so the channel doesn't become noise.composer audit as a hard gate is fine, but enforcing a third-party SaaS call is not.versioneye.com will hang or fail. Set timeout => 3, connect_timeout => 2 and wrap in try/catch if you're reusing client code — otherwise a dead DNS entry becomes a five-minute cron hang.parameters.yml. If you inherit a repo doing this, rotate the key immediately and move it to env() / a secret manager before anything else.{language}/{prod|dev}/{name} (e.g. packagist/php/monolog/monolog), while Composer speaks vendor/package. Any port needs an explicit translation, and an explicit decision about whether require-dev is in scope — the bundle's default scanning behavior will surprise you on dev dependencies.debug level once — the report format (license, outdated, security with CVE ids) is the only thing worth preserving, and it's easy to lose in a rewrite.composer outdated --direct --strict (versions), composer audit (advisories, Composer 2.4+), roave/security-advisories (prevent install), local-php-security-checker (offline scanning), plus Dependabot or Renovate for continuous PRs and Enlightn or Laravel Shift for framework-level review. Ship these; keep VersionEye's reporting shape and nightly-diff workflow.How can I help you explore Laravel packages today?