Skip to content
Advertisement

Add “first” and “last” classes to strings containing one or more tags in PHP

I have two strings I’m outputting to a page

# string 1
<p>paragraph1</p>

# string 2
<p>paragraph1</p>
<p>paragraph2</p>
<p>paragraph3</p>

What I’d like to do is turn them into this

# string 1
<p class="first last">paragraph1</p>

# string 2
<p class="first">paragraph1</p>
<p>paragraph2</p>
<p class="last">paragraph3</p>

I’m essentially trying to replicate the css equivalent of first-child and last-child, but I have to physically add them to the tags as I cannot use CSS. The strings are part of a MPDF document and nth-child is not supported on <p> tags.

I can iterate through the strings easy enough to split the <p> tags into an array

$dom = new DOMDocument();
$question_paragraphs = array();
$dom->loadHTML($q['quiz_question']);
foreach($dom->getElementsByTagName('p') as $node)
{
 $question_paragraphs[] = $dom->saveHTML($node);
}

But once I have that array I’m struggling to find a nice clean way to append and prepend the first and last class to either end of the array. I end up with lots of ugly loops and array splicing that feels very messy.

I’m wondering if anyone has any slick ways to do this? Thank you 🙂

Edit Note: The two strings are outputting within a while(array) loop as they’re stored in a database.

Advertisement

Answer

You can index the node list with the item() method, so you can add the attribute to the first and last elements in the list.

$dom = new DOMDocument();
$question_paragraphs = array();
$dom->loadHTML($q['quiz_question']);
$par = $dom->getElementsByTagName('p');
if ($par->length == 1) {
    $par->item(0)->setAttribute("class", "first last");
} elseif ($par->length > 1) {
    $par->item(0)->setAttribute("class", "first");
    $par->item($par->length - 1)->setAttribute("class", "last");
}
    
foreach($par as $node)
{
    $question_paragraphs[] = $dom->saveHTML($node);
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement