generated, vendor, Tests & Templates
Magento 2 poses particular challenges for PhpStorm: thousands of generated classes, a huge vendor/ tree, PHPUnit tests across multiple layers, and phtml templates with mixed PHP/HTML syntax. The right configuration makes the difference between a sluggish IDE and a precise development environment.
Table of Contents
- 1. The Particularities of Magento in the IDE Context
- 2. Directories: Setting Sources, Tests and Excluded Correctly
- 3. generated/ Code: Index or Exclude?
- 4. Navigating vendor/ Efficiently
- 5. Setting Up PHPUnit for Magento Tests
- 6. Running Integration and API Tests in PhpStorm
- 7. phtml Templates: Syntax Highlighting and Navigation
- 8. Navigating Magento XML Configurations in PhpStorm
- 9. Configuration Comparison: Standard vs. Magento-Optimized
- 10. Summary
- 11. FAQ
1. The Particularities of Magento in the IDE Context
A fresh Magento 2 project has tens of thousands of PHP files right after installation. The vendor/ directory alone contains the libraries for Magento Core, Composer dependencies, and third-party modules. On top of that come the generated classes in generated/: proxies, interceptors, and factories that Magento creates on the first page load or during setup:di:compile. By default, PhpStorm tries to index all of these files, which improves code completion on the one hand but can noticeably slow the IDE down on the other.
The challenge lies in finding the right balance: excluding too much means missing code completion and incorrect error markers. Excluding too little means a sluggish IDE that takes minutes to reindex after every change. The Directories feature in PhpStorm (module settings) allows precise control over which directories count as source roots, which are indexed only as libraries, and which are excluded entirely.
Magento tests operate across three layers: unit tests in dev/tests/unit/, integration tests in dev/tests/integration/, and API functional tests in dev/tests/api-functional/. Each layer has its own phpunit.xml.dist, its own bootstrap files, and different requirements for the running environment. PhpStorm can run all three layers, but only if the run configurations point to the correct bootstrap file in each case.
2. Directories: Setting Sources, Tests and Excluded Correctly
The most important configuration for a Magento project in PhpStorm is found under Right-click on the project → Module Settings → Sources. Here you define the correct role for each directory type. The src/ directory (or the Magento root) is the source root. The directories dev/tests/unit/, dev/tests/integration/, and every Test/ subdirectory in modules are marked as Test Source Root. This lets PhpStorm separate production code from test code and offers test-specific inspections and navigation inside test files.
Mark as Excluded any directories that PhpStorm should not index at all: var/, pub/static/, pub/media/, dev/tests/api-functional/ (if no API testing is planned), and temporary directories. These exclusions reduce the memory footprint of the PhpStorm index and significantly speed up search, because irrelevant files are never scanned. The node_modules/ directory in Hyva themes should be excluded as well.
<?php
/**
* Example: Test bootstrap configuration for Magento Unit Tests.
* PhpStorm Run Configuration points to this file via:
* Settings → PHP → Test Frameworks → PHPUnit → Path to script
*
* File: dev/tests/unit/framework/bootstrap.php (Magento default)
* Custom modules bootstrap at: app/code/Vendor/Module/Test/Unit/
*/
declare(strict_types=1);
// Magento unit test bootstrap, do not modify, set via PhpStorm config
define('BP', dirname(__DIR__, 4));
define('TESTS_TEMP_DIR', BP . '/dev/tests/unit/tmp');
// Register Magento autoloader for unit tests
require_once BP . '/vendor/autoload.php';
// Initialize test environment
\Magento\Framework\TestFramework\Unit\Helper\Bootstrap::setObjectManagerFactory(
new \Magento\TestFramework\ObjectManager\Factory()
);
3. generated/ Code: Index or Exclude?
The generated/ directory contains automatically produced classes that Magento generates for each concrete implementation. Proxies enable lazy loading, interceptors implement the plugin system, and factories create new instances via the ObjectManager. These classes are not meant for manual editing, but they are essential for understanding the Magento DI system and for correct code completion.
The recommendation: mark generated/ as a Sources Root, but not as a regular source directory, rather as an additional library. This lets PhpStorm find the generated classes for code completion and navigation without marking them as actual project files. Concretely: Module Settings → Sources → mark the generated/ directory as Sources Root. PhpStorm can then jump directly from a SomeClass\Proxy reference to the generated file without reporting an error.
Important: generated/ needs to be reindexed after every bin/magento setup:di:compile run. PhpStorm detects file changes automatically and triggers reindexing on its own, but on very large projects it can help to trigger reindexing manually via File → Invalidate Caches / Restart if code completion appears incomplete after a compile run.
4. Navigating vendor/ Efficiently
The vendor/ directory of a Magento project contains Magento Core and all dependencies, several gigabytes of PHP code in total. PhpStorm indexes this directory fully as a library, which enables full code completion for all Magento Core classes. The Navigate to Class feature (Ctrl+N) finds any core class instantly, even if it sits deep in the vendor hierarchy.
Especially important for daily work: Go to Declaration (Ctrl+B) jumps from an interface to its implementation, even if that implementation lives in vendor/ and is resolved via the DI configuration. The Magento PhpStorm plugin extends this navigation with DI XML resolution: from a prefer configuration in di.xml you jump directly to the implementation class. This bidirectional navigation, from code to configuration and back, is one of the biggest advantages the Magento plugin offers over a plain PHP editor.
5. Setting Up PHPUnit for Magento Tests
Magento unit tests run with PHPUnit and a dedicated bootstrap file. In PhpStorm, you configure PHPUnit under Settings → PHP → Test Frameworks → + → PHPUnit by Remote Interpreter (once a Docker interpreter is set up). As Path to phpunit.phar or script, provide the path to the phpunit binary inside the Docker container: /var/www/html/vendor/bin/phpunit. As the default configuration file, choose /var/www/html/dev/tests/unit/phpunit.xml.dist.
After this configuration, a green play icon appears in the gutter next to every test method. Clicking it runs that single test without starting the entire test suite. This is valuable for Magento development because the full unit test suite can take several minutes to run. Individual tests for a newly written method complete in seconds and provide instant feedback right inside the editor.
<?php
/**
* Example Magento Unit Test using PhpStorm test runner.
* Run this with the green gutter icon or via Run → Run 'Test'.
* PhpStorm shows pass/fail directly in the test window.
*/
declare(strict_types=1);
namespace Mironsoft\Module\Test\Unit\Model;
use Mironsoft\Module\Model\PriceCalculator;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Magento\Framework\App\Config\ScopeConfigInterface;
/**
* Unit test for PriceCalculator model.
*/
class PriceCalculatorTest extends TestCase
{
private PriceCalculator $calculator;
private MockObject&ScopeConfigInterface $scopeConfigMock;
protected function setUp(): void
{
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
$this->calculator = new PriceCalculator($this->scopeConfigMock);
}
/**
* @dataProvider priceProvider
*/
public function testCalculateDiscountedPrice(float $base, float $discount, float $expected): void
{
$this->scopeConfigMock->method('getValue')->willReturn((string)$discount);
$result = $this->calculator->calculateDiscountedPrice($base);
self::assertEqualsWithDelta($expected, $result, 0.001);
}
public static function priceProvider(): array
{
return [
'ten percent off 100' => [100.0, 10.0, 90.0],
'twenty percent off 50' => [50.0, 20.0, 40.0],
'zero discount' => [75.0, 0.0, 75.0],
];
}
}
6. Running Integration and API Tests in PhpStorm
Magento integration tests require a running database and a separate Magento installation in test mode. The install-config-mysql.php file in dev/tests/integration/etc/ contains the database connection for the test database. In the Mark Shust Docker environment, you set up a second database for integration tests and enter it in the configuration file. PhpStorm then runs the tests via a separate run configuration that points to dev/tests/integration/phpunit.xml.dist.
Integration tests in Magento carry @magentoDbIsolation enabled and @magentoDataFixture annotations. PhpStorm recognizes these PHPDoc annotations and offers autocompletion for fixture paths. Running integration tests takes considerably longer than unit tests because they involve full DI resolution and database operations. For development, it is best to run integration tests in the CI pipeline and only start the affected test classes directly in PhpStorm locally.
7. phtml Templates: Syntax Highlighting and Navigation
Magento templates have the .phtml extension and contain PHP code embedded directly in HTML. PhpStorm recognizes .phtml files as PHP files by default and offers full syntax highlighting and code completion even inside embedded PHP tags. For Hyva themes using Alpine.js directives, it is also worthwhile installing the Alpine.js PhpStorm plugin, which understands x-data, x-on, and other Alpine directives within the HTML.
One practical setting: under Settings → Editor → File Types, check that *.phtml is mapped to the PHP file type. If phtml files are recognized as an unknown type, add the extension manually. For Tailwind CSS classes in phtml templates, the Tailwind CSS plugin provides autocompletion, provided the Tailwind configuration file sits in the project root or theme directory and has been detected once.
8. Navigating Magento XML Configurations in PhpStorm
Magento 2 uses XML configuration for nearly every aspect of the system: di.xml for dependency injection, events.xml for observers, routes.xml for routing, and layout.xml plus default.xml for the layout system. The Magento PhpStorm plugin enriches PhpStorm with understanding of these XML schemas. In a di.xml file, you can jump straight from a type name="SomeClass" attribute to the PHP class. In a plugin configuration, you jump to the plugin class and from there to the affected method of the original class.
PhpStorm also offers a Structure View (Alt+7) for XML files, which lays out the hierarchy of XML elements clearly. For large di.xml files with hundreds of entries, this lets you navigate quickly to the plugin or preference you need without scrolling manually through the document. Find Usages (Alt+F7) on a class name inside an XML file shows every other XML configuration referencing that class, an important feature when refactoring classes that are configured in multiple places.
9. Configuration Comparison: Standard vs. Magento-Optimized
A direct comparison between a standard PhpStorm configuration and a Magento-optimized configuration shows the concrete differences in day-to-day workflows.
| Configuration Area | Standard PhpStorm | Magento-Optimized | Impact |
|---|---|---|---|
| generated/ | Unknown, errors in DI | Marked as Sources Root | Proxy/interceptor navigation works |
| var/ pub/static/ | Indexed (slow) | Marked as Excluded | Search 3 to 5x faster |
| PHPUnit | Not configured | Docker interpreter + phpunit.xml.dist | Run tests directly from the gutter |
| phtml files | PHP highlighting present | + Tailwind + Alpine.js plugin | Full frontend support |
| XML navigation | XML syntax only | Magento plugin: jump to PHP classes | DI/plugin/observer instantly navigable |
The sum of these configuration steps makes a substantial difference in quality. An unoptimized PhpStorm configuration for Magento is not just slower, it also shows false errors (missing generated classes), fails to find types (because var/ is searched instead of generated/), and does not allow direct test execution. The investment of one to two hours in configuration pays off daily.
Mironsoft
Magento 2 development, testing, and IDE configuration
Want to build a professional Magento test infrastructure?
We set up PhpStorm, PHPUnit, and the Magento test infrastructure for your project: unit tests, integration tests, and CI pipeline integration for maintainable Magento code.
PHPUnit setup
Configure PhpStorm and Docker for all three Magento test layers
Writing tests
Write unit and integration tests for existing Magento modules
IDE optimization
Directories, plugins, and settings for maximum PhpStorm performance
10. Summary
A Magento-specific PhpStorm configuration consists of several steps building on one another. Directories management separates source code, test code, and excluded directories, which speeds up search and prevents false errors. The generated/ folder as Sources Root ensures that proxy and interceptor classes are available for navigation and code completion. PHPUnit with a Docker interpreter makes it possible to run individual tests directly from the editor, without switching context to the terminal.
The phtml template configuration with Tailwind and Alpine.js plugins closes the gap between backend PHP development and frontend template work in Hyva themes. The Magento PhpStorm plugin makes XML configurations navigable and connects DI configuration, plugin definitions, and observer registrations with the corresponding PHP classes. Together, these configurations turn PhpStorm from a generic PHP editor into a Magento-specific development platform.
Magento PhpStorm Settings: The Essentials at a Glance
Directories
var/, pub/static/, pub/media/ as Excluded. generated/ as Sources Root. dev/tests/ as Test Source Root. Saves indexing time and prevents incorrect search results.
PHPUnit
Settings → PHP → Test Frameworks → PHPUnit by Remote Interpreter. Path: /var/www/html/vendor/bin/phpunit. Config: dev/tests/unit/phpunit.xml.dist.
phtml templates
File Types: map *.phtml to the PHP type. Tailwind CSS plugin for class completion. Alpine.js plugin for x-data and x-on directives in Hyva templates.
Magento plugin
Magento PhpStorm plugin from the JetBrains Marketplace. Navigation from di.xml to PHP classes, plugin-to-method navigation, and observer configuration directly from XML.