laravel/ranger
Beta Laravel introspection library that scans your codebase to discover routes, models, enums, broadcast events, env vars, and Inertia components. Register callbacks per item or collection and receive rich DTOs as Ranger walks your app.
Installation:
composer require laravel/ranger
Register the service provider in config/app.php under providers:
Laravel\Ranger\RangerServiceProvider::class,
First Use Case: Run a basic scan in a command or controller:
use Laravel\Ranger\Ranger;
$ranger = app(Ranger::class);
$ranger->walk(); // Triggers all registered callbacks
Key Files:
app/Providers/RangerServiceProvider.php (if customizing)config/ranger.php (future config, currently minimal)app/Console/Commands/ (for CLI integration)Register Callbacks:
// Individual items
$ranger->onRoute(fn($route) => $this->logRoute($route));
$ranger->onModel(fn($model) => $this->analyzeModel($model));
// Entire collections
$ranger->onRoutes(fn(Collection $routes) => $this->generateRouteMap($routes));
DTO-Based Processing: Each callback receives a DTO with structured data:
$ranger->onModel(function (Components\Model $model) {
$model->getAttributes(); // ['name' => 'string', 'email' => 'string']
$model->getRelations(); // ['user' => 'App\Models\User']
$model->getFilePath(); // 'app/Models/User.php'
});
Common Use Cases:
.env variables.Integration with Laravel Features:
use Laravel\Ranger\Ranger;
class ScanCommand extends Command {
public function handle() {
$ranger = app(Ranger::class);
$ranger->walk();
// Process results...
}
}
public function boot() {
$ranger = app(Ranger::class);
$ranger->onRoutes($this->generateRouteCache(...));
}
Conditional Processing:
$ranger->onRoute(function (Components\Route $route) {
if ($route->isApi()) {
$this->generateApiDocs($route);
}
});
Performance:
onRoutes, onModels) instead of individual items.Beta API:
v1.0. Avoid relying on undocumented properties.Route URIs:
Route::domain() URIs are returned relative to APP_URL (not absolute).domain('admin.app')->uri('users') → /admin/users (not https://admin.app/users).Model Attributes:
$hidden, $visible, and $appends are respected (since v0.2.4), but custom casts may not be fully reflected.Inertia Props:
string|int) in Inertia props require v0.2.3+ for accurate detection.Inspect DTOs:
$ranger->onRoute(function (Components\Route $route) {
dd($route->toArray()); // Debug full structure
});
Filter Components:
$ranger->onRoute(function (Components\Route $route) {
if (str_contains($route->uri(), 'admin')) {
$this->processAdminRoute($route);
}
});
Skip Unnecessary Scans:
tests/, workbench/) by modifying RangerServiceProvider:
protected function getExcludedDirectories(): array {
return array_merge(parent::getExcludedDirectories(), ['storage/', 'vendor/']);
}
Handle Missing Data:
BroadcastEvents) may return empty collections if no events are found.Custom Collectors:
Extend Laravel\Ranger\Collectors\Collector to scan additional components (e.g., custom macros):
class MacroCollector extends Collector {
public function collect() {
return $this->app->make(MacroAnalyzer::class)->analyze();
}
}
Modify DTOs: Override DTO properties in a service provider:
$ranger->onRoute(function (Components\Route $route) {
$route->setCustomTag('api' => $route->uri() === '/api');
});
Post-Processing: Chain callbacks to transform data:
$ranger->onModels(function (Collection $models) {
$models->each(fn($model) => $this->validateModel($model));
});
Environment Variables:
DB_PASSWORD) are not exposed by default. Use cautiously:
$ranger->onEnv(function (Components\Env $env) {
if ($env->isSensitive()) {
$this->logSensitiveVar($env->name());
}
});
spatie/laravel-api-docs or darkaonline/l5-swagger by extracting route metadata.$ranger->onInertiaComponent(function (Components\InertiaComponent $component) {
$this->generateTypeScriptInterface($component);
});
$ranger->onModels(function (Collection $models) {
$models->each(fn($model) => $this->generateValidationRules($model));
});
```markdown
### Example: Full Command Integration
```php
use Laravel\Ranger\Ranger;
use Illuminate\Console\Command;
class RangerAuditCommand extends Command {
protected $signature = 'ranger:audit';
protected $description = 'Audit application components with Ranger';
public function handle() {
$ranger = app(Ranger::class);
// Route analysis
$ranger->onRoutes(function (Collection $routes) {
$this->info("Found {$routes->count()} routes");
$routes->each(fn($route) => $this->line("• {$route->method()} {$route->uri()}"));
});
// Model validation
$ranger->onModels(function (Collection $models) {
$models->each(fn($model) => $this->generateValidationRules($model));
});
$ranger->walk();
}
protected function generateValidationRules(Components\Model $model) {
$rules = [];
foreach ($model->getAttributes() as $name => $type) {
$rules[$name] = match ($type) {
'string' => 'required|string',
'integer' => 'required|integer',
default => 'required',
};
}
$this->line("<comment>Validation for {$model->getName()}:</comment>");
$this->line(print_r($rules, true));
}
}
How can I help you explore Laravel packages today?