Skip to main content

Limitations & Risks

Prune performs static analysis only. It does not execute your code, so it cannot detect references that exist only at runtime. Treat its output as a list of candidates to investigate, never as a confirmed delete list.

danger

Always review before deleting! Removing a class that Prune flagged — without checking — can break your application. Read this page before acting on a report.

Things Prune cannot see​

Dynamic instantiation​

Classes created from a variable or resolved by a container are invisible:

$class = 'App\\MyClass';
new $class();
app()->make(MyService::class); // resolved at runtime

This pattern is common in service containers, factories, and plugin systems.

String-based references​

Class names passed as plain strings — to config arrays, route definitions, or event listeners — are not detected. Laravel service providers, middleware stacks, and config files frequently reference classes this way.

Reflection and magic methods​

Code using ReflectionClass, __call, or __callStatic to interact with classes dynamically is not tracked. (Note: class_exists() and similar functions are tracked, but only for fully qualified string names — see What Gets Detected.)

External consumers​

If your project is a library, its public API classes may look unused because the consumers live outside the scanned directories.

Framework auto-discovery​

Some frameworks discover classes by convention — Laravel commands, event listeners, policies, Nova resources, and so on. These often have no explicit reference in your own code.

Generated code​

Classes produced at build time or by code generators may not exist when Prune scans, which can cause references to them to be missed.

Scope of analysis​

Only files inside the configured paths are scanned. If a class is referenced solely from a file outside those paths — a test suite, a script not under src/ — it will still be reported as orphaned. Use excludePaths, additional paths, or referencePaths to widen or narrow the scope deliberately.

Blade analysis scope​

Blade view detection only covers @include, @extends, @component, @each, @livewire, <x-…>/<livewire:…> tags, and view()/Route::view() calls. Custom directives, dynamically named views, and JavaScript-driven component rendering are not tracked.

Recommendation​

  1. Run Prune.
  2. For each reported class or view, search the codebase (and any consumers) for dynamic, string-based, or convention-driven uses.
  3. Add anything that is intentionally referenced indirectly to excludePaths / excludeViews, or widen referencePaths.
  4. Only then remove what remains genuinely dead.

For tuning which paths and views are considered, see the Configuration File.