开发者

PHP Chaining... I just can't get it!

I'm trying to create a chaining function for working with strings that are returned from an XML file.

1 original string may have multiple replacements, some of which come from the XML file.

Here is the ugly and standard wrapped approach:

str_replace("what","is meant", str_replace("name","randomer",str_replace("blah", "hello", $string1)));

Here is the approach I'm trying to replicate (like Java):

$string1.replace("blah","hello").replace("name","randomer").replace("what","is meant");

With the above, it works easily... until I use the XML function to get the replacing string.

Here's my class:

class resources{

private static $instance, $string;

public static function getString($stringName){
    # Create new instance
    self::$instance = new self;

    # Grabs stringName from an XML file
    self::$string = $stringName;

    # Return instance
    var_dump(self::$instance);
    return self::$instance;

}

public static function replace($replace_this, $with_this){
    # Replace and return instance
    self::$string = str_replace($replace_this, $with_this, self::$string);
    return self::$instance;
}

public static function show(){
    # Return String
    return self::$string;
}

}

echo resources::getString("alpha") // alpha
    ->replace("lpha","bravo") // abravo
    ->replace("vo", resources::getString("charlie")->show()) // should be abracharlie
 ->show(); // charlie

I'd like it to understand why it's not working as I think it should and how it should actually work. It seems that when I call the class again (despite var_dump saying its a seperate instance), it replaces the original text with "charlie" so I can't just replace a part of the first bit.

Thanks, Dominic

EDIT: Yes!! I have figured it out (using statics) but it seems Ryano below has an even better solution

<?php

class resources{
private static $instance, $string, $originalString;

public static function getInstance($stringName){
    self::$instance = new self();
    self::$originalString = $stringName;
    return self::$instance;
}

public static function getString($stringName){
    # Grabs stringName from an XML file
    self::$string = $stringName;
    return self::$instance;
}

functi开发者_开发技巧on replace($replace_this, $with_this){
    self::$originalString = str_replace($replace_this, $with_this, self::$originalString);
    self::$string = self::$originalString;
    return self::$instance;
}

function show(){
    return self::$string;
}

}

echo resources::getInstance("alpha") // alpha
    ->replace("lpha","bravo") // abravo
    ->replace("vo", resources::getString("charlie")->show()) // should be abracharlie
    ->replace("lie", resources::getString("vo")->show()) // abracharvo
    ->show(); // abracharvo

echo "<br />";

echo resources::getInstance("randomer") // randomer
    ->replace("er","") //  random
    ->replace("ran", resources::getString("")->show()) // dom
    ->replace("dom", resources::getString("Dom")->show()) // Dom
    ->show(); // Dom

echo "<br />";

echo resources::getInstance("nomster") // nomster
    ->replace("nom","nmo") //  nmoster
    ->replace("nom", resources::getString("mon")->show()) // nmoster
    ->replace("nmo", resources::getString("mon")->show()) // monster
    ->show(); // monster

?>


Your problem is that everything is static. I would suggest brushing up on some object-oriented programming fundamentals.

Because everything is static, the state is shared between all invocations of the functions. In the line replace("vo", resources::getString("charlie")->show()), the nested call to resources::getString replaces the string built so far (abravo) with the argument to getString which is charlie. Then the wrapping function is called like replace("vo", "charlie"), but the value of self::$string is now charlie, which does not contain vo and therefore the final show() then returns simply charlie. If, instead of vo, you'd called it with replace("ar", resources::getString("charlie")->show()), the final show() would have instead returned chcharlielie.

You must create a class with non-static member variables and methods in order to maintain separate states.

Here's a working version:

class resources {

  private $string;

  public function __construct ($string) {
    $this->string = $string;
  }

  public static function getString ($string) {
    $obj = new resources($string);

    return $obj;
  }

  public function replace ($replace_this, $with_this) {
    # Replace and return instance
    $this->string = str_replace($replace_this, $with_this, $this->string);
    return $this;
  }

  public function show () {
    # Return String
    return $this->string;
  }

}

Edit: I like the above code as the closest transition from the question's code. If I was writing something similar myself, I would simplify it further like this:

class Str {
    private $str;

    private function __construct ($str) {
      $this->str = $str;
    }

    public static function with ($str) {
        return new Str($str);
    }

    public function replace($replace_this, $with_this) {
      $this->str = str_replace($replace_this, $with_this, $this->str);
      return $this;
    }

    public function __toString () {
      return $this->str;
    }
}

echo Str::with('nomster')->replace('nom', 'mon') . "\n";

Now there's no need for show() and the names are a little nicer to type. Many other useful methods could be added here; any php string function you would want to chain.


When you call getString() several times, you create several instances since you call new self() in getString().

To prevent that from happening you should create a method getInstance() and use that in getString()

public static function getInstance() {
    if(!self::instance) {
        self::instance = new self();
    }
    return self::instance;
}

public static function getString() {
    $instance = self::getInstance();

    // use $instance here instead of self::instance
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜