如何基于ACF灵活内容字段实现单个Bootstrap折叠目录与多段落内容展示?
The issue with your current code is that you’re generating the entire accordion component inside the loop that iterates over each paragraph. This means every paragraph gets its own copy of the TOC, which is why you’re seeing duplicates.
To fix this, we need to separate the logic into two clear steps:
- First, collect all your paragraph data into an array
- Then, render the accordion TOC once (using the array to populate all links), followed by each paragraph section
Here’s the corrected code for your component-post_section.php file:
<?php // Step 1: Collect all paragraph data into an array $paragraphs = []; if (have_rows('paragraph')) : while (have_rows('paragraph')) : the_row(); $paragraphs[] = [ 'id' => get_sub_field('id'), 'title' => get_sub_field('title'), 'text' => get_sub_field('text') ]; endwhile; endif; // Step 2: Render content only if we have paragraphs if (!empty($paragraphs)) : ?> <!-- Bootstrap Accordion TOC (rendered once) --> <div id="accordion"> <div class="card"> <div class="card-header" id="headingToc"> <h5 class="mb-0"> <button class="btn btn-link" data-toggle="collapse" data-target="#collapseToc" aria-expanded="true" aria-controls="collapseToc"> Table of Contents </button> </h5> </div> <div id="collapseToc" class="collapse show" aria-labelledby="headingToc" data-parent="#accordion"> <div class="card-body"> <?php foreach ($paragraphs as $paragraph) : ?> <p><a href="#<?php echo esc_attr($paragraph['id']); ?>"><?php echo esc_html($paragraph['title']); ?></a></p> <?php endforeach; ?> </div> </div> </div> </div> <!-- Render each paragraph section --> <?php foreach ($paragraphs as $paragraph) : ?> <div class="container"> <div class="row" id="<?php echo esc_attr($paragraph['id']); ?>"> <h2><?php echo esc_html($paragraph['title']); ?></h2> <?php echo $paragraph['text']; ?> </div> </div> <?php endforeach; ?> <?php endif; ?>
Key improvements made:
- Collected data first: We loop through the ACF rows once to store all paragraph info in an array. This lets us reuse the data for both the TOC and the sections without re-querying.
- Fixed anchor links: Added
#to thehrefattribute so links scroll to the correct section on the same page (your original code was missing this critical piece). - Proper escaping: Used
esc_attr()for HTML attributes andesc_html()for text content to prevent potential XSS vulnerabilities. - Single TOC rendering: The accordion is now outside the paragraph loop, so it only appears once with all links included.
Do you need a separate component file?
It’s not strictly necessary for this use case, but if you plan to reuse this TOC logic across multiple templates, extracting the accordion part into a separate file (like component-toc.php) could help keep your code DRY. You would just pass the $paragraphs array to that component when including it.
内容的提问来源于stack exchange,提问作者chappers

