1

I was just debuging some code, and found that

$id = null;
$field = $id === null ? true : false;
$field = $id ? true : false;

Both should set $field to TRUE value. However for some reason it does not work as intended. First one returns true, other one returns false.

Edit1: I accidentaly mistook things when writing question. It should be why its different.

Edit2: I ask my question since this behaviour is different on 2 different servers. 2nd Example is expected to return True, but somehow it does not return true on one of my servers.

Edit3: Here is the real code. Its class/ObjectModel.php in Prestashop 1.5

/* Copy the field, or the default language field if it's both required and empty */
        if ((!$this->id_lang AND isset($this->{$field}[$id_language]) AND !empty($this->{$field}[$id_language])) 
        OR ($this->id_lang AND isset($this->$field) AND !empty($this->$field)))
            $fields[$id_language][$field] = $this->id_lang === null ? pSQL($this->$field) : pSQL($this->{$field}[$id_language]);
        elseif (in_array($field, $this->fieldsRequiredLang))
            $fields[$id_language][$field] = $this->id_lang === null ? pSQL($this->$field) : pSQL($this->{$field}[Configuration::get('PS_LANG_DEFAULT')]);
        else
            $fields[$id_language][$field] = '';

The expected behaveior (that is true on most servers) is if $this->id_lang is set to null then $this->$field should be used instead of $this->$field[$id_language]. However, on my server set on CentOS machine this behaviour differ and when value is set to null it gets $this->$field[$id_language] as value.

6
  • 1
    This is correct behavior. What's the problem? Commented Apr 10, 2013 at 21:56
  • I'm sorry for confusion, corrected question. Commented Apr 11, 2013 at 12:28
  • Why do you expect $field = $id ? true : false; to be true? Commented Apr 11, 2013 at 13:43
  • 1
    $field = $id === null is enough :) Commented Apr 11, 2013 at 13:44
  • As answer i chose sated. Seems to be distribution/build depended interpretation. Since on some it is considered true and on some as false. Commented Apr 11, 2013 at 18:50

2 Answers 2

4

The statement (you have unfortunately edited) is the same as:

$id = null;
if($id === null) {
    $field = true;
} else {
    $field = false;
}

Are you still expecting false? :)

The statement in your question is using the so called ternary operator. To understand your example you should read this documentation (Section: Ternary Operator)

The ternary operator is a shorthand for if statements that allows to shorten code, especially conditional assignments. However, the fact that you ask this question is a good example for it's disadvantage: It is less readable ;)

Sign up to request clarification or add additional context in comments.

3 Comments

I understand what it is. Thank you. I more meant why does this script work differently on other servers. On one server its good, and on my CentOS it's behaviour is different than expected.,
You mean on CentOS you get FALSE?
Yep, updated question with real code and more detailed explanation.
3

Regarding Edit 3, if you are experiencing different results on different distributions with the same code and data set then my guess is that the CentOS binaries you are using have been modified by their developers and a bug has been introduced, perhaps in operator precedence.

As a general rule, I personally prefer to enclose each clause or group of clauses in parentheses in order to reduce the chances of something like this happening, thus I suggest giving the following a try:

if ((!$this->id_lang && isset($this->{$field}[$id_language]) && !empty($this->{$field}[$id_language])) || ($this->id_lang && isset($this->$field) && !empty($this->$field))) {
    $fields[$id_language][$field] = (($this->id_lang === null) ? pSQL($this->$field) : pSQL($this->{$field}[$id_language]));
} else if (in_array($field, $this->fieldsRequiredLang)) {
    $fields[$id_language][$field] = (($this->id_lang === null) ? pSQL($this->$field) : pSQL($this->{$field}[Configuration::get('PS_LANG_DEFAULT')]));
} else {
    $fields[$id_language][$field] = '';
}

This way, you force the parser to evaluate the various clauses and operators in the order you define rather than the order the parser thinks they should be processed.

Original Answer

$field is being set to true because the === operator compares two values and returns true if they contain both the same value and the same type.

By setting $id to null, you are essentially running this:

$field = (null === null);

You could expand your current code to clarify the logic as follows:

if ($id === null) {
    $field = true;
} else {
    $field = false;
}

Or, you could just simply run:

$field = ($id === null);

3 Comments

I wrote it like that to simplify code :) It's not true or false in real code.
Alas, I think you over-simplified it. :) I've updated my answer regarding the new information. I suspect your problem is operator precedence, so you should try adding parentheses around the clauses.
Maybe ;) Anway, I had to change it to $this->id_lang === null to repair that "flaw". Somehow i was more curious why it was happening. Since it's not my code I had problem with. Anyway, as I said, made it more bugproof :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.