.append link inside a <H4> while in a php loop

Hi all

i have a php foreach loop that outputs html to the page with every loop.

i have a variable that stores the html inside it. this variable gets echo out on each loop.

what i want to do is update this variable (before it gets eco out) so that it has its old heading removed and update the contents of the heading to have an <a href> inside it.

The <a href> is also available as a variable with in the loop.

example: this is the output of the variable with <xmp> tags surrounding it

	<div class="lesson-desc-inner top-cat">
                  <div class="w-row">
                    <div class="w-col w-col-4 center">
                      <img class="pad-image" src="/sites/the_english_notebook/themes/theme_by_chris_sowerby/images/book%20icon.png" width="92" alt="52c6d55a9c7b16355f0002bd_book%20icon.png">
                    </div>
                    <div class="w-col w-col-8">
                      <div class="lesson-select-text-area">
                        <h4 class="reusable-heading">Module name will update...</h4>
                        <div class="text-contain">
                          <p>In the 2nd grade you learned to add and subtract 2-digit numbers. Now we take things further by adding and subtracting three-digit numbers. This is good practice for 4th grade where you&#039;ll be expected to add or subtract pretty much any whole number!</p>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

Open in new window


so i need to update this part:

<h4 class="reusable-heading">Module name will update...</h4>

Open in new window



to look like this:


<h4 class="reusable-heading">
<a href="/sites/the_english_notebook/index.php/pick-your-key-stage/key-stage-1/verbs-2/" target="_self">verbs 3</a>
</h4>

Open in new window


the <a href> can be  output within my loop like this:

<a href='<?php  echo $url ?>' target='<?php  echo $target ?>'><?php  echo $title ?></a>

Open in new window



so i just need to replace the old heading with the link but am not sure how i can break apart my html from its variable and add my link variables inside it at the correct places.

Thanks for helping.
LVL 1
helpchrisplzAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gr8gonzoConsultantCommented:
What does your foreach code look like?
helpchrisplzAuthor Commented:
like this:

<?php  foreach ($pages as $page):
	$title = $th->entities($page->getCollectionName());
	$url = $nh->getLinkToCollection($page);
	$target = ($page->getCollectionPointerExternalLink() != '' && $page->openCollectionPointerExternalLinkInNewWindow()) ? '_blank' : $page->getAttribute('nav_target');
	$target = empty($target) ? '_self' : $target;
?>

<?php $teaser = $plth->getPageTeaser($page, 'Description of this lesson', $teaserBlockCount, $teaserTruncateChars);		?>
	
	<a href="<?php  echo $url; ?>" target="<?php  echo $target; ?>"><?php  echo $title; ?></a>


	<?php  echo $teaser; // html code output here ?>
	
<?php  endforeach; ?>

Open in new window

gr8gonzoConsultantCommented:
Okay, so I assume $teaser is the block containing the <h4> tag. Probably the simplest way to do this is to use a regex:

<?php  foreach ($pages as $page):
	$title = $th->entities($page->getCollectionName());
	$url = $nh->getLinkToCollection($page);
	$target = ($page->getCollectionPointerExternalLink() != '' && $page->openCollectionPointerExternalLinkInNewWindow()) ? '_blank' : $page->getAttribute('nav_target');
	$target = empty($target) ? '_self' : $target;
?>

<?php 
$teaser = $plth->getPageTeaser($page, 'Description of this lesson', $teaserBlockCount, $teaserTruncateChars);		?>

// Build link HTML
$link = "<a href=\"{$url}\" target=\"{$target}\">{$title}</a>";

// Replace the inside contents of the <h4> with the link.
$teaser = preg_replace("@(<h4 class=\"reusable-heading\">)([^<]+)(</h4>)@","\\1{$link}\\3",$teaser);
	
	<a href="<?php  echo $url; ?>" target="<?php  echo $target; ?>"><?php  echo $title; ?></a>


	<?php  echo $teaser; // html code output here ?>
	
<?php  endforeach; ?>

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
helpchrisplzAuthor Commented:
yes that did it :) thanks

looks like i really need to learn how preg_replace works.

This baffles me:

 ("@(<h4 class=\"reusable-heading\">)([^<]+)(</h4>)@","\\1{$link}\\3",$teaser)
gr8gonzoConsultantCommented:
It starts with the syntax:

RESULT = preg_replace( FIND REGULAR EXPRESSION,  REPLACE WITH,  ORIGINAL CONTENT );

So:

$teaser = preg_replace("/e/","a", $teaser);

...would change every "e" with an "a".

Regular expressions need delimiters to indicate when they should start and stop, which is why there are / around the "e". The delimiter can be just about any non-alpha-numeric character, so you could use @ or %, for example:

$teaser = preg_replace("/e/","a", $teaser);
$teaser = preg_replace("%e%","a", $teaser);
$teaser = preg_replace("@e@","a", $teaser);

All three lines do the exact same thing. The / is simply the most common version. People use different delimiters to avoid having to escape characters in their regular express that also happen to be the delimiter. For example, if you wanted to change all instances of "/h4>" to the word "blah", you might think of doing this:

$teaser = preg_replace("/</h4>/","blah",$teaser);

...however that / right before h4 is also the regular expression delimiter, so this would throw an error because the regular expression engine doesn't know whether you're trying to end the regular expression or if you're looking for the / character. So you can either escape the / with a backslash \ or you can use a different delimiter:

$teaser = preg_replace("/<\/h4>/","blah",$teaser);
or
$teaser = preg_replace("@</h4>@","blah",$teaser);

When I'm working with HTML, I usually use the @ delimiter so I don't have to keep escaping every forward slash character.

Now, when you use parentheses, you're "capturing" that content temporarily and you can use it in your output. For example:

$teaser = "The quick brown fox.";
$teaser = preg_replace("@(quick) (brown) (fox)@", "\\3, which is \\1 and \\2", $teaser);

The first word "quick" is capture number 1, "brown" is capture number 2, and "fox" is capture number 3. In the second part of preg_replace, you see \\1, which means "the value of capture 1", \\2 which means "the value of capture 2", and \\3, which means "the value of capture 3". So the above would result in $teaser being "The fox, which is quick and brown.";

Finally, the last "magic" piece of the regex was this: [^<]+. Put simply, it means "every character that ISN'T the < character. So if I had this:

$teaser = "The quick brown fox.";
$teaser = preg_replace("@(quick) ([^n]+n) (fox)@", "\\3, which is \\1 and \\2", $teaser);

... I would still get the same result as before. The regular expression in the middle says "any character except for n". The regular expression goes character-by-character. It starts with "b", which is not "n", so it gets added. Then "r", which is not "n", so it also gets added, and so on. It finally gets to the point where "brow" is captured, and then the regular expression sees an "n", so it stops. However, since I want the "n", too, I have it as part of my capture, so the second capture group is really two expressions: [^n]+ and then the letter "n". Together, you get "brown". This isn't the most useful regular expression with that phrase, but in HTML, it's a pretty simple way sometimes to get the inner content of a tag, because it's matching everything EXCEPT for the beginning of the next tag, which starts with <. So:

$teaser = "Hello <sometag>World</sometag>!";
$teaser = preg_replace("@<sometag>([^<]+)</sometag>@", "\\1", $teaser);

...would result in "Hello World!"

So what I did with your content is capture the whole <h4> starting tag as capture #1, all of the content leading up to the </h4> ending tag as capture #2, and then the </h4> ending tag itself as capture #3. Then I replaced it all with capture #1 (the starting H4 tag), followed by the link HTML, followed by capture #3 (the ending H4 tag).

I didn't need to capture the content of your H4 tag as capture #2, but I wasn't sure if you were going to use it, so I figure it would be easier to write the more "complete" regex up front and if you wanted to reuse the content somehow (like as the link text), you could just throw \\2 in there somewhere.

Hopefully that all makes sense. Once you know regular expressions well, this type of stuff isn't very difficult. It looks FAR more complicated than you think it is. I also use a free tool called The Regex Coach all the time to help me see what my regular expressions are doing as I write them.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.