Jump to content

Recommended Posts

Hey, I'm having a little trouble with chaining and I can't quite understand why this is behaving like it is... it's probably obvious to anyone but myself :D

 

getString() retrieves the string and returns the entire object (for chaining), show() will output it as a String (so that I can do other stuff to the string first)

 

Here it is in it's basic form:

$resources->getString("newsletter.hello")->show(); // returns "Hello Name"

 

Then lets say I want to replace some text within that string...

$resources->getString("newsletter.hello")->replace("name","Bob")->show(); // returns "Hello Bob"

 

Now...... I want to replace some text within that string with another string I get using that object:

$resources->getString("newsletter.hello")->replace("name", $resources->getString("admin.name")->show())->show(); // returns "Bob" (instead of "Hello Admin")

 

Within the first call, it grabs "Hello name" but when it gets to the second call, it replaces "Hello name" with just "Bob" because it overrides the entire string with what the second call pulls back.

 

I need to understand why the first item gets it's value replaced (I'm guessing its because its reusing the same object so the Variable gets replaced rather than maintaining it for when I need to replace something within it) but I'm not sure how to fix it.

 

The class (stripped out crap so its easier to read):

 

class resources{
	private $currentLocale = "en";
	private $string = "";

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

	public function getString($stringName){

                        # Grabs stringName from an XML file
                        $this->string = xmlfile($stringName);

		return $this;

	}

	function replace($replace_this, $with_this){
		$this->string = preg_replace("/" . $replace_this . "/", $with_this, $this->string);
		return $this;
	}

	function show(){
		return $this->string;
	}

}

 

I'd really appreciate the help, I'm looking to understand this issue...

Link to comment
https://forums.phpfreaks.com/topic/239233-chaining-and-using-the-same-class/
Share on other sites

I'm guessing that I need to create the opposite of a Singleton class... Like so:

 

function getInstance(){
// If not created yet, create it and return
if (self::$instance){
self::$instance = new resources();
}
return self::$resources;
}

 

Will test and relay my results back here for future reference if it fixes or doesn't work

What I'm trying to replicate is like something in Java...

 

resources.getString("blahblah").replace("this","that").replace("that",resources.getString("anotherstring"));

 

Each resources thing is contained as its own thing but you don't need to initiate each one of them so that its all chained and on one line and really clean. If anyone understands?

class Foo {
  private $_original = '';
  private $_dirty = '';
  
  public function getString() {
    $this->_original = 'whatever';
    $this->_dirty = $this->_original;
    return $this;
  }
  
  public function show() {
    return $this->_dirty;
  }
  
  public function replace($thisstr, $thatstr) {
    $this->_dirty = str_replace($thisstr, $thatstr, $this->_original);
    return $this;
  }
}

 

#Use-Case 1
$resource->getString()->show(); // whatever
$resource->getString()->replace('whatever', 'whichever')->show(); // whichever
$resource->getString()->replace('whatever', 'what-eva')->show(); //what-eva

 

Derived from:

Here it is in it's basic form:

$resources->getString("newsletter.hello")->show(); // returns "Hello Name"

 

Then lets say I want to replace some text within that string...

$resources->getString("newsletter.hello")->replace("name","Bob")->show(); // returns "Hello Bob"

 

Now...... I want to replace some text within that string with another string I get using that object:

$resources->getString("newsletter.hello")->replace("name", $resources->getString("admin.name")->show())->show(); // returns "Bob" (instead of "Hello Admin")

 

Which is different from:

 

resources.getString("blahblah").replace("this","that").replace("that",resources.getString("anotherstring"));

 

class Foo {
  private $_string = '';
  
  public function getString() {
    $this->_string = 'whatever';
    return $this;
  }
  
  public function replace($thisstr, $thatstr) {
    $this->_string = str_replace($thisstr, $thatstr, $this->_string);
    return $this;
  }
  
  public function show() {
    return $this->_string;
  }
}

 

#Use-Case 2
$resources->getString()->show(); // whatever
$resources->getString()->replace('whatever', 'whichever')->replace('whichever', 'what-eva')->show(); // what-eva

Now you realize where your thinking went wrong it's time to ponder further and question your current design. Since you could make this mistake someone else using your API will too. How to solve? This of course depends on how you want your design to behave. You could implement Lazy Initialization, since you suggested a Singleton I think this is the way you want to go without actually implemeting the Singleton of course.

 

class Foo {
  private $_string;
  
  public function getString(){
    if (is_null($this->_string)) {
      $this->_string = xmlfile();
    }
    return $this;
  }
}

 

This has a drawback that once the value is loaded from the XML it's not "refreshed" on subsequent calls.

 

$resources->getString()->show(); // bla
$resources->getString()->replace('bla', 'foo')->show(); // foo
$resources->getString()->show(); // foo

 

In contrast to your current design where it loads bla from the XML on each call to getString()

Hi, thanks for the reply :) I've had a look through the code that you've posted and read into lazy initialisation and it sounds like what I'm trying to figure out. You process the string as many times as you need to and then at the end you display the item.

 

I got a little closer to solving this at work but forgot to send it home to have another play so will try and mimic what I had created. I basically set it so that every call of getString created a new instance of the object so they were all unique but I had this problem... The first time it would allow a replace and would use its own object, but the next time I try it, it reused the first object like so:

 

Object resources [1]

Object resources [2]

Object resources [1]

 

 

The code you posted here works until you try and replace a string with something else from the XML file

 

Heres the original:

 

#Use-Case 2
$resources->getString()->show(); // whatever
$resources->getString()->replace('whatever', 'whichever')->replace('whichever', 'what-eva')->show(); // what-eva

 

And what doesn't seem to work when you try to replace using something else from the XML:

 

#Use-Case 2
$resources->getString()->show(); // whatever
$resources->getString()->replace('whatever', 'whichever')->replace('whichever', $resources->getString()->show())->show(); // should display "whatever" again

 

The reason I wanted to chain was to make it really easy to replace strings one after the other:

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

 

Otherwise you have loads of wrapping and it gets really ugly:

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

 


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

 

This is the closest I thought I had got... but the original value gets replaced with 'charlie' instead of maintaining 'abravo' and replacing part of that... So close yet so far away!

Managed to get this solved :) I originally came across a solution using a static object and another method but was given a much better solution by a guy named Ryano from Stackoverflow...

 

I will post his solution (I won't include mine as I don't want others to use bad code)

 

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

}

$resources->getString()->replace('whatever', 'whichever')->replace('whichever', $resources->getString()->show())->show(); // should display "whatever" again

 

No, that should display whichever anything else is wrong due to the lazy initalization as you are actually doing this:

 

$resources->getString()->replace('whatever', 'whichever')->replace('whichever', 'whichever')->show(); // should display "whatever" again

 

You see ;)

 

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

 

This is also not true since str_replace accepts an array. Very few people seem to know this feature exists.

 

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

 

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

 

This doesn't work because when you replace "vo" you set the static value of $string to "charlie" effectively trying to replace "vo" in "charlie".

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.