PHP Chaining ... Я просто не могу получить это! - PullRequest
1 голос
/ 14 июня 2011

Я пытаюсь создать функцию цепочки для работы со строками, которые возвращаются из файла XML.

1 исходная строка может иметь несколько замен, некоторые из которых происходят из файла XML.

Вот уродливый и стандартный упакованный подход:

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

Вот подход, который я пытаюсь повторить (как Java):

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

С учетом вышесказанного это работает легко ... пока я не использую функцию XML для получения замещающей строки.

Вот мой класс:

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 'Мне бы хотелось понять, почему это не работает так, как я думаю, и как это должно на самом деле работать.Кажется, что когда я снова вызываю класс (несмотря на то, что var_dump говорит, что он является отдельным экземпляром), он заменяет исходный текст на «Чарли», поэтому я не могу просто заменить часть первого бита.

Спасибо,Доминик

РЕДАКТИРОВАТЬ: Да!Я понял это (используя статику), но у Райано ниже есть еще лучшее решение

<?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;
}

function 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

?>

Ответы [ 2 ]

2 голосов
/ 14 июня 2011

Ваша проблема в том, что все статично. Я бы предложил освежить некоторые основы объектно-ориентированного программирования.

Поскольку все статично, состояние разделяется между всеми вызовами функций. В строке replace("vo", resources::getString("charlie")->show()) вложенный вызов resources::getString заменяет построенную строку (abravo) аргументом getString, равным charlie. Тогда функция обертки вызывается как replace("vo", "charlie"), но значение self::$string теперь равно charlie, которое не содержит vo, и поэтому конечный show() затем просто возвращает charlie. Если бы вместо vo вы бы назвали его с помощью replace("ar", resources::getString("charlie")->show()), итоговый show() возвратил бы chcharlielie.

Вы должны создать класс с нестатическими переменными-членами и методами, чтобы поддерживать отдельные состояния.

Вот рабочая версия:

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;
  }

}

Редактировать: мне нравится приведенный выше код как ближайший переход от кода вопроса. Если бы я писал что-то подобное сам, я бы упростил это так:

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";

Теперь нет необходимости в show(), а имена немного приятнее набирать. Многие другие полезные методы могут быть добавлены здесь; любая функция PHP-строки, которую вы хотите добавить в цепочку.

0 голосов
/ 14 июня 2011

Когда вы вызываете getString() несколько раз, вы создаете несколько экземпляров, так как вы вызываете new self() в getString().

Чтобы этого не происходило, вы должны создать метод getInstance() и использовать его в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
}
...