laravel/ranger
Beta Laravel introspection library that walks your codebase and exposes rich DTOs for routes, models, enums, broadcast events, env vars, and Inertia components. Register callbacks per item or collection, then run a single walk to process everything.
Installation:
composer require laravel/ranger
Add to config/app.php under providers:
Laravel\Ranger\RangerServiceProvider::class,
First Use Case: Inspect all routes in your application:
use Laravel\Ranger\Ranger;
$ranger = app(Ranger::class);
$ranger->onRoute(function ($route) {
echo $route->uri() . "\n";
});
$ranger->walk();
Where to Look First:
Laravel\Ranger\Components namespace for detailed DTO structures (e.g., Route, Model).$hidden, $visible, and $appends properties in model inspection (new in v0.2.4).Model Attribute Inspection:
Leverage $hidden, $visible, and $appends in model callbacks:
$ranger->onModel(function ($model) {
$this->info('Visible Attributes: ' . implode(', ', $model->visibleAttributes()));
$this->info('Appended Attributes: ' . implode(', ', $model->appendedAttributes()));
});
Component-Specific Callbacks: Register callbacks for granular control over individual components:
$ranger->onModel(function ($model) {
// Log model attributes (respecting $hidden/$visible)
file_put_contents('models.log', $model->name() . ': ' . implode(', ', $model->getVisibleAttributes()), FILE_APPEND);
});
Bulk Processing: Use collection callbacks for post-processing after all components are discovered:
$ranger->onModels(function (Collection $models) {
$models->each(function ($model) {
// Generate API docs from models, respecting $appends
$this->info($model->name() . ' - Appends: ' . $model->appendedAttributes());
});
});
Artisan Command: Encapsulate Ranger in a custom Artisan command for CLI usage:
use Laravel\Ranger\Ranger;
use Illuminate\Console\Command;
class ModelInspectCommand extends Command
{
protected $signature = 'app:inspect-models';
protected $description = 'Inspect models with hidden/visible/appends';
public function handle(Ranger $ranger)
{
$ranger->onModel(fn($model) => $this->info(
$model->name() . ': ' .
implode(', ', $model->getVisibleAttributes())
));
$ranger->walk();
}
}
Event Listeners:
Trigger Ranger during application bootstrapping (e.g., booted event):
use Laravel\Ranger\Ranger;
public function booted()
{
$ranger = app(Ranger::class);
$ranger->onModels(fn($models) => $this->cacheModelAttributes($models));
$ranger->walk();
}
Testing: Use Ranger in PHPUnit tests to validate model attributes:
public function testModelVisibility()
{
$ranger = app(Ranger::class);
$ranger->onModel(function ($model) {
$this->assertNotContains('password', $model->getVisibleAttributes());
$this->assertContains('api_token', $model->appendedAttributes());
});
$ranger->walk();
}
Dynamic Configuration: Load callbacks from config files:
$callbacks = config('ranger.callbacks');
foreach ($callbacks as $type => $callback) {
$method = 'on' . ucfirst($type);
$ranger->$method($callback);
}
Performance:
--env=testing or cache results:
$ranger->walk()->cache()->forever();
Model Attribute Resolution:
$hidden and $visible properties now override default attribute visibility (v0.2.4).getVisibleAttributes() and appendedAttributes() methods for consistency:
$ranger->onModel(function ($model) {
$this->info('Visible: ' . implode(', ', $model->getVisibleAttributes()));
});
Route URI Resolution:
Route::domain('admin')->group(...)) may not resolve as expected.APP_URL is set correctly in .env or use absolute paths:
$ranger->onRoute(function ($route) {
$this->info($route->uri()); // Uses APP_URL + base_path()
});
Inertia.js Quirks:
$ranger->onInertiaComponent(function ($component) {
if (str_contains($component->path(), 'Resources/Pages')) {
// Process custom Inertia components
}
});
Environment Variables:
APP_KEY) may leak if not filtered.$ranger->onEnv(function ($env) {
if (str_contains($env->key(), ['KEY', 'SECRET'])) {
return; // Skip sensitive vars
}
$this->info($env->key() . '=' . $env->value());
});
Verbose Output: Enable debug mode for detailed logs:
$ranger->debug(true)->walk();
Model Attribute Validation: Validate model attributes with visibility rules:
public function testModelVisibility()
{
$ranger = app(Ranger::class);
$ranger->onModel(function ($model) {
$this->assertNotContains('password', $model->getVisibleAttributes());
$this->assertContains('api_token', $model->appendedAttributes());
});
$ranger->walk();
}
Partial Walks:
Use only() to inspect specific collectors:
$ranger->only(['routes', 'models'])->walk();
Excluding Directories: Skip vendor or test directories:
$ranger->ignoreDirectories(['vendor', 'tests'])->walk();
Custom Collectors: Extend Ranger by creating a custom collector:
use Laravel\Ranger\Collector;
class CustomCollector implements Collector
{
public function collect()
{
return collect([new CustomComponent('data')]);
}
}
Register it in RangerServiceProvider:
public function register()
{
$this->app->singleton(Ranger::class, function ($app) {
$ranger = new Ranger();
$ranger->addCollector(new CustomCollector());
return $ranger;
});
}
DTO Customization: Override DTO properties in callbacks:
$ranger->onRoute(function ($route) {
$route->setMetadata(['tags' => ['api']]);
});
Post-Walk Processing:
Chain methods after walk():
$results = $ranger->walk()->getResults();
$results['models']->each(function ($model) {
$this->info($model->name() . ': ' . implode(', ', $model->getVisibleAttributes()));
});
Model Attribute Inspection: Create custom inspection methods for models:
$ranger->onModel(function ($model) {
$this->info('Full Attributes: ' . implode(', ', $model->getAttributes()));
$this->info('Visible Attributes: ' . implode(', ', $model->getVisibleAttributes()));
$this->info('Appended Attributes: ' . implode(', ', $model->appendedAttributes()));
});
How can I help you explore Laravel packages today?