Skip to content

TypeUnsafeComparison ​

warning on by default quick-fix

Group: Type compatibility · PhpStorm name: TypeUnsafeComparisonInspection

Loose equality (==, !=, <>) silently juggles types ('abc' == 0 was true before PHP 8, '1e1' == '10' is true). This rule asks for strict comparison, offers a one-click switch when comparing against a non-numeric string literal, and flags objects compared to strings that have no __toString().

Example ​

php
<?php
interface Labelled            { public function __toString(); }
interface Plain               {}
abstract class BaseTag        { abstract public function __toString(); }
class Tag extends BaseTag     { function __toString(): string { return "t"; } }
class ChildTag extends Tag    {}
class Invoice                 {}
class Stamp extends DateTimeImmutable {}

function compare(Labelled $l, Plain $p, ChildTag $t, Invoice $i, ?Invoice $n, $v, $w) {
    return [
        $l == 'x',
        $p != 'x',
        'name' == $t,
        '0' == $i,
        ($n) <> '',
        $n == 'paid',

        $v == 'ready',
        "done" != $v,
        $v<>'1x3',

        $v == '1e3',
        $v == "{$w}",

        $v == '12',
        $v != '-.5',
        $v == "",
        $v <> $w,
        $v == ('text'),

        new Stamp() == new DateTime(),
        date_create('now') != $w,
        $v === 'ready',
    ];
}
php
<?php
interface Labelled            { public function __toString(); }
interface Plain               {}
abstract class BaseTag        { abstract public function __toString(); }
class Tag extends BaseTag     { function __toString(): string { return "t"; } }
class ChildTag extends Tag    {}
class Invoice                 {}
class Stamp extends DateTimeImmutable {}

function compare(Labelled $l, Plain $p, ChildTag $t, Invoice $i, ?Invoice $n, $v, $w) {
    return [
        $l == 'x',
        $p != 'x',
        'name' == $t,
        '0' == $i,
        ($n) <> '',
        $n == 'paid',

        $v === 'ready',
        "done" !== $v,
        $v!=='1x3',

        $v == '1e3',
        $v == "{$w}",

        $v == '12',
        $v != '-.5',
        $v == "",
        $v <> $w,
        $v == ('text'),

        new Stamp() == new DateTime(),
        date_create('now') != $w,
        $v === 'ready',
    ];
}

Reported:

  • line 13: \Plain has no __toString(), so it cannot be compared to a string.
  • line 15: \Invoice has no __toString(), so it cannot be compared to a string.
  • line 17: \Invoice has no __toString(), so it cannot be compared to a string.
  • line 19: Use '===' here; the string is not numeric, so strict comparison is safe.
  • line 20: Use '!==' here; the string is not numeric, so strict comparison is safe.
  • line 21: Use '!==' here; the string is not numeric, so strict comparison is safe.
  • line 23: Prefer '===' to avoid implicit type juggling.
  • line 24: Prefer '===' to avoid implicit type juggling.
  • line 26: Prefer '===' to avoid implicit type juggling.
  • line 27: Prefer '!==' to avoid implicit type juggling.
  • line 28: Prefer '===' to avoid implicit type juggling.
  • line 29: Prefer '!==' to avoid implicit type juggling.
  • line 30: Prefer '===' to avoid implicit type juggling.

Configure ​

In custos.json:

json
{
  "rules": {
    "TypeUnsafeComparison": {
      "enabled": false
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file), either of:

php
// @custos-ignore TypeUnsafeComparison

/**
 * @noinspection TypeUnsafeComparisonInspection
 */

Released under the MIT License. Rule catalogue modelled on Php Inspections (EA Extended); independent clean-room implementation.