Static vs Dynamic Analysis
What is Static Analysis?
Static analysis examines code without executing it. It reads source files and reports potential issues based on rules and type information.
What is Dynamic Analysis?
Dynamic analysis examines code while it runs. Unit tests, integration tests, and profiling are forms of dynamic analysis.
Comparison
| Aspect | Static Analysis | Dynamic Analysis |
|---|---|---|
| Runs | Without execution | During execution |
| Speed | Seconds to minutes | Minutes to hours |
| Coverage | All code paths | Only tested paths |
| Findings | Type errors, code smells, bugs | Runtime errors, behavior bugs |
| False positives | Some | Rare |
| Examples | PHPStan, Psalm, PHPMD | PHPUnit, integration tests |
Why Static Analysis Matters
// This passes dynamic analysis (tests work)
function processOrder(array $data): Order
{
$order = new Order();
$order->setTotal($data['total']);
return $order;
}
// But static analysis catches the bug BEFORE running:
// PHPStan: Property Order::$total does not exist
// (You forgot to define the property)
// Or this:
function getPrice(): float
{
return 'free'; // PHPStan: Method must return float, string returned
}
Static analysis catches type errors, undefined properties, missing return types, and other issues before you ever run the code.
PHPStan: Type Checking
What is PHPStan?
PHPStan analyzes PHP code for type errors without running it. It catches bugs that type checks would catch if PHP had strict typing everywhere.
Basic Usage
# Install
composer require --dev phpstan/phpstan
# Run
vendor/bin/phpstan analyse src/ --level=6
# With configuration (phpstan.neon)
vendor/bin/phpstan analyse
phpstan.neon Configuration
parameters:
level: 6 # 0-9 (9 is strictest)
paths:
- app/code/Vendor/Module/Api/
- app/code/Vendor/Module/Model/
ignoreErrors:
- '#Property .* is never assigned#'
excludePaths:
- app/code/Vendor/Module/Test/
# Magento-specific rules
stubs:
- etc/phpstan/stubs/*.stub
Level Guide
| Level | Checks |
|---|---|
| 0 | Basic checks (unknown classes, functions) |
| 1 | Unknown methods on $this, argument types |
| 2 | Unknown magic methods/properties |
| 3 | Return types, property types |
| 4 | Basic dead code, always true/false checks |
| 5 | Checking types of arguments passed to methods |
| 6 | Basic dead code checking, always true/false |
| 7 | Nullable types, undefined variables |
| 8 | Union type handling |
| 9 | Strict mode, all checks |
Magento-Specific PHPStan
# phpstan.neon for Magento
includes:
- vendor/magento/magento2-phpstan/extension.neon
parameters:
level: 6
paths:
- app/code/Vendor/
ignoreErrors:
- '#Call to an undefined method Magento\\Framework\\App\\Config::getValue#'
The Magento extension adds type stubs for Magento's dynamic methods.
Psalm and PHPMD
Psalm: Gradual Typing
Psalm is similar to PHPStan but focuses on gradual type enforcement:
# Install
composer require --dev vimeo/psalm
# Run
vendor/bin/psalm --config=psalm.xml
<!-- psalm.xml -->
<psalm
errorLevel="4"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="app/code/Vendor/Module"/>
<ignoreFiles>
<directory name="vendor"/>
</ignoreFiles>
</projectFiles>
</psalm>
Psalm's unique feature: type assertions and suppressed issues:
/** @psalm-suppress InvalidReturnType */
public function risky(): mixed
{
// Psalm won't report this return type issue
}
PHPMD: Mess Detector
PHPMD detects code smells and bad practices:
# Install
composer require --dev phpmd/phpmd
# Run
vendor/bin/phpmd app/code/Vendor/Module/ text rulesets/codesize.xml,rulesets/unusedcode.xml
PHPMD Rulesets:
| Ruleset | Detects |
|---|---|
| codesize | Long methods, too many parameters |
| unusedcode | Unused variables, unused private methods |
| cleanCode | Duplicate code, overly complex expressions |
| naming | Short variables, long class names |
| design | Too many fields, deep inheritance |
<!-- phpmd.xml -->
<ruleset name="Magento Rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_1_0_0.xsd">
<description>Custom rules for Magento</description>
<rule ref="rulesets/codesize.xml">
<properties>
<property name="maximum-method-complexity" value="15"/>
<property name="maximum-method-length" value="50"/>
<property name="maximum-parameters" value="5"/>
</properties>
</rule>
<rule ref="rulesets/unusedcode.xml"/>
</ruleset>
All Three Together
# In CI pipeline
vendor/bin/phpstan analyse src/ --level=6
vendor/bin/psalm --config=psalm.xml
vendor/bin/phpmd src/ text phpmd.xml
Quiz
1. What is the key difference between static and dynamic analysis?
2. PHPStan level 6 checks for:
3. PHPMD detects:
Flashcards
Question
Static vs Dynamic analysis?
Click to reveal answer
Answer
Static: without execution (PHPStan). Dynamic: during execution (PHPUnit).
Question
PHPStan levels?
Click to reveal answer
Answer
0-9. Higher = stricter. 6 is recommended starting point.
Question
What does PHPMD detect?
Click to reveal answer
Answer
Code smells: long methods, unused code, duplicate code, deep inheritance
Question
Why use static analysis?
Click to reveal answer
Answer
Catch bugs at write-time before running code, faster feedback loop
Revision Notes
Key Takeaways
- 1. Static analysis: examines code without executing it (type errors, code smells)
- 2. Dynamic analysis: examines code during execution (tests, profiling)
- 3. PHPStan: type checking, levels 0-9, level 6 is recommended
- 4. Psalm: gradual typing with type assertions and suppressions
- 5. PHPMD: code smells (long methods, unused code, duplicate code)
- 6. All three should run in CI pipeline for quality gates
Interview Tips
- • Explain why static analysis complements (not replaces) unit testing
- • Recommend PHPStan level 6 as starting point for Magento
- • Discuss trade-offs: false positives vs catching real bugs
Cheat Sheet
Static Analysis: without execution
Dynamic Analysis: during execution
PHPStan: composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src/ --level=6
Psalm: composer require --dev vimeo/psalm
vendor/bin/psalm --config=psalm.xml
PHPMD: composer require --dev phpmd/phpmd
vendor/bin/phpmd src/ text phpmd.xml
All three → CI pipeline quality gates