【问题标题】:PHP Chaining... I just can't get it!PHP 链接...我就是不明白!
【发布时间】:2011-06-13 21:03:56
【问题描述】:

我正在尝试创建一个链接函数来处理从 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 说它是一个单独的实例),它用“charlie”替换了原始文本,所以我不能只替换第一位的一部分。

谢谢,多米尼克

编辑:是的!我已经想通了(使用静态),但似乎下面的 Ryano 有一个更好的解决方案

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

?>

【问题讨论】:

  • 我假设你看过一些糟糕的设计模式建议。摆脱所有staticself:: 的东西并使用$this-&gt; 代替它。并给该类一个适当的名称(“mystrings”),如果这是它所处理的。
  • 静态方法试图将每个对象保持在它自己的范围内,但它似乎不起作用。我最初确实像您说的那样拥有它,但这也不起作用,因此尝试了多种方法。资源在其简单的形式中是一个坏名字,但我已经剥离了很多代码来尝试让基本功能正常工作
  • 如果嵌套超过 2 个级别,您的“工作”版本将不起作用。试试resources::getInstance("nomster")-&gt;replace('nom', resources::getInstance("mon")-&gt;replace("o", resources::getInstance('bob')-&gt;show())-&gt;show())-&gt;show()。当它应该返回 mbobnster 时,这将返回 bb
  • 那是因为您在 replace 方法中调用 getInstance 。您只在第一次调用 getInstance 以便可以在同一页面上多次使用该类。如果您复制并粘贴我的示例,它可以 100% 工作。我将看看您在下面发布的内容,因为我确定我即将学到一些东西:D

标签: php oop static replace method-chaining


【解决方案1】:

您的问题是一切都是静态的。我建议复习一些面向对象的编程基础知识。

因为一切都是静态的,所以状态在函数的所有调用之间共享。在replace("vo", resources::getString("charlie")-&gt;show()) 行中,对resources::getString 的嵌套调用将到目前为止构建的字符串(abravo) 替换为getString 的参数charlie。然后像replace("vo", "charlie") 一样调用包装函数,但是self::$string 的值现在是charlie,它不包含vo,因此最终的show() 然后简单地返回charlie。如果不是vo,而是使用replace("ar", resources::getString("charlie")-&gt;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 字符串函数。

【讨论】:

  • 我没有先使用静态的东西,我有更接近这个的东西,但它从来没有用过,我也不明白为什么......必须与我的第一个版本进行比较,看看我到底是什么做错了:D 我上面的工作代码确实有效,但远没有这样简单和好(我花了大约 10 个小时才到达)......我不得不在每个字符串的开头使用 getInstance 函数并使用负载的静力学。非常感谢这个答案:)
  • 刚刚测试了您最新的代码迭代,它的性能要好得多,而无需在所有代码结束时调用最后一个 ->show() 函数。最初只是在那里,因为我不确定上次如何自己打印出来。谢谢,我现在知道为什么我第一次不能让它工作了。
【解决方案2】:

当您多次调用getString() 时,会创建多个实例,因为您在getString() 中调用了new self()

为防止这种情况发生,您应该创建一个方法 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
}

【讨论】:

  • 我故意创建多个实例以尝试将每种用法的范围保持在自己的范围内...我有多个对象,但由于某种原因它们仍然相互覆盖:/
  • 那么你应该(imo)不要使用创建对象的静态方法,而是首先创建你的对象,然后使用非静态方法。方法名称应该是不言自明的,至少在大多数情况下是这样。没有人(甚至在两个月内你也不)期望静态方法 getString() 返回一个新实例。
  • 这是单例模式,不是这里的答案。
猜你喜欢
  • 2011-01-14
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-30
  • 1970-01-01
  • 2023-01-21
  • 2011-05-08
相关资源
最近更新 更多