【问题标题】:HTML markup manipulation in PHPPHP 中的 HTML 标记操作
【发布时间】:2012-07-28 21:57:33
【问题描述】:

使用 PHP DOM - html 操作。这是输出 HTML 标记的非常有效的方法(至少可以防止代码中的逻辑和标记混乱)。

但是,要生成 50 行 html 标记,必须用 PHP 编写大约 200 行 :( .

示例代码:

...

$signup_form = $document->createElement('form');
$signup_form->setAttribute('id', 'signup_form');
$signup_form->setAttribute('action', 'registration/signup.php');
$signup_form->setAttribute('method', 'post');
$su_fname_label = $document->createElement('label');
$su_fname_label->setAttribute('for', 'fname');
$su_fname_label_content = $document->createTextNode('Name');
$su_fname_label->appendChild($su_fname_label_content);
$su_fname_textbox = $document->createElement('input');
$su_fname_textbox->setAttribute('name', 'fname');
$su_fname_textbox->setAttribute('class', 'valid');
$su_fname_textbox->setAttribute('placeholder', 'Please enter your name');
$su_fname_textbox->setAttribute('type', 'text');

...

如您所见,它只有 1 个表单元素。想象一下,如果 HTML 表单中有 5 个元素,那么 php 代码将是巨大的。我想知道,有没有办法缩小前任。通过一次设置多个属性?有什么建议吗?

【问题讨论】:

  • 在 HTML 代码中嵌入 PHP 的 sn-ps 有什么问题?我认为之后它会更具可读性。
  • 哇,好有趣!
  • 除了编写自己的辅助函数或用于创建单个元素的专用类之外,没有。 DOM 是一个冗长的 API。
  • 确实是个缺点。但是,我倾向于不以这种方式“制作”HTML:我只是加载一个预制的 HTML 模板,然后用 PHP 填写一些细节。我其实更喜欢不符合 DOM 的 DOMDocumentFragment ;)

标签: php html dom


【解决方案1】:

为什么不直接输出 HTML 并启用输出缓冲。然后,您可以使用 tidy 扩展过滤掉输出,并确保您的输出 HTML 是有效的,同时仍然像编写纯 HTML 一样快。

尽管如此,正如@Gordon 建议的那样:

tidy 几乎不适合以编程方式创作 (x)html。它更像是一个后处理器。

【讨论】:

  • tidy 必须启用 iirc。默认情况下启用 dom。此外,tidy 几乎不适合以编程方式创作 (x)html。它更像是一个后处理器。
  • 是的,这很好。不过,我发现在启用了 tidy 的环境中,使用 tidy 更容易。是的,它是一个后处理器。我也建议像使用它一样使用它。
  • 大声笑,我的背上没有皮肤。我刚刚贡献了我的答案,似乎有人不喜欢它:)
【解决方案2】:

您使用 DOM 生成 html 输出的原因是什么?没有办法让 DOM 简洁

通常你只是使用 PHP 来做模板。像这样创建一个单独的文件:

<?php // template.php
echo '<!DOCTYPE html>',"\n";
?>
<html>
    <head>
    <meta charset="utf-8">
    <title><?=htmlspecialchars($title, ENT_NOQUOTES, 'utf-8')?></title>
    </head>
    <body>
       <form id="signup_form" action="registration/signup.php" method="post">
           <label for="fname">Name</label>
           <input id="fname" name="fname" class="valid" placeholder="Please enter your name" type="text">
       </form>
    </body>
</html>

然后使用模板函数:

function render($__filename, $__data) {
    extract($__data, EXTR_SKIP);
    ob_start();
    include $__filename;
    return ob_get_clean();
}

从您的代码中呈现您的模板,如下所示:

do_something();
$templatedata = array('title'=>'The Title');
$html = render('template.php', $templatedata);

如果您想要节点感知的东西(这是确保格式正确和正确转义的好主意!),您可以使用 XSLT 或第三方模板引擎,如 PHPTAL

【讨论】:

    【解决方案3】:

    根据您对速度的需求以及如果您能够使用缓存等,可以使用诸如 phpQuery 之类的库。

    它是一种类似于jQuery 到 PHP 的“端口”,具有与jQuery 相同的多功能性和简单性。但是,根据我的经验,生成代码的速度并没有我想的那么快(我没有,但是,进行了任何彻底的测试,这只是一种感觉)。

    您作为示例给出的代码可以用phpQuery未经测试)按照这些方式表示:

    $form = pq ('<form />')
              ->attr (array (
                        'id' => 'signup_form',
                        'action' => 'registration/signup.php',
                        'method' => 'POST',
                      ));
    $label = pq ('<label />')
              ->html ('Name')
              ->attr ('for', 'fname')
              ->appendTo ($form);
    $text = pq ('<input />')
              ->attr (array (
                        'name' => 'fname',
                        'data-placeholder' => 'Please enter your name',
                        'type' => 'text',
                      ))
              ->addClass ('valid')
              ->appendTo ($label);
    

    我用我喜欢的格式编写了它,它比你提供的代码稍微多一些;但如果您喜欢更紧凑的编码,它可以很容易地减少到 5-10 行左右并保持可读性。无论如何,我发现它更容易阅读,而且您不必编写太多DOM 代码即可生成大量 HTML 代码。

    另外,鉴于phpQuery 使用与jQuery 相同的包装概念,一个未包装的节点,例如上面代码中的$form,是一个常规的DOMNode,除非包装在pq() 中。这为您提供了很大的灵活性,既可以使用phpQuery 的便利例程,也可以使用PHP DOM 的更“基本”功能。

    【讨论】:

      【解决方案4】:

      我曾经做你正在做的事情,直到我意识到它不是很可读。您必须分析代码以确定正在构建的标记。也更难维护。正如您所说,向表单添加单个字段需要相当多的代码,而进行更改需要挖掘所有代码。我同意将您的 PHP 逻辑与您的标记分开;但是,根据您要执行的操作,有更好的方法可以让您的代码保持干净。

      在不涉及第三方解决方案的情况下,您可以:

      1. Load markup from a separate file into a DOM object 进行进一步操作。

      2. 通过将 PHP 嵌入到您的标记中,使用 PHP 作为模板引擎。正如上校 Shrapnel 雄辩地解释的那样:“[E] 嵌入式 PHP 让您可以在站点范围内将业务逻辑与表示逻辑分开,支持任何大小和结构的模板……”。

      3. 使用heredoc syntax 将标记分配给变量。虽然不是最佳选择,但它比纯粹基于 DOM 的方法更易于阅读。

      $signup_form = <<<EndHTMLForm
      <form id="signup_form" action="registration/signup.php" method="post">
          <label for="fname">Name</label>
          <input name="fname" class="valid" placeholder="Please enter your name" type="text">
      </form>
      EndHTMLForm;
      

      我在这里的目的不是让您远离第三方解决方案,而是在普通 PHP 中说明替代方法。 DOM 很冗长。它当然有很好的优势,但从头开始创建标记并不是其中之一。

      【讨论】:

      • 你对 (2) 和 (3) 的描述感到困惑。嵌入式 PHP 允许您在站点范围内将业务逻辑与表示逻辑分离,支持任何大小和结构的模板,而 heredoc 确实适用于“小剂量”,根本不支持逻辑或分离。并不是说您正在丢失使用heredoc 突出显示的代码。
      • @Col:在 (2) 中,我指的是整个 HTML 模板中的“小剂量”PHP——而不是两者的大部分,我推断 OP 试图避免这种情况。我想我不清楚这一点,所以我会尝试解决它。然而,我绝对同意,任何使用heredoc 都应该以“小剂量”进行。即使没有代码突出显示的好处,我的示例也肯定比 OP 的基于 DOM 的方法更清晰。这些仅作为可能的替代方案提供,因为 OP 从未指定意图。
      猜你喜欢
      • 2021-05-01
      • 2011-09-12
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多