preg_replace problem

jlknauff

New member
Aug 25, 2008
237
1
0
Code:
function addLinks(){
 preg_replace("text", "<a href=\"[URL]http://www.example.com/\">text</a[/URL]>", $spun, 1);
}
Gives me the error message "Delimiter must not be alphanumeric or backslash" - what am I doing wrong here? If it makes a difference, this function goes through a chunk of text and replaces certain words with a hyperlinked version of itself.
 


Ok, perhaps I'm doing something else wrong then...I don't get the error message now that I've made that change, but I'm getting no output. When I do it outside of a function, it works fine. Do you see any mistakes here?

Code:
function addLinks(){
 preg_replace("/text/", "/<a href=\"[URL="http://www.example.com//%22%3Etext%3C/a%3E/"]http://www.example.com/\">text</a>/[/URL]", $spun, 1);
}
 $spun = spinContent($spin_this);
 $post = addLinks($spun);
 
 echo $post

Also - is preg_replace the best aproach, or would str_replace be better? There will be several words to be hyperlinked if that makes a difference.
 
Well, you aren't taking the string as an argument in the function declaration.
You need to return the preg_replace modified string:


Code:
function addLinks($spun){
 return preg_replace("/text/", "/<a href=\"http://www.example.com/\">text</a>/", $spun, 1);
}
$spun = spinContent($spin_this);
$post = addLinks($spun);
 
echo $post;


And yes, str_replace would be a better option, as well as if you're doing multiple replaces you can make an array and loop through each, like so:

Code:
function addLinks( $spun ) {
 $links = array( 'text' => 'link', 'moretext' => 'anotherlink' );
 foreach( $links as $findMe => $link ) {
  $spun = str_replace( $findMe, "<a href=\"$link\">$findMe</a>", $spun );
 }
 return $spun;
}
 
Ok, thanks! Now I'm trying to solve two small details...

1. I want it to search using a space before and after the word so that it won't link if the text is found inside another word. I've tried adding a space to the code in the applicable spots, but it doesn't seem to work.

2. I only want to link the first (or better yet, a random instance) of the word within the text, so for example, "text" would only be linked onece, "here" would only be linked once, and if possible, it would occur at a random location rather than always the first instance. I've tried adding a counter to the code to facilitate that, but it seems impossible to put it into a place within the foreach statement that would have an effect.

Here is what I've tried:

Code:
function addLinks( $spun ) {
 $links = array( " text " => "[url=http://example.com/]Example Web Page[/url]", " here " => "[URL]http://otherexample.com/[/URL]" );
  foreach( $links as $findMe => $link ) {
   $counter = 1; 
   while ($counter>0) { 
    if ($counter==1) { 
     $spun = str_replace( $findMe, " <a href=\"$link\">$findMe</a> ", $spun );
     $counter = $counter - 1; 
    } 
   }  
  }
  return $spun;
}
 
There's probably a much simpler way to do this, lol, but anyway this'll do what you want:

Code:
<?php

class ALObj {
	public $replacements = array( 'text' => 'link',
												   'moretext' => 'anotherlink' );
	private $replaceIndex, $replacePointer;

	function addLinks( $string ) {
		foreach( $this->replacements as $findMe => $link ) {
			preg_match_all( '/\s'.preg_quote( $findMe ).'\s/', $string, $matches );
			if ( !isset( $matches[0][0] ) ) {
				continue;
			}
			if ( ( $count = count( $matches[0] ) ) == 1 ) {
				$this->replaceIndex = 0;
			} else {
				$this->replaceIndex = rand( 0, ( $count - 1 ) );
			}
			$this->replacePointer = 0;
			$string = preg_replace_callback( '/\s'.preg_quote( $findMe ).'\s/', array( $this, 'checkReplacement' ), $string );
		}
		return $string;
	}

	function checkReplacement( $matches ) {
		if ( $this->replaceIndex == $this->replacePointer ) {
			$string = ' <a href="'.$this->replacements[ trim( $matches[0] ) ].'">'.trim( $matches[0] ).'</a> ';
		} else {
			$string = $matches[0];
		}
		++$this->replacePointer;
		return $string;
	}
}

$text = 'text ext random text weeerer text moretext text weee and then some moretext wee.';

$ALObj = new ALObj;
echo $ALObj->addLinks( $text );

?>
 
Yea man. There's a much easier way. This might work as well.

[HIGH=php]
<?php

function str_replace_random($haystack, $find, $replace_with)
{

preg_match_all('/\b'.$find.'\b/si', $haystack, $result, PREG_PATTERN_ORDER);

$n = array_rand($result[0]) +1;

$result = preg_split('/\b('.$find.')\b/', $haystack, $n, PREG_SPLIT_DELIM_CAPTURE);

array_push($result, preg_replace('/\b('.$find.')\b/', $replace_with, array_pop($result), 1));

return implode($result);

}


// USAGE::
$text = 'text ext random text weeerer text moretext text weee and then some moretext wee.';
$_replace = "--TEXT--";
$_find = "text";


echo str_replace_random($text, $_find, $_replace)

?>

[/HIGH]
 
ashbeats, I think kineticbug's solution works better...there are several words that need to be replaced, which is why it pulls from an array.