orklah/psalm-insane-comparison
Psalm plugin that flags “insane” string-to-number loose comparisons that change behavior in PHP 8 (RFC: Saner string to number comparisons). Helps you find risky == checks like non-empty string vs 0 before upgrading, and suggests safer typing/casts.
Install the Plugin
composer require --dev orklah/psalm-insane-comparison
vendor/bin/psalm-plugin enable orklah/psalm-insane-comparison
Run Psalm
vendor/bin/psalm
0 (or other numeric literals) that behave differently in PHP 7 vs. PHP 8.First Use Case: Pre-Migration Audit
CI/CD Pipeline
vendor/bin/psalm to your CI pipeline (e.g., GitHub Actions) to catch issues early.- name: Run Psalm Insane Comparison
run: vendor/bin/psalm --no-cache
Incremental Fixing
--report=json to generate a report and prioritize fixes:
vendor/bin/psalm --report=json > psalm-report.json
Team Collaboration
@var annotations (e.g., positive-int, numeric-string) to suppress false positives or clarify intent.Legacy Code Handling
psalm.xml:
<file-list>
<directory name="vendor" />
<directory name="legacy" exclude="true" />
</file-list>
| Issue Type | Recommended Fix | Example |
|---|---|---|
String vs. 0 |
Use strict equality (===) |
if ($str === $num) |
| String vs. numeric literal | Cast to same type | if ((int)$str == $num) |
| Dynamic numeric values | Use @var annotations |
/** @var positive-int $value */ |
| Numeric strings | Use @var numeric-string |
/** @var numeric-string $input */ |
False Positives
"123").@var numeric-string to suppress warnings for known numeric strings:
/** @var numeric-string */
$input = "123";
if ($input == 0) { // No warning
}
Performance Overhead
vendor/bin/psalm --cache-dir=~/.psalm-cache
Edge Cases in Logic
if ($userInput == 0) where $userInput might be "0" or 0).PHP 8+ Codebases
"0" == 0 is true, but "abc" == 0 is false).Suppress Specific Warnings
Disable the plugin for specific files in psalm.xml:
<plugin-classes>
<plugin-class>Orklah\PsalmInsaneComparison\Plugin</plugin-class>
<exclude-files>
<directory>tests/</directory>
</exclude-files>
</plugin-classes>
Understand the Underlying Logic
0 or other numeric literal.if ("0" == 0) { // No warning (both operands are strings/numbers)
}
Leverage Psalm’s --init
Generate a psalm.xml config file to customize behavior:
vendor/bin/psalm --init
level (e.g., level=1 for basic checks) or add custom types.Extension Points
null comparisons).Pair with Other Psalm Plugins
Combine with psalm/plugin for stricter type checking:
composer require --dev vimeo/psalm
vendor/bin/psalm-plugin enable vimeo/psalm
Automate Fixes with IDE
Use PHPStorm’s "Quick Fix" (Alt+Enter) to apply common fixes (e.g., adding @var annotations) when Psalm flags an issue.
Document Intentional Cases Add PHPDoc comments to clarify why a comparison is intentional:
// Intentionally compare string "0" with 0 (PHP 7/8 behavior is desired).
if ($flag == 0) { ... }
Monitor Progress Track fixes over time by comparing Psalm reports:
vendor/bin/psalm --report=json > before.json
# After fixes...
vendor/bin/psalm --report=json > after.json
How can I help you explore Laravel packages today?