Due to the weakly typed nature of PHP comparing two values might sometimes give unexpected results.

Example:

  if ($this->getOperation() == 'delete') {
    // Delete everything.
  }

If for some reason $this->getOperation() would return TRUE then a boolean comparison will be performed, and everything will be unexpectedly deleted.

A better practice is to use the strict comparison operator for strings:

  if ($this->getOperation() === 'delete') {
    // Delete everything.
  }

I propose to add this to the coding standards, so we can detect and avoid potential bugs like these.

Comments

pfrenssen created an issue. See original summary.

dawehner’s picture

I like the idea, but I'm wondering whether we should first go with the smaller step, which would be to strongly encourage people to use the === operator.

sardara’s picture

I really like this proposition. Using strict comparison will also avoid type juggling, so it's a bit faster too.

slootjes’s picture

+1 to prevent type juggling which can cause bugs. For sensitive (ie. usernames, tokens) use hash_equals() instead as it prevents timing attacks.

bobbygryzynger’s picture

+1 I would like to see this added to the standard as well. It produces clearer reading code and cuts out a slew of potentially difficult to debug edge-cases. The relevant sniff to add would be Squiz.Operators.ComparisonOperatorUsage.

jhodgdon’s picture

This seems like a good idea, but unless either the left-hand or right-hand side of the operator is a literal string, it would be difficult to enforce with a Coder sniffing rule. I guess that is often the case, but not always. I think we normally don't adopt new coding standards that are difficult or impossible to enforce with Coder rules.

dawehner’s picture

It feels even by documenting we could make a sort of positive impact, simply by rising the awareness of the problem.

effulgentsia’s picture

but unless either the left-hand or right-hand side of the operator is a literal string, it would be difficult to enforce with a Coder sniffing rule

Any reason not to broaden the scope of this proposal to always require the strict operator? I.e., remove "for comparing strings" from the issue title?

pfrenssen’s picture

@effulgentsia this is an interesting idea. After all if you are comparing values you know the type in advance.

There are certainly use cases for the non-strict comparison operator: functions might return different types depending on the result of their action. For example a function might return NULL or FALSE instead of an actual value if an error occurred, or if there are no results. In these cases you can use == as a shortcut. Returning different types (eg FALSE on failure) is a very bad practice but unfortunately PHP code is rife with this.

I think that in these cases it is arguably better to rewrite these using strict comparisons. This will be more verbose but it will also more clearly express what is being done and that the type casting is intentional.

slootjes’s picture

@pfrenssen In those cases you could also consider using empty() instead of a weak typed comparison which will pass on the same kind of values (FALSE/NULL/0,etc).

andypost’s picture

GuyPaddock’s picture

Do bear in mind that strict equality against numeric values can lead to unexpected results if the two sides differ in precision or one side has been juggled into being a string, so be careful with numbers.

slootjes’s picture

That's exactly the reason why strict typing is the way to go; to be as strict as possible and don't have weird side effects.

andypost’s picture