0

My code is as follows. In my understanding from diverse websites and the php documentation, empty() is a language construct that checks whether the key exists, just like isset() (only that it also does a loose 'false'-comparison in case the Variable or Key exists...

37     $origin = 
38                !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] :
39                !empty($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] :
40                !empty($_SERVER['ORIGIN']) ? $_SERVER['ORIGIN'] :
41                "Unknown Origin";

Error:

Undefined index: ORIGIN in somePHPFile.php:40

Update: I fixed it by wrapping the else-parts in parentheses. When i have discovered the exact problem (associativity or else...) i will update this answer again.

        $origin = 
            (!empty($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] :
            ((!empty($_SERVER['HTTP_ORIGIN'])) ? $_SERVER['HTTP_ORIGIN'] :
            (!empty($_SERVER['ORIGIN']) ? $_SERVER['ORIGIN'] :
            "Unbekannte Herkunft"));
Toastgeraet
  • 371
  • 1
  • 11
  • 2
    Using nested ternary operations like that should be illegal. It's hard to read and debug. – M. Eriksson Jan 30 '18 at 14:48
  • 1
    Add some parenthesis to your ternaries so it's processed properly. When you don't use parenthesis, things get weird. – aynber Jan 30 '18 at 14:49
  • 1
    Interesting. What php version is this? Please provide a minimal but working code example for us to test this. Thanks. – arkascha Jan 30 '18 at 14:52
  • I will try to provide a working minimal example, as well as the php version by thursday - if the real cause (might be the associativity) is not found, earlier. – Toastgeraet Jan 30 '18 at 15:07
  • 1
    Just a heads up. Right now, that might look good to you, but when you go back in a few weeks/months or even years, and need to read/update that code (or worse, someone else needs to do it), you're gonna regret it. Lines in a file are cheap. You should try to make the code more readable. Plus, if you did that, this would probably not have been an issue to start with. – M. Eriksson Jan 30 '18 at 15:10

1 Answers1

4

The reason for this error is associativity of ternary operator in PHP - it's left-to-right, while in most other languages it's right-to-left. That's why nested ternaries are very cumbersome both to read and to write in PHP. )

In this particular case it means, in particular, the following: if HTTP_REFERER header is set, the value of $_SERVER['HTTP_ORIGIN'] will be checked as well.

To solve this, you need to either wrap the conditions in parenthesis, use plain old if-elseif-else combination, or (makes most sense to me) do some abstraction over your code:

$origin = 'Unknown Origin';
$headersToCheck = ['HTTP_REFERER', 'HTTP_ORIGIN', 'ORIGIN'];
foreach ($headersToCheck as $header) {
  if (!empty($_SERVER[$header]) {
    $origin = $_SERVER[$header];
    break;
  }
}
raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 1
    It works, because no check succeeds. [This version](https://3v4l.org/DC9L1) shows what happens in the OP code. – raina77ow Jan 30 '18 at 14:58
  • Ah. Of course. It's so obvious when you show it _that_ way... :-) – M. Eriksson Jan 30 '18 at 15:00
  • I wrapped the else-parts in parentheses, not the conditions - see my update. But you put me on the right track. Thank you. Also thanks for the alternative method you provided. – Toastgeraet Jan 30 '18 at 15:03
  • @Toastgeraet You need to wrap each condition in the order you want processed e.g. `(false === true ? true : (false === false ? true : false))` See: https://3v4l.org/pKP1C for an example. – Will B. Jan 30 '18 at 15:44