You could consider wp_unique_id()
:
This is a PHP implementation of Underscore’s uniqueId method. A static variable contains an integer that is incremented with each call. This number is returned with the optional prefix. As such the returned value is not universally unique, but it is unique across the life of the PHP process.
Even if you have multiple instances of the block, wp_unique_id()
should generate a unique-enough ID for you. You can then use this ID as a prefix for the IDs in the loop to keep them all unique from each other:
$unique_id = wp_unique_id( 'faq-' );
?>
<?php if( $questions ) : ?>
<div class="offset-xl-1 col-xl-8">
<div class="<?php echo $class.'__questions'; ?> accordion accordion-flush" id="faq-<?php echo $block['id'] ;?>">
<?php foreach( $questions as $index => $question ) :
…
?>
<div class="accordion-item">
<h3 … id="<?php echo esc_attr( $unique_id ); ?>-heading-<?php echo $index; ?>">
<button …
data-bs-target="#<?php echo esc_attr( $unique_id ); ?>-answer-<?php echo $index; ?>"
aria-controls="<?php echo esc_attr( $unique_id ); ?>-answer-<?php echo $index; ?>"
>
<?php echo $question['question']; ?>
</button>
</h3>
<div
…
id="<?php echo esc_attr( $unique_id ); ?>-answer-<?php echo $index; ?>"
aria-labelledby="<?php echo esc_attr( $unique_id ); ?>-answer-<?php echo $index; ?>"
>