Jump to content
Larry Ullman's Book Forums

Recommended Posts

I'm having a little trouble with preg_replace. The aim is to take a shortcode and replace it with some html code. The shortcode is of the format [image file=name.ext]. Each instance of the shortcode in some content should be replaced with

<img src="path/to/images/name.ext" alt="name image" />

What is actually happening is the shortcode is being replaced with

[<img src="path/to/images/name.ext" alt="name image" />]

Printing out the relevant array shows no brackets so not sure where to look to solve this.

 

Also can preg_match be used to find more than one occurrence of a pattern? The php manual indicates yes, but my testing was only coming up with one occurrence so I've resorted to using preg_match_all.

 

Here's my test file with some content if you want to test it out. As ever please suggest any improvements. Thanks.

define ('BASE_URL', '/path/to/root/');

$content = '<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames 
ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit 
amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. 
Mauris placerat eleifend leo.</p>
[image file=file1.jpg]<h3>Ipsem</h3>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames 
ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit 
amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. 
Mauris placerat eleifend leo.</p>
[image file=file2.jpg]<h3>Lorem</h3>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames 
ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit 
amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. 
</span>ipsem lorem blah di blah.</span>';


$html_content=replace_shortcodes($content);
echo( $html_content);

function replace_shortcodes($content){
	$html_array=array();
	$shortcodes = get_all_shortcodes($content);
	foreach ($shortcodes as $shortcode) {
			$filename = get_sc_attr($shortcode);
			$alt = substr($filename, 0, strpos($filename,'.'));
			$html_array[]='<img src="' . BASE_URL . 'images/' . $filename . '" alt="'. $alt. ' image" />';	
	}
	$html_content= preg_replace($shortcodes, $html_array, $content);
	return $html_content;
}

function get_all_shortcodes($content){
	$sc_regex = '/\[\s*image\s+file\s*=\s*[\w-]+\.[\w-]+\s*\]/';
	preg_match_all($sc_regex, $content, $matches);
	return $matches[0];
}

function get_sc_attr($shortcode) {
	$length = (strpos($shortcode,']') - strpos($shortcode,'=')); 
	$filename = trim(substr($shortcode, strpos($shortcode,'=') +1,$length-1));
	return $filename;
}

Link to comment
Share on other sites

 

Also can preg_match be used to find more than one occurrence of a pattern? The php manual indicates yes, but my testing was only coming up with one occurrence so I've resorted to using preg_match_all.
Where in the PHP manual does it say this? I'm pretty sure that preg_match stops after the first match (although you can set an offset to affect from where in the subject string the first match is found). As you stated, you have to use preg_match_all to do a global (i.e., multimatch) search.
 
Now, with that said, in your case, you can probably do the whole search and replace in one line of code using the preg_replace function and backreferences. The following is some code that demonstrates what I would do to solve your problem:
<?php
  
  define('BASE_URL', '/path/to/root/');
  
  $str = 'The following are two really cool images:
 
[image file=big_kahuna.jpg]
 
[image file=solar_flare.png]
 
And here\'s one more inline image ([image file=webgl.gif]) just because.';
  
  echo "<b>Original text with shortcodes:</b><br><pre>$str</pre><br><br>";
  
  echo "<b>New text with HTML img tags:</b><br><pre>" . htmlentities(preg_replace('/\[\s*image\s+file\s*=\s*([\w-]+)\.([\w-]+)\s*\]/', '<img src="' . BASE_URL . 'images/$1.$2" />', $str)) . '</pre>';
 
The $1 and $2 in the second argument of the preg_replace function are the backreferences. They refer to the [\w-]+ parts of the regex within the two sets of parentheses. (If you'll recall from your other recent topic on regexes, I mentioned that one of the two uses of parentheses in regexes is to create backreferences.)
 
As a final comment, note that I had to use both pre tags and the htmlentities function to make the before and after code viewable on the screen. For an actual application, neither would be required.
Please let me know if you have any other questions.
Thanks.
  • Upvote 2
Link to comment
Share on other sites

Thanks HartleySan - that's a very nice solution to what I was trying to do. I appreciate you taking the time to explain it as I understand the preg functions better now.

 

I misunderstood the manual and was thinking that the 3rd argument was an array collecting all the matches, but its for collecting full and partial matches.

Link to comment
Share on other sites

 Share

×
×
  • Create New...