Scopes, Custom Searches and Structural Search
In Magento 2 projects with tens of thousands of files in vendor/ and hundreds of modules in your own code, unfocused searching is inefficient. PhpStorm scopes limit search results to relevant areas, Custom Search Scopes filter down to your own modules, and Structural Search finds code patterns that cannot be meaningfully described with regex.
Table of Contents
- 1. The navigation problem in large projects
- 2. Scopes: limiting search to relevant directories
- 3. Defining custom scopes for Magento projects
- 4. Find Usages with scope: targeted instead of global
- 5. Structural Search: finding code patterns structurally
- 6. Structural Search and Replace: performing mass changes safely
- 7. More navigation shortcuts for large projects
- 8. Search tools compared
- 9. Summary
- 10. FAQ
1. The navigation problem in large projects
A typical Magento 2 project has more than 100,000 files in the vendor/ directory after composer install. On top of that come the generated classes in the generated/ directory, cached files in var/cache/, and static resources in pub/static/. A simple text search (Find in Files, Ctrl+Shift+F) without a scope restriction returns thousands of hits from these directories, none of which are relevant, because the developer only wants to search their own code in app/code/ and app/design/.
The second problem is search quality: regular expressions can find syntactic patterns, but not semantic code patterns. Anyone searching for every place where a particular service is instantiated directly through the ObjectManager instead of via constructor injection won't get far with a regex, the syntactic variations are too diverse. Structural Search solves this problem because it analyzes PHP code as an AST (Abstract Syntax Tree) and recognizes structural patterns, not just character sequences.
2. Scopes: limiting search to relevant directories
PhpStorm scopes are named groups of files and directories used for various IDE actions: search, inspections, version control, and code analysis. The default scopes (Project Files, Project Production Files, Changed Files) are a good starting point, but for Magento projects custom scopes are indispensable. Under Settings → Scopes you can define as many scopes with path patterns as you like.
Scope syntax uses path patterns: file:app/code/Mironsoft//* includes all files in your own modules. !file:app/code/Mironsoft//generated//* excludes generated files again. Scopes can be combined with && (AND) and || (OR). Once defined, a scope appears as a selectable option in all relevant dialogs: in file search, in Find Usages, in inspections, and in analysis configuration. That saves several seconds of cleaning up irrelevant hits on every single search.
# PhpStorm scope definitions for a Magento 2 project
# Settings: Settings → Scopes → + (New Scope)
# Scope 1: "Own Modules" - only app/code/Mironsoft
# Scope expression:
file:app/code/Mironsoft//*
# Scope 2: "Frontend + Backend Code" - own modules + design
# Scope expression:
file:app/code/Mironsoft//* || file:app/design/frontend/Mironsoft//*
# Scope 3: "All PHP files except Vendor/Generated"
# Scope expression:
file:*.php && !file:vendor//* && !file:generated//* && !file:pub//*
# Scope 4: "Layout and Template Files"
# Scope expression:
file:*.xml && file:app//* || file:*.phtml && file:app//*
# Scope 5: "Only changed files in own modules" (combined with VCS status)
# Use the built-in "Changed Files" scope plus your own restriction
# Usage in Find in Files (Ctrl+Shift+F):
# Set the scope dropdown to "Own Modules" -> search finds only relevant files
# No more hits from vendor/magento, vendor/hyva-themes, etc.
3. Defining custom scopes for Magento projects
For a professional Magento 2 project, a scope library that covers various development scenarios is recommended. A module scope for each of your own modules allows targeted searches within one module without distraction from other modules. A frontend scope limits searches to phtml templates, Tailwind CSS files, and Alpine.js components. An XML configuration scope covers all etc/ directories of your own modules for searching configuration files such as di.xml, routes.xml, and events.xml.
Custom scopes in PhpStorm are persistent and are stored in the project directory under .idea/scopes/ as XML files. That means they can be checked into the Git repository and shared with the team, similar to Live Templates. New team members have all defined scopes available immediately after checkout. The scope files are human readable and small, so diffs stay comprehensible. This is a significant advantage over team-specific editor configurations that have to be synchronized manually.
4. Find Usages with scope: targeted instead of global
Find Usages (Alt+F7) is one of the most powerful navigation features in PhpStorm. It finds all uses of a class, method, variable, or interface, taking into account the PHP type system, inheritance, and interfaces. This means: Find Usages on an interface finds all implementing classes and all places where the interface is used as a type hint, not just a string match of the interface name.
By default, Find Usages searches the entire project, which in Magento projects returns thousands of hits from vendor/. With Find Usages Settings (Alt+Shift+F7 or right-click → Find Usages Advanced), a scope can be selected. The dialog shows the scope dropdown with all defined custom scopes. A Find Usages on ProductRepositoryInterface with the scope "Own Modules" shows only usages in your own code, a much shorter and more relevant list than the hundreds of hits from the entire Magento core.
<?php
// Find Usages Advanced - usage examples
// PhpStorm understands the PHP type system, not just string matching
declare(strict_types=1);
namespace Mironsoft\Catalog\Api;
/**
* ProductRepositoryInterface defines the contract for product data access.
*
* Find Usages on this interface finds:
* - all classes that implement it (ProductRepository)
* - all constructors that use it as a type hint (via DI)
* - all methods that declare it as a parameter or return type
* - all di.xml entries (as a string reference)
*
* With scope "Own Modules" only your own code - no Magento core noise.
*/
interface ProductRepositoryInterface
{
/**
* Find product by ID.
*
* @param int $productId The product entity ID
* @param bool $editMode Load in edit mode (bypasses cache)
* @return \Mironsoft\Catalog\Api\Data\ProductInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getById(int $productId, bool $editMode = false): Data\ProductInterface;
/**
* Save product entity.
*
* @param \Mironsoft\Catalog\Api\Data\ProductInterface $product
* @return \Mironsoft\Catalog\Api\Data\ProductInterface
* @throws \Magento\Framework\Exception\CouldNotSaveException
*/
public function save(Data\ProductInterface $product): Data\ProductInterface;
/**
* Delete product by ID.
*
* @param int $productId
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Magento\Framework\Exception\CouldNotDeleteException
*/
public function deleteById(int $productId): void;
}
5. Structural Search: finding code patterns structurally
Structural Search (Ctrl+Shift+S) is one of the most underrated features in PhpStorm. Unlike text search (which looks for character strings) and regex search (which looks for textual patterns), Structural Search analyzes the PHP AST and finds code patterns independent of formatting, variable names, and line breaks. This enables searches like: "all methods that call $this->objectManager->create()" or "all catch blocks that only log the exception without re-throwing it".
The Structural Search template uses $VARIABLE$ placeholders that stand for arbitrary AST nodes. $method$ stands for any method call, $expression$ for any expression. Count constraints (minimum/maximum) let you define how often a placeholder must match. Type constraints restrict the placeholder to expressions of a specific type. The results are shown in the Find panel with full context and are clickable, just like a normal search, but semantically more precise.
<?php
// Structural Search templates for common Magento problem patterns
// Open: Ctrl+Shift+S -> enter the template text
// Template 1: calling ObjectManager directly (anti-pattern in Magento)
// Search template:
// \Magento\Framework\ObjectManagerInterface::$method($args)
// Finds all direct ObjectManager calls regardless of variable name
// Examples that are found:
$this->objectManager->create(\Mironsoft\Catalog\Model\Product::class);
$om->get('Magento\Catalog\Model\ProductFactory');
$objectManager->create($type, $arguments); // also with $type as a variable
// Template 2: exception is caught but never rethrown
// Search template:
// try { $statements$; } catch ($ExceptionType$ $e$) { $logger$->$logMethod$($e); }
// Finds catch blocks that only log the exception
// Template 3: echo without escapeHtml (security issue in phtml)
// Search template:
// echo $variable$;
// In scope "Frontend" -> finds all unescaped echo output
// Use case for Hyva: find all phtml files where <?= is used without escapeHtml
// Template for Structural Search and Replace:
// Search: <?= $block->$getterMethod$() ?>
// Replace: <?= $block->escapeHtml($block->$getterMethod$()) ?>
// IMPORTANT: don't apply blindly, some getters already return escaped HTML
6. Structural Search and Replace: performing mass changes safely
Structural Search and Replace (Ctrl+Shift+M) extends the search with a structurally correct replacement. The replacement template uses the same $VARIABLE$ placeholders as the search template and can output them in a new arrangement. The result is a replacement that respects the original formatting, variable names, and types, unlike simple regex replacements that blindly replace text.
A typical use case for Magento upgrades: PHP 8.4 introduces property hooks that can replace certain getter/setter patterns. With Structural Search and Replace, you can find a pattern for "private property with getter" and replace it with a property using a getter hook, structurally correct for every variable name, without having to manually adjust every hit. The same applies to migrating from old Magento APIs to new service contracts: instead of manually finding and replacing every usage of a deprecated method, you define a Structural Replace template once and apply it across all your own modules.
7. More navigation shortcuts for large projects
Go to Class (Ctrl+N) and Go to File (Ctrl+Shift+N) are the fastest ways to reach a known file or class. PhpStorm uses CamelCase matching: PRI finds ProductRepositoryInterface, CatProd finds CatalogProductRepository. The search is fuzzy and respects camel case word boundaries. With a colon after the class name (ProductRepository:42), you jump directly to a specific line.
Recent Files (Ctrl+E) and Recent Locations (Ctrl+Shift+E) are the most efficient ways back to recently edited spots. Recent Locations shows not just the file but the code snippet that was last edited, especially useful when making changes across several classes in parallel. Back/Forward Navigation (Ctrl+Alt+←/→) jumps forward and backward through navigation history, like the browser's back button, but for code. For Magento projects with deep plugin chains, this is indispensable when following a method call through several interceptor layers and then wanting to navigate back.
| Feature | Shortcut | Strength | Typical Magento use |
|---|---|---|---|
| Scoped Search | Ctrl+Shift+F | Only relevant directories | Search in your own modules without vendor |
| Find Usages | Alt+F7 | Semantic, type safe | Interface implementations and DI usage |
| Structural Search | Ctrl+Shift+S | AST-based, pattern matching | Finding ObjectManager calls, anti-patterns |
| Go to Class | Ctrl+N | CamelCase fuzzy | Quickly to interface/model/view model |
| Recent Locations | Ctrl+Shift+E | Context of recent edits | Between several parallel changes |
A practical example from everyday Magento work: you find a class name like Magento\Catalog\Plugin\Category\Collection in a stack trace. With Go to Class (Ctrl+N) and the class name, PhpStorm jumps directly to this file in vendor/, without navigating manually through the file tree. From there you can use Find Usages to check whether your own module affects this class. The entire navigation scenario takes less than 10 seconds in PhpStorm; in the terminal it would be a combination of find vendor/ -name "Collection.php" | grep Plugin and manual analysis.
Mironsoft
Magento 2 development and PhpStorm workflows for PHP teams
Want to optimize the PhpStorm setup for your Magento team?
We set up custom scopes, Structural Search templates, and navigation workflows for Magento 2 projects and train teams in the features that save time daily in large codebases.
Scope Library
Define custom scopes for every Magento development scenario and check them into the team repo
Structural Templates
Set up anti-pattern templates for Magento code reviews and automatic inspection
Team Training
Hands-on practice with navigation workflows, shortcuts, and search strategies for large PHP projects
9. Summary
Scopes, Custom Searches, and Structural Search are the three pillars of efficient navigation in large PHP projects like Magento 2. Scopes limit all search and analysis operations to relevant directories and eliminate the noise from vendor/, generated/, and other non-relevant areas. Find Usages with scope finds semantically correct usages of classes, methods, and interfaces, taking the PHP type system into account, not just as a text search. Structural Search finds code patterns that cannot be meaningfully described with regex, and Structural Replace enables mass changes that are structurally correct.
Custom scopes are versionable as .idea/scopes/*.xml files and can be shared with the team. Structural Search templates can be saved as an inspection configuration and used for automatic code review checks. The investment in the initial setup pays off daily: every search without vendor noise, every semantically correct usages analysis, and every structurally safe mass change saves measurable time in the everyday work of a Magento team.
Navigation in Large Projects: The Essentials at a Glance
Custom Scopes
Define under Settings → Scopes → +. Syntax: file:app/code/Mironsoft//* for your own modules. Stored in .idea/scopes/, versionable and shareable across the team.
Find Usages
Alt+F7 for a quick search. Alt+Shift+F7 for advanced options with scope selection. Semantically correct: finds implementations and type hints, not just strings.
Structural Search
Ctrl+Shift+S for search, Ctrl+Shift+M for Search and Replace. $VARIABLE$ as an AST placeholder. Finds code patterns independent of formatting and variable names.
Navigation Shortcuts
Ctrl+N (Go to Class), Ctrl+Shift+N (Go to File), Ctrl+E (Recent Files), Ctrl+Shift+E (Recent Locations), Ctrl+Alt+← (Back). CamelCase matching for class search.