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.
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.
Step by step
- 01Run atlas in a project with a composer.json so the PHP namespaces, autoload config, and dependencies are all in scope.
- 02Describe the behavior to codebase_search in plain language; the semantic index returns candidate declarations even when your words do not appear in the source.
- 03Confirm 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.
- 04Open 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.
- 05Use 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.
- 06Summarize the call path back with concrete file and line references, from the controller through the middleware down to the method.
- 07Check whether a PHPUnit case already covers the method, since the assertions describe the contract better than a docblock does.
- 08If 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.
Frequently asked questions
- 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.
Try Atlas in your terminal
The terminal-native AI coding agent. Free core, single binary.
Install AtlasRelated guides
Locate Where a Behavior Is Implemented with Atlas in 2026
How to locate where a behavior is implemented with Atlas in 2026: codebase_search for meaning, grep for exact text, and the lsp tool for the symbol graph.
Atlas for PHP in 2026
Atlas, the terminal-native AI coding agent, empowers PHP developers in 2026 with intelligent code understanding, secure workflows, and direct integration for Composer and PSR standards.
Onboard to an Unfamiliar PHP Codebase with Atlas (2026)
Build a mental model of an unfamiliar PHP repo in 2026 without reading every file. Atlas maps the Composer layout, delegates sweeps to a read-only explore subagent.
Audit a PHP Repository with Parallel Subagents in 2026
Sweep your entire PHP codebase for issues without context window limits. Atlas uses parallel subagents to audit Composer packages and PSR standards, integrating with PHPUnit and PHP-CS-Fixer.
Add a regression test for a bug fix in PHP with Atlas (2026)
Add a PHP regression test for a bug fix in 2026: Atlas proves the PHPUnit test fails red first, applies the fix with edit, and re-runs the same command to prove green.
Refactor a Legacy PHP Module with Atlas Without Breaking Callers (2026)
How Atlas refactors a legacy PHP module in 2026: map callers with the lsp tool, pin behavior with PHPUnit, restructure with apply_patch, and format with PHP-CS-Fixer.
Self-review your working diff before committing in PHP with Atlas in 2026
Catch your own mistakes in PHP code before they reach a reviewer or CI. Atlas helps PHP developers in 2026 self-review uncommitted diffs, run PHPUnit tests, and apply PHP-CS-Fixer formatting.
Review a Pull Request in PHP with Atlas in 2026
Streamline your PHP pull request reviews in 2026 with Atlas, the terminal-native AI agent. Leverage PHPUnit, Composer, and PHP-CS-Fixer for thorough, context-aware code analysis, catching bugs a line-by-line read would