简体   繁体   中英

Printing HTML with PHP function produces output which is wrongly interpreted by browser

maybe I am just too tired or missing something really fundamental, but I am growing frustrated.

I have table which contains data. I wrote php function which takes data from database and construct html table.

My problem is, that first row in table misses element in last table cell.

PHP function:

function printTable($stmt) {
    $result = '<table>';
    while ($data = $stmt -> fetch()) {
         $result .= '<tr>'
                     . '<td><span>' . $data['id'] . '</span></td>'
                     . '<td><span>' . $data['name'] . '</span></td>'
                     . '<td>'
                        . '<form method="post" action="">'
                           . '<input type="hidden" name="id" value="' . $data['id'] . '">
                           . '<button type="submit" name="edit">Edit</button>'
                        . '</form>'
                     . '</td>'
                 . '</tr>';
    }
    $result .= '</table>';
    return $result;
}

The problem is that browser ignores form element in first row. Hidden input and button stay in place but without its parent form. So the output in browser looks like this:

<table>
   <tr>
      <td><span>1</span></td>
      <td><span>Foo</span></td>
      <td>
         <input type="hidden" name="id" value="1">
         <button type="submit" name="edit">Edit</button>
      </td>  
   </tr>
   <tr>
      <td><span>2</span></td>
      <td><span>Bar</span></td>
      <td>
         <form method="post" action="">
            <input type="hidden" name="id" value="2">
            <button type="submit" name="edit">Edit</button>
         </form>
      </td>  
   </tr>
   <tr>
      <td><span>3</span></td>
      <td><span>Foo Bar</span></td>
      <td>
         <form method="post" action="">
            <input type="hidden" name="id" value="3">
            <button type="submit" name="edit">Edit</button>
         </form>
      </td>  
   </tr>
</table>

Furthermore, if I dump return value of this function, for example: var_dump(htmlspecialchars(printTable($stmt))); it shows that first form is there, but in browser suddenly misses. Is it mysteriously dissapearing form magic?

Well, it seems this behaviour is related to nested forms and how browsers handle them. Nested forms are invalid by specification.

See Is it valid to have a hrml form inside another html form? or Chrome is eating my first inner form why?

The output in the browser certainly doesn't look the way you've shown it, because your PHP code doen't output any indentation.

So what you're probably showing us is the browser's processed DOM, which may or may not represent the actual code that is being sent to the browser.

The chances are that the code the browser is receiving is invalid in some way or another, and what you're seeing is the browser's attempt to correct the mistakes.

Without seeing the rest of the page, I can't be certain what the invalid code actually looks like, but my guess is that you've got a <form> element already open prior to the table being output. You can't have nested <form> s, so the browser sees the first one inside the table and says to itself "oh, this is invalid". So it tries to fix it, and the result is that the inner form gets removed.

As I say, that's mostly speculation, and I can't be any more accurate without seeing the rest of the page, but I'd say it's likely a fairly close guess.

In any case, you can find out for yourself what the problem really is by running the code through the W3C's HTML validator. You can find it, and other code validation tools here: https://www.w3.org/developers/tools

The easiest way to use it is to open the page in your browser, and use the "view source" option to see the actual HTML code (ie not the DOM code shown in the dev tools), and then copy+paste that into the form in the validator.

It should tell you pretty quickly what the problems are with your code.

Best of luck.

Just incase my suggestions were unclear I pulled your code out and faked your data

$allData = [
    ['id' => 1, 'name' => 'Foo'],
    ['id' => 2, 'name' => 'Bar'],
    ['id' => 3, 'name' => 'Baz']
];
$result = '<form method="post" action=""><table>';
foreach ($allData as $data) {
    $result .= '<tr>'
        . '<td><span>' . $data['id'] . '</span></td>'
        . '<td><span>' . $data['name'] . '</span></td>'
        . '<td>'
            . '<button type="submit" name="edit" value="' . $data['id'] . '">Edit</button>'
        . '</td>'
    . '</tr>';
}
$result .= '</table></form>';
echo $result;

According to HTML specs, you cannot have a form inside of a table cell, but you can have a table inside of a form. Catharsis' answer is correct, but I am baffled as to why your first opening and closing form tag have disappeared, there must be other parts of your code that are causing this to happen. Anyhow, I would take the form outside the table and for ease of readability replace all the concatenation code with HEREDOC code.

function printTable($stmt) {
    $result = '<form method="post">';
    $result .= '<table>';
    while ($data = $stmt -> fetch()) {
         $result .= <<<HTML
             <tr>
                <td>{$data['id']}</td>
                <td>{$data['name']}</td>
                <td><button type="submit" name="edit" value="{$data['id']}">Edit</button></td>

             </tr>
HTML;
    }
    $result .= '</table>';
    $result .= '</form>';
    return $result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM