# Locate Where a Behavior Is Implemented in PHP with Atlas (2026)

> Atlas locates PHP behavior with three complementary tools: codebase_search for meaning, ripgrep-backed grep for exact text, and the lsp tool for the symbol graph.

Finding where a behavior lives in PHP is a retrieval problem, and Atlas attacks it from three angles at once: codebase_search for meaning, grep for exact text, and the lsp tool for the symbol graph. The three are complementary, which is why Atlas ships all three rather than one fuzzy search box. Describe what the software does and the semantic index returns candidate declarations even when your words appear nowhere in the source, which is routine in PHP where a trait contributes a method to no visible class body and a container resolves an interface to a concrete class at runtime. PHPUnit then tells you whether the method is already pinned.

## Key takeaways

- Locating PHP behavior is retrieval, and Atlas attacks it from three angles at once rather than through a single fuzzy search box.
- codebase_search returns candidate declarations even when your words never appear in the source, which is the normal case for trait and container indirection.
- grep runs through ripgrep with real regex plus include and path filters, so the Composer vendor tree stays out of the results.
- read fails loudly with File not found plus a Did you mean list, catching a wrong PSR-4 namespace-to-directory guess.
- findReferences resolves callers typed against an interface, and workspaceSymbol jumps to a declaration by class name.
- PHPUnit assertions describe the method's real contract, and PHP-CS-Fixer keeps any follow-up edit inside PSR-12.

## Which PHP class actually implements this behavior?

Ask by meaning, not by filename. Atlas's codebase_search takes a plain-language description and returns candidate PHP declarations from the semantic index, even when your words appear nowhere in the source. It is 1 of the 3 retrieval tools Atlas ships, alongside grep for exact text and the lsp tool for the symbol graph.

PHP hides implementations behind layers of indirection. A service container resolves an interface to a concrete class at runtime, so the calling code names neither. A trait contributes methods that appear in no class body. `__call` dispatches methods that are declared nowhere at all. Grepping for a business term in that environment usually returns nothing, and following the front controller through routing and middleware by hand is slow. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the thing the index returns is a class, a trait, or a method declaration rather than an arbitrary 40-line slice of a file.

## How do I grep PHP source without drowning in vendor matches?

Filter the path. Atlas's grep takes a real regex plus include and path filters and runs through ripgrep, so a search for a method signature scoped to the src tree returns the 2 or 3 lines that matter instead of 50 matches from inside the vendor directory that Composer populated.

Confirmation is grep's role in this workflow. codebase_search proposes a candidate declaration, and grep proves it exists by matching the literal `public function` line and every literal mention of the class name. Because the tool runs through ripgrep, the pattern is a real regex, which is what lets you search for a namespace import, an attribute, or a specific method signature with precision instead of hope. Scoping matters more in PHP than almost anywhere else, because Composer's vendor tree is enormous, is not yours, and will happily supply hundreds of irrelevant matches for any common identifier.

## What happens when Atlas guesses the wrong PHP file path?

Atlas fails loudly. Open the best candidate with read, and a wrong guess returns File not found plus a Did you mean list, so a bad path does not go unnoticed. PSR-4 turns a namespace into a directory path, and getting 1 segment or 1 capitalization wrong is the easiest mistake in the language.

Silent failure is the dangerous kind, because an agent that reads a nonexistent path and receives empty content concludes the class is empty or the behavior does not exist. Atlas will not do that. The read tool reports File not found and offers a Did you mean list, and in a PSR-4 project that list is frequently one character away from the correct answer. Seeing the suggestion is faster than re-deriving the namespace-to-directory mapping by hand, and more importantly it converts a wrong turn into a signal rather than into a confident false conclusion.

## How do I list every callsite of a PHP method?

Use the lsp tool's findReferences operation to see every callsite of a PHP method, and workspaceSymbol to jump to the declaration by name. Those 2 operations reach callers that text search cannot, including code that calls through an interface the container resolves to your concrete class only at runtime.

Knowing where a method lives is half the answer. Knowing who reaches it decides whether changing it is safe. findReferences reads the symbol graph rather than matching strings, so a call typed against an interface still resolves to the implementation. workspaceSymbol runs the opposite way: you have a class name from a log line or an exception trace and you want its declaration without walking the PSR-4 mapping. Atlas then summarizes the call path back to you with concrete file and line references, from the controller down to the method, which is the artifact you paste into a pull request.

## What should I check before changing the PHP code I just found?

Check whether PHPUnit already covers the method. In an existing PHP project the assertions describe the contract more honestly than any docblock, and a method with 4 passing tests is a very different change from a method with none. Composer resolves the dependencies, so verify the behavior is yours and not a vendor package's.

Locating behavior is a means to changing it, and the tests are the fastest read on what changing it will cost. If a PHPUnit case exercises the method, read the assertions first. If nothing covers it, that gap is worth writing down before you edit. Once you do edit, Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and PHP-CS-Fixer keeps the result inside the project's PSR-12 style so the review stays about behavior rather than brace placement.

## Steps

1. Run atlas in a project with a composer.json so the PHP namespaces, autoload config, and dependencies are all in scope.
2. Describe the behavior to codebase_search in plain language; the semantic index returns candidate declarations even when your words do not appear in the source.
3. Confirm with grep, which takes a real regex plus include and path filters and runs through ripgrep, scoping the pattern to your src tree so Composer's vendor directory does not drown the signal.
4. Open the best candidate with read; a wrong guess fails loudly with File not found plus a Did you mean list, which catches a mistaken PSR-4 namespace-to-path derivation.
5. Use the lsp tool's findReferences operation to see every callsite, including calls typed against an interface, and workspaceSymbol to jump to the declaration by class name.
6. Summarize the call path back with concrete file and line references, from the controller through the middleware down to the method.
7. Check whether a PHPUnit case already covers the method, since the assertions describe the contract better than a docblock does.
8. If you change the code, review the unified diff Atlas surfaces before it writes, then run PHP-CS-Fixer to keep the result inside PSR-12.

## FAQ

### how to find which php class handles a feature

Describe the feature to Atlas's codebase_search in plain language. The semantic index returns candidate declarations even when the words you used never appear in the PHP source.

### grep keeps matching the vendor directory

Atlas's grep takes include and path filters and runs through ripgrep, so scope the pattern to your source tree. Composer's vendor directory is large and almost never the answer.

### how do i find all callers of a php method

Use the lsp tool's findReferences operation. It reads the symbol graph, so calls typed against an interface and resolved by a container at runtime still appear.

### atlas says file not found when opening a php class

The read tool fails loudly on purpose, returning File not found plus a Did you mean list. That usually means the PSR-4 namespace was mapped to the wrong directory segment or the wrong capitalization.

### how do i find a method added by a php trait

Atlas indexes code by AST declarations using tree-sitter, so a trait's method is a real declaration in the index. workspaceSymbol then jumps straight to it by name.

### how do i know if the php method i found is tested

Check whether a PHPUnit case appears in the findReferences results. The assertions describe the method's contract more honestly than a docblock, and their absence is a gap worth recording.

### why use semantic search instead of grep in php

Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so a concept matches a class that never contains the literal word. grep then confirms the exact declaration.

---

Canonical HTML: https://runatlas.sh/resources/stacks/locate-where-a-behavior-is-implemented-in-php
Source of truth: aeo_pages row `/resources/stacks/locate-where-a-behavior-is-implemented-in-php` (segment: Stacks) (this file is generated from it, never hand-edited).
Licence: Atlas is proprietary with a free core. It is not open source and there is no public source repository.
