Jump to content

Recommended Posts

Guys,  total PHP noob here but years of MS development experience (I know, I know,,,).

 

Really need to get an understanding of this code, I have a handle on the individual lines and can run the code, but overall I'm kinda at a loss, all help much appreciated!

 

class MyTestClass
{
const REGEXP = '/\{(((?>[^\{\}]+)|(?R))*)\}/x';
 
public function render($text)
{
               return preg_replace_callback(
self::REGEXP,
[$this, 'replace'],
$text
);
}
 
public function replace($text)
{
$text = $this->render($text[1]);
$parts = explode('|', $text);
return trim($parts[array_rand($parts)]);
}
 
}
 
$obj = new MyTestClass();
 
$result = $obj->replace("Fred");
 
echo $result;

 

Link to comment
https://forums.phpfreaks.com/topic/298311-help/
Share on other sites

The regex is perfectly fine, but you're not using the class correctly.

 

What this does is look for substrings of the kind {<choice1>|<choice2>|<choice3>|...|<choicen>} and randomly replace them with one of the substrings <choice1>, <choice2>, <choice3>, ..., <choicen>. For example,

Have a look at our {fabulous|fantastic|awesome} pet shop.

could become “Have a look at our fantastic pet shop.” or “Have a look at our awesome pet shop”.

 

Nested patterns are also supported:

We sell {furry {cats|kittens}|adorable dogs}.

So it's basically a simple text generator.

You use the class by calling the render() method with an appropriate input. Do not call replace(), that's just an internal method.

<?php

class TextGenerator
{
    const REGEXP = '/\{(((?>[^{}]+)|(?R))*)\}/';

    public function render($text)
    {
        return preg_replace_callback(
            self::REGEXP,
            [$this, 'replace'],
            $text
        );
    }

    public function replace($text)
    {
        $text = $this->render($text[1]);
        $parts = explode('|', $text);
        return trim($parts[array_rand($parts)]);
    }

}

$textGenerator = new TextGenerator();
echo $textGenerator->render('We sell {furry {cats|kittens}|adorable dogs}.');

Edited by Jacques1
Link to comment
https://forums.phpfreaks.com/topic/298311-help/#findComment-1521550
Share on other sites

Jacques1 - thank you very much for the reply - it has really helped.   In the Replace function, the line

$text = $this->render($text[1]);

is confusing me, does this "recall" the Render function??

 

If I had to add a second parameter to Render, how would I pass it into the callback?

 

Thanks

Link to comment
https://forums.phpfreaks.com/topic/298311-help/#findComment-1521563
Share on other sites

In the Replace function, the line

$text = $this->render($text[1]);

is confusing me, does this "recall" the Render function??

 

Yes, the method is called repeatedly to handle nested expressions.

 

 

 

If I had to add a second parameter to Render, how would I pass it into the callback?

 

You can use a closure as the callback function. It has access to variables in the scope of its definition:

<?php

class TextGenerator
{
    const REGEXP = '/\{(((?>[^{}]+)|(?R))*)\}/';

    public function render($text, $separator)
    {
        $replace = function ($subject) use ($separator) {
            $subject = $this->render($subject[1], $separator);
            $parts = explode($separator, $subject);
            return trim($parts[array_rand($parts)]);
        };

        return preg_replace_callback(
            self::REGEXP,
            $replace,
            $text
        );
    }
}

$textGenerator = new TextGenerator();
$separator = '/';
echo $textGenerator->render('We sell {furry {cats/kittens}/adorable dogs}.', $separator);

This is actually a cleaner solution in general, because you don't need a pseudo-public replace() method.

Link to comment
https://forums.phpfreaks.com/topic/298311-help/#findComment-1521583
Share on other sites

PHP 5.3 doesn't support $this in a closure. You need to explicitly import it as a variable:

public function render($text, $separator)
{
    $currentObject = $this;
    $replace = function ($subject) use ($currentObject, $separator) {
        $subject = $currentObject->render($subject[1], $separator);
        ...
    };
}

Note that both PHP 5.3 and PHP 5.4 have reached end-of-life.

Link to comment
https://forums.phpfreaks.com/topic/298311-help/#findComment-1521663
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.