Navigation in Large Projects: Scopes, Custom Searches and Structural Search in PhpStorm
AI generated
IDE
{ }
PhpStorm · Scopes · Structural Search · Navigation · Magento
Navigation in Large Projects
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.

17 min read Scopes · Structural Search · Find Usages · Magento · Navigation PhpStorm 2024.x · 2025.x · Magento 2.4.x

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.

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.

10. FAQ: Navigation in Large Projects with PhpStorm

1What are PhpStorm scopes?
Named file/directory groups for search, Find Usages, and inspections. In Magento: your own modules without vendor noise. Define under Settings → Scopes → +.
2Exclude vendor/ from search?
Custom scope with !file:vendor//* or mark vendor/ as Excluded under Project Structure. In Find in Files set the scope dropdown to "Own Modules".
3Text search vs. Structural Search?
Text search = character strings. Structural Search = AST analysis. Finds patterns independent of formatting and variable names. Ctrl+Shift+S opens the tool.
4Finding ObjectManager calls?
Structural Search: $var$->create($type$) with a type constraint for ObjectManagerInterface. Finds all calls regardless of variable name.
5Share custom scopes with the team?
Yes. Check .idea/scopes/*.xml into the Git repo. All team members have the same scopes available immediately after pulling.
6CamelCase matching in Go to Class?
Uppercase letters in the input are interpreted as word starts. PRI -> ProductRepositoryInterface. CatProd -> CatalogProductRepository. Very fast navigation.
7Find Usages vs. text search?
Find Usages analyzes the type system: finds implementations, overrides, and type hints even with import aliases. Text search finds only exact character strings.
8Structural Replace for Magento upgrades?
Yes. For deprecated API migrations and PHP 8.x modernizations. Structurally correct replacements. Check the result in the diff viewer before applying.
9Navigating plugin chains in Magento?
Ctrl+click -> implementation. Ctrl+Alt+← back. Find Usages shows all plugins (before/around/after). Recent Locations for quick jumping back.
10Structural templates as inspections?
Yes. Save Template in the Structural Search dialog. It then appears under Settings → Inspections → General → Structural Search as an automatic inspection.