stefanzweifel/laravel-stats-phploc
Fork of sebastianbergmann/phploc used to keep wnx/laravel-stats compatible across Laravel versions by supporting multiple sebastian/version releases. Measures PHP project size and structure (LOC, complexity, dependencies). Not intended for real projects.
Install via Composer (Laravel Integration)
composer require stefanzweifel/laravel-stats-phploc
The package integrates seamlessly with Laravel’s service container and provides a facade (Stats) for easy access.
First Usage
Run a basic analysis on your project’s src directory:
use Stats\Facades\Stats;
$results = Stats::analyze(app_path('src'));
$results->getLinesOfCode(); // Returns total LOC
Quick CLI Check Use Artisan to generate a report:
php artisan stats:phploc src
Outputs a structured breakdown of classes, methods, complexity, etc.
Stats\Facades\Stats provides methods like analyze(), getLinesOfCode(), getCyclomaticComplexity(), etc.stats:phploc, stats:report) for CLI-driven analysis.php artisan vendor:publish --provider="StefanZweifel\LaravelStatsPhploc\StatsPhplocServiceProvider"
Track Codebase Growth Over Time
// In a controller or scheduled job
$currentLoc = Stats::analyze(app_path('src'))->getLinesOfCode();
cache()->put('last_analysis_loc', $currentLoc, now()->addDays(7));
Compare cached values to monitor LOC trends.
Integrate with CI/CD
Add a GitHub Action or GitLab CI step to run php artisan stats:report and fail builds if LOC exceeds thresholds:
# .github/workflows/phploc.yml
- name: Check LOC
run: |
php artisan stats:phploc src --threshold=5000
if [ $? -ne 0 ]; exit 1;
Dynamic Reporting
Use the Stats::analyze() result object to build custom dashboards:
$report = Stats::analyze(app_path('src'));
return view('stats.dashboard', [
'classes' => $report->getClasses(),
'complexity' => $report->getAverageComplexityPerClass(),
]);
Exclude Directories
Configure exclusions in config/stats-phploc.php:
'excludes' => [
'tests/*',
'vendor/*',
'storage/*',
],
Laravel Events
Trigger analysis on job.processed or model.saved to log changes:
event(new AnalyzeCodebase());
Service Providers
Bind the Stats facade to a custom service for extended functionality:
$this->app->bind('stats', function () {
return new CustomStatsService(Stats::analyze(app_path('src')));
});
Testing
Mock Stats::analyze() in unit tests to avoid real file scans:
Stats::shouldReceive('analyze')->andReturn(new MockReport());
Performance Overhead
phploc on large directories (>10k files) in production.$results = cache()->remember('phploc_results', now()->addHours(24), fn() => Stats::analyze(app_path('src')));
False Positives in Complexity
--ignore flags to exclude problematic directories:
php artisan stats:phploc src --ignore="app/OldLegacyCode/*"
PHP Version Mismatches
.php-version file or Docker to enforce PHP 8.0+.Silent Failures
If Stats::analyze() returns empty data, verify:
!file_exists(app_path('src'))).chmod -R 755 app_path('src')).Command-Line Debugging
Run with --verbose to see raw phploc output:
php artisan stats:phploc src --verbose
Custom Metrics
Extend the StefanZweifel\LaravelStatsPhploc\Report class to add project-specific metrics:
class ExtendedReport extends Report {
public function getTestCoverageRatio(): float {
return $this->getLinesOfCode() / $this->getTestLinesOfCode();
}
}
Database Storage
Save reports to a stats_reports table:
Stats::analyze(app_path('src'))->saveToDatabase();
(Requires publishing migrations: php artisan vendor:publish --tag=migrations.)
Slack/Email Alerts
Hook into Laravel’s illuminate\mail or notifications to alert on LOC spikes:
if ($report->getLinesOfCode() > config('stats.threshold')) {
notify(new LocThresholdExceeded($report));
}
Default Excludes
The package excludes vendor/, node_modules/, and tests/ by default. Override in config/stats-phploc.php:
'excludes' => [
'app/Console/Kernel.php', // Exclude specific files
],
Output Format Force JSON output for API consumers:
php artisan stats:phploc src --format=json
How can I help you explore Laravel packages today?