문제

http://ronaldarichardson.com/2011/09/23/recursive-php-spintax-class-3-0/

I like this script, but it isn't perfect. If you use this test input case:

{This is my {spintax|spuntext} formatted string, my {spintax|spuntext} formatted string, my {spintax|spuntext} formatted string example.}

You can see that the result ALWAYS contains 3 repetitions of either "spintax" or "spuntext". It never contains 1 "spintax" and 2 "spuntext", for example.

Example:

This is my spuntext formatted string, my spuntext formatted string, my spuntext formatted string example.

To be truly random it needs to generate a random iteration for each spintax {|} block and not repeat the same selection for identical blocks, like {spintax|spuntext}.

If you look at comment #7 on that page, fransberns is onto something, however when using his modified code in a live environment, the script would repeatedly run in an infinite loop and eat up all the server memory. So there must be a bug there, but I'm not sure what it is.

Any ideas? Or does anyone know of a robust PHP spintax script that allows for nested spintax and is truly random?

도움이 되었습니까?

해결책

Please check this gist, it is working (and it is far simpler than original code ..).

다른 팁

The reason the Spintax class replaces all instances of {spintax|spuntext} with the same randomly chosen option is because of this line in the class:

  $str = str_replace($match[0], $new_str, $str);

The str_replace function replaces all instances of the substring with the replacement in the search string. To replace only the first instance, progressing in a serial fashion as you desired, we need to use the function preg_replace with a passed "count" argument of 1. However, when I looked over your link to the Spintax class and reference to post #7 I noticed an error in his suggested augmentation to the Spintax class.

fransberns suggested replacing:

$str = str_replace($match[0], $new_str, $str);

with this:

//one match at a time
$match_0 = str_replace("|", "\|", $match[0]);
$match_0 = str_replace("{", "\{", $match_0);
$match_0 = str_replace("}", "\}", $match_0);
$reg_exp = "/".$match_0."/";
$str = preg_replace($reg_exp, $new_str, $str, 1);

The problem with fransbergs' suggestion is that in his code he did not properly construct the regular expression for the preg_replace function. His error came from not properly escaping the \ character. His replacement code should have looked like this:

//one match at a time
$match_0 = str_replace("|", "\\|", $match[0]);
$match_0 = str_replace("{", "\\{", $match_0);
$match_0 = str_replace("}", "\\}", $match_0);
$reg_exp = "/".$match_0."/";
$str = preg_replace($reg_exp, $new_str, $str, 1);

Consider replacing the original class with this augmented version utilizing my correction on fransberns' suggested replacemnet:

class Spintax {

   function spin($str, $test=false)
   {
      if(!$test){
         do {
            $str = $this->regex($str);
         } while ($this->complete($str));
         return $str;
      } else {
         do {
            echo "<b>PROCESS: </b>";var_dump($str = $this->regex($str));echo "<br><br>";
         } while ($this->complete($str));
         return false;
      }
   }

   function regex($str)
   {
      preg_match("/{[^{}]+?}/", $str, $match);
      // Now spin the first captured string
      $attack = explode("|", $match[0]);
      $new_str = preg_replace("/[{}]/", "", $attack[rand(0,(count($attack)-1))]);
//      $str = str_replace($match[0], $new_str, $str); //this line was replaced
      $match_0 = str_replace("|", "\\|", $match[0]);
      $match_0 = str_replace("{", "\\{", $match_0);
      $match_0 = str_replace("}", "\\}", $match_0);
      $reg_exp = "/".$match_0."/";
      $str = preg_replace($reg_exp, $new_str, $str, 1);    
      return $str;
   }

   function complete($str)
   {
      $complete = preg_match("/{[^{}]+?}/", $str, $match);
      return $complete;
   }
}

When I tried using fransberns' suggested replacement "as is", because of the improper escaping of the \ character, I got an infinite loop. I assume that this is where your memory problem came from. After correcting fransberns' suggested replacement with the correct escaping of the \ character I did not enter an infinite loop.

Try the class above with the corrected augmentation and see if it works on your server (I can't see a reason why it shouldn't).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top