PHP цепочка... Я просто не могу получить это!
Я пытаюсь создать функцию цепочки для работы со строками, которые возвращаются из файла 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
Мне бы хотелось, чтобы он понял, почему он не работает так, как я думаю, и как он должен работать на самом деле. Кажется, что когда я снова вызываю класс (несмотря на то, что 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 ответа
Ваша проблема в том, что все статично. Я бы предложил освежить некоторые основы объектно-ориентированного программирования.
Поскольку все статично, состояние разделяется между всеми вызовами функций. В соответствии 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, которую вы бы хотели создать.
Когда вы звоните 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
}