使用 PHP 函数打印 HTML 会产生被浏览器错误解释的输出


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

也许我只是太累了,或者错过了一些真正基本的东西,但我越来越沮丧。

我有包含数据的表格。我编写了php函数,它从数据库中获取数据并构建html表。

我的问题是,表中的第一行缺少最后一个表格单元格中的元素。

PHP函数:

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;
}

问题是浏览器忽略了第一行中的表单元素。隐藏的输入和按钮保留在原位,但没有其父窗体。所以浏览器中的输出如下所示:

<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>

此外,如果我转储此函数的返回值,例如:var_dump(htmlspecialchars(printTable($stmt)));它显示第一个形式在那里,但在浏览器中突然错过。难道是神秘消失的魔法?

以防万一我的建议不清楚,我把你的代码拿出来,伪造了你的数据

$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;

嗯,这种行为似乎与嵌套表单以及浏览器如何处理它们有关。嵌套表单根据规范无效。

请参阅在另一个 html 表单中包含 hrml 表单是否有效?或者 Chrome 正在吃掉我的第一个内部表单,为什么?

浏览器中的输出肯定不像你显示的那样,因为你的PHP代码没有输出任何缩进。

因此,您可能向我们展示的是浏览器处理的 DOM,它可能代表也可能不代表发送到浏览器的实际代码。

浏览器

收到的代码可能以某种方式无效,您看到的是浏览器试图纠正错误。

如果没有看到页面的其余部分,我无法确定无效代码的实际外观,但我的猜测是,在输出表之前,您已经打开了一个<form>元素。你不能嵌套<form> s,所以浏览器看到表中的第一个,并对自己说"哦,这是无效的"。所以它试图修复它,结果是内部形式被删除。

正如我所说,这主要是猜测,如果不看到页面的其余部分,我就无法更准确,但我想说这可能是一个相当接近的猜测。

无论如何,您可以通过 W3C 的 HTML 验证器运行代码来自己找出问题的真正所在。您可以在此处找到它和其他代码验证工具:https://www.w3.org/developers/tools

使用它的最简单方法是在浏览器中打开页面,并使用"查看源代码"选项查看实际的 HTML 代码(即不是开发工具中显示的 DOM 代码),然后将其复制+粘贴到验证器中的表单中。

它应该很快告诉你代码的问题是什么。

祝你好运。

根据 HTML 规范,表格单元格内不能有表单,但可以在表单内有表格。Catharsis的答案是正确的,但是我很困惑为什么您的第一个打开和关闭表单标签消失了,一定有代码的其他部分导致这种情况发生。无论如何,我会采用表格之外的形式,为了便于阅读,将所有连接代码替换为 HEREDOC 代码。

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;
}