laravel/surveyor
Laravel Surveyor is a mostly static analysis tool for PHP/Laravel code. It parses files to extract metadata on classes, methods, properties, and types, and can also inspect models (brief DB connection) and container bindings to enrich results for other tools/packages.
Installation:
composer require laravel/surveyor
No additional configuration is required for basic usage.
First Use Case:
Run Surveyor on a directory (e.g., app/) to extract metadata:
use Laravel\Surveyor\Surveyor;
$surveyor = new Surveyor();
$results = $surveyor->survey(app_path('Http/Controllers'));
This returns an array of Surveyor\Result objects, each representing a parsed PHP file.
Where to Look First:
Surveyor class: Core entry point for analysis.Result class: Contains parsed metadata (e.g., classes, methods, properties).Surveyor::survey(): Primary method to trigger analysis.Surveyor::getResults(): Retrieve raw results (useful for debugging).Surveying a Directory:
$results = Surveyor::survey(base_path('app'));
foreach ($results as $result) {
// Access parsed data: $result->classes, $result->methods, etc.
}
Filtering Results:
Use Surveyor::filter() to narrow results (e.g., by namespace or class name):
$filtered = $results->filter(fn ($result) => str_contains($result->namespace, 'App\\Http\\Controllers'));
Extracting Specific Metadata: Access structured data directly:
foreach ($results as $result) {
$methods = $result->methods->where('isPublic', true);
$properties = $result->properties->where('isStatic', false);
}
Integration with Laravel Ranger:
For high-level DTOs, pair with laravel/ranger:
use Laravel\Ranger\Ranger;
$ranger = new Ranger();
$ranger->analyze($results); // Convert Surveyor results to Ranger DTOs
Artisan Command: Create a custom command to run Surveyor periodically (e.g., during CI):
use Laravel\Surveyor\Surveyor;
use Symfony\Component\Console\Command\Command;
class SurveyCommand extends Command {
protected function handle() {
$results = Surveyor::survey(app_path());
// Log or process results...
}
}
Event Listeners:
Trigger Surveyor on file changes (e.g., via file:updated events) to keep metadata fresh.
Caching:
Cache results for performance (e.g., in bootstrap/cache):
$cacheKey = 'surveyor_results';
$results = Cache::remember($cacheKey, now()->addHours(1), fn () => Surveyor::survey(app_path()));
Beta API Instability:
v1.0.0. Check the changelog for breaking changes.composer.json (e.g., ^0.1.0) to avoid unexpected updates.Performance with Large Codebases:
vendor/ or storage/ to speed up analysis:
$surveyor = new Surveyor(['exclude' => ['vendor', 'storage']]);
False Positives in Parsing:
eval(), create_function()). Avoid relying on its output for such cases.Namespace Resolution:
composer dump-autoload is up to date.Enable Verbose Output:
Pass ['verbose' => true] to the Surveyor constructor to log parsing details:
$surveyor = new Surveyor(['verbose' => true]);
Inspect Raw Results:
Use Surveyor::getRawResults() to debug parsing issues:
$rawResults = Surveyor::getRawResults();
dd($rawResults); // Inspect the underlying data structure.
Custom Analyzers: Extend Surveyor by creating custom analyzers (e.g., to detect deprecated methods):
use Laravel\Surveyor\Contracts\Analyzer;
class DeprecationAnalyzer implements Analyzer {
public function analyze($result) {
foreach ($result->methods as $method) {
if (str_contains($method['docComment'], '@deprecated')) {
// Trigger a warning or log the issue.
}
}
}
}
Register the analyzer via the Surveyor constructor:
$surveyor = new Surveyor(['analyzers' => [new DeprecationAnalyzer()]]);
Post-Processing: Use Laravel collections to transform results:
$controllers = $results->flatMap->classes
->where('name', 'ends_with', 'Controller')
->pluck('methods');
Integration with Static Analysis Tools: Export Surveyor results to JSON for use with other tools (e.g., SonarQube):
file_put_contents(
storage_path('app/surveyor_results.json'),
json_encode($results->toArray())
);
Exclusion Patterns: Use glob patterns to exclude files/directories:
$surveyor = new Surveyor(['exclude' => ['tests/*', 'app/Console/*']]);
File Extensions:
Surveyor defaults to .php files. To include other extensions (e.g., .inc), pass:
$surveyor = new Surveyor(['extensions' => ['php', 'inc']]);
How can I help you explore Laravel packages today?