You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现FAQ页面自动注入Schema微数据异常,求修正方案

修正PHP FAQ页面Schema微数据注入代码

问题说明

我有一个基于PHP的动态网站FAQ页面,为提升SEO效果需要自动注入Schema微数据。当前代码生成的HTML结构不符合预期,空的<p>标签被单独列出,而期望的结构是<div itemprop="acceptedAnswer">包含带有内容的<p>标签。

修正后的完整代码

<?php
$faq = "
<h3>What does the story's title mean?</h3>
<p>The beating of a heart which causes the narrator to go insane that he confesses to his crimes. So the title means he's telling (Tell) the story of the old man's beating heart (Tale Heart) that drove him insane.</p>
<h3>The narrator claims he is not mad. What evidence do we have that he is?</h3>
<p>The narrator's desire to eradicate the man's eye motivates his murder, but the narrator does not acknowledge that this act will end the man's life. By dismembering his victim, the narrator further deprives the old man of his humanity.</p>";

$dom = new DOMDocument();
$dom->loadHTML($faq);
$title = $dom->getElementsByTagName('h3');
$paras = $dom->getElementsByTagName('p');

// 处理h3标签,添加属性
foreach($title as $h){
    $h->setAttribute('class', 'faqy');
    $h->setAttribute('itemprop', 'name');
}

// 修正处理p标签的逻辑,将p包裹进acceptedAnswer容器
foreach($paras as $p){
    $parent = $p->parentNode;
    // 创建Answer容器
    $acceptedAnswer = $dom->createElement('div');
    $acceptedAnswer->setAttribute('itemscope','');
    $acceptedAnswer->setAttribute('itemprop','acceptedAnswer');
    $acceptedAnswer->setAttribute('itemtype','https://schema.org/Answer');
    
    // 给p标签设置属性
    $p->setAttribute('class', 'faqp');
    $p->setAttribute('itemprop', 'text');
    $p->setAttribute('style', 'display: none;');
    
    // 调整节点层级:p → acceptedAnswer → 原父节点
    $parent->removeChild($p);
    $acceptedAnswer->appendChild($p);
    $parent->appendChild($acceptedAnswer);
}

$html=$dom->saveHTML();

function wrapcallback( $buffer ){
    $delimiter='#';
    $tags=array('h1','h2','h3','h4','h5','h6');
    $query=implode('|', explode( $delimiter, sprintf( '//%s', implode( sprintf( '%s//', $delimiter ), $tags ) ) ) );
    $keepers=array();
    $parents=array();
    libxml_use_internal_errors( true );
    $dom=new DOMDocument;
    $dom->validateOnParse=false;
    $dom->recover=true;
    $dom->strictErrorChecking=false;
    $dom->preserveWhiteSpace=true;
    $dom->loadHTML( $buffer );
    libxml_clear_errors();
    $xp=new DOMXPath( $dom );
    $col=$xp->query( $query );
    if( $col->length > 0 ){
        foreach( $col as $node ){
            $parents[]=$node->parentNode;
            $nodes=array( $node );
            while( $node = $node->nextSibling ){
                if( in_array( $node->nodeName, $tags ) )break;
                if( $node->nodeType==XML_ELEMENT_NODE  )$nodes[]=$node;
            }
            $keepers[]=$nodes;
        }
    }
    foreach( $keepers as $index => $obj ){
        $mainEntity=$dom->createElement('li');
        $mainEntity->setAttribute('class', 'faqq');
        $mainEntity->setAttribute('itemscope', '');
        $mainEntity->setAttribute('itemprop', 'mainEntity');
        $mainEntity->setAttribute('itemtype', 'https://schema.org/Question');
        $parents[ $index ]->appendChild( $mainEntity );
        foreach( $obj as $child )$mainEntity->appendChild( $child );
    }
    echo $dom->saveHTML();
};
$wraptext=$html;
?>
<div class="dfaq cfix" itemscope itemtype="https://schema.org/FAQPage">
<h2 class="faqt">FAQs</h2>
<ul class="faqs">
<?php wrapcallback($wraptext); ?>
</ul>
</div><!-- /.dfaq -->

关键修改点

  1. 调整节点层级关系:原代码将<div itemprop="acceptedAnswer">放入<p>标签内,导致<p>成为空外壳。修正后将<p>标签整体移入<div itemprop="acceptedAnswer">中,符合期望的嵌套结构。
  2. 优化节点操作顺序:先保存<p>的父节点,调整节点位置后再添加回原父节点,确保DOM结构正确。

修正后输出的HTML

<div class="dfaq cfix" itemscope="" itemtype="https://schema.org/FAQPage">
    <h2 class="faqt">FAQs</h2>
    <ul class="faqs">
        <li class="faqq" itemscope="" itemprop="mainEntity" itemtype="https://schema.org/Question">
            <h3 class="faqy" itemprop="name">What does the story's title mean?</h3>
            
            <div itemscope="" itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
                <p class="faqp" itemprop="text" style="display: none;">The beating of a heart which causes the narrator to go insane that he confesses to his crimes. So the title means he's telling (Tell) the story of the old man's beating heart (Tale Heart) that drove him insane.</p>
            </div>
        </li>
        <li class="faqq" itemscope="" itemprop="mainEntity" itemtype="https://schema.org/Question">
            <h3 class="faqy" itemprop="name">The narrator claims he is not mad. What evidence do we have that he is?</h3>
            
            <div itemscope="" itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
                <p class="faqp" itemprop="text" style="display: none;">The narrator's desire to eradicate the man's eye motivates his murder, but the narrator does not acknowledge that this act will end the man's life. By dismembering his victim, the narrator further deprives the old man of his humanity.</p>
            </div>
        </li>
    </ul>
</div>

内容的提问来源于stack exchange,提问作者Dayyal Dg.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:20:31