1

I am currently working on a project involving multiple languages including HTML/JS/PHP.

In one of my PHP functions, I discovered an unexpected behavior.

I broke it down to simpler functions so it would be clearer :

<?php

function generateInput($inputID, $oninputFunction)
{
    echo '<input id="' . $inputID . '" oninput="' . $oninputFunction . '">';
}

function generateDIV(){
    $ID = "someId";
    echo '<div>';
    generateInput($ID, 'someFunction('. $ID .')');
    echo '</div>';
}
?>
<script>
  function someFunction(selectID) {
    console.log(selectID);
  }
</script>
<!DOCTYPE html>
<html>
<body>
    <?php generateDIV() ?>
</body>
</html>

As you can tell, the expected console output when something is typed in the input is "someId". However, for some reason, the output is the HTML element which is:

<input id="someId" oninput="someFunction(someId)">

If anyone has an explanation to this behavior, please let me know.

GDev
  • 13
  • 1
  • 2
  • It's a string, passed from PHP to the JS function. – GDev Jun 15 '23 at 18:04
  • 2
    **generateInput($ID, 'someFunction('. $ID .')');** is including the string of **$ID**. However, since you aren't wrapping it in double quotes, the generated code is passing it as a variable and not as a string. Since you are actually using double quotes in your input, try this **generateInput($ID, "someFunction('". $ID ."')");** That will wrap the output in single quotes so it is passed as a string. – imvain2 Jun 15 '23 at 18:04
  • Need to quote it in that case. `generateInput($ID, "someFunction('{$ID}')");` (The `{}` is PHP to expand the variable) – user3783243 Jun 15 '23 at 18:04
  • Although you don't even need to pass it. Instead just pass the variable **this** **** and you can reference the element's id in the **function someFunction(e){ console.log(e.id) }** – imvain2 Jun 15 '23 at 18:07
  • That's very interesting. So when passing it as a variable the JS function automatically assigns it with the corresponding element that has the same id? – GDev Jun 15 '23 at 18:08
  • That is what `this` achieves in the function call – ADyson Jun 16 '23 at 07:59

1 Answers1

2

As you can tell, the expected console output when something is typed in the input is "someId".

No it isn't. Look closely at the HTML being generated by this:

<input id="someId" oninput="someFunction(someId)">

Specifically the JavaScript function call:

someFunction(someId)

In this case someId is not a string. It's a variable. Coincidentally this variable name matches the id of the element, so it's actually a property on the window object which references that element.

(Note: This behavior is happening by coincidence in this case, but it shouldn't be relied upon as a standard. More information can be found starting here.)

So the code is outputting the element.

Remove the id from the element and observe an error:

Uncaught ReferenceError: someId is not defined

If you want it to be a string literal then it needs quotes around it:

generateInput($ID, "someFunction('". $ID ."')");

As an aside... Quoting problems like this are very common when trying to mix multiple languages all on the same line of code. PHP, HTML, and JS all munged together like this is a recipe for quoting problems. It's best to keep them as separated as you can so you can more clearly observe the syntax of each language.

David
  • 208,112
  • 36
  • 198
  • 279
  • Much appreciated. I have never encountered such scenario or used this functionality so it seemed like an expected behavior. – GDev Jun 15 '23 at 18:12
  • Can you add more details about "property on the window object"? Is `console.log` running something like `document.getelementbytid()`, or JS maps all non-strings that map to ids? – user3783243 Jun 15 '23 at 18:14
  • 1
    @user3783243: Looks like that result may also be by coincidence, there's a larger rabbit hole of details starting [here](https://stackoverflow.com/q/15767961/328193). – David Jun 15 '23 at 18:17