Jump to content

OOP: Method chaining if value is empty - How to?


Juergen
 Share

Recommended Posts

Hello @ all,

I am learning OOP and I have a problem for which i didnt find a solution in the web. Maybe someone can help me out.

I have written a class to render alerts. Fe. to output an alert  box I can write:

default notation:

$alert = new Alert();
$alert->text('This is the alert text');
echo $alert->render();

or with method chaining:

echo (new Alert())->text('This is the alert text')->render();

Both methods work until text has content inside. So sometimes there is no text content present (text value is empty).

default notation (this works):

$alert = new Alert();
$alert->text();
echo $alert->render();

or with method chaining (this leads to an error):

echo (new Alert())->text()->render();

So if text has no value I get this error if I use method chaining: Call to member function render on null

This is the getter/setter method for the text

public function text(string $value = null)
  {
    if($value){
        $this->text = trim($value);
        return $this;
    } else {
       return $this->text;
    }
  }

Is there a way to get method chaining to work if there is no value in the text property present?

Thanks for your help

Link to comment
Share on other sites

Chaining is based on the idea that your method returns a self-reference, i.e. "return $this", after which you can access another method from the returned object.

In your example when you leave $value param of the text() method empty (so that it defaults to "null"), the method returns "$this->text" (which is a string or null) instead of an object – and you cannot use a string (or null) for chaining (it doesn't have any methods).

In other words: even if "$this->text" had a non-null value, you still couldn't use it for chaining, 'cause it would return a string and not a self-reference to the containing object ?

Based on your code it looks like text() without a $value is supposed to work like a getter, returning the text (string), so technically this is how it's supposed to work. The most obvious option would be defining another method – perhaps something like setText(string $value = null) – that sets the value but always returns $this, and never the value itself. Or you could just modify the text() method so that it cannot be used as a getter for the value, i.e. make that always return $this.

Hope this helps a bit ?

  • Like 7
  • Thanks 1
Link to comment
Share on other sites

Thanks @teppo

this is a very clear explanation. Chaining is only possible with a reference to the object itself not with a string. You are right: my method for text is a combination of a setter an a getter and the getter will always return a string or null, so no reference to the object itself.

So I ended up separating getter and setter into 2 different methods and now it works with or without chaining:

public function setText(string $value = null)
  {
    $this->text = trim($value);
    return $this;
  }

public function getText()
  {
      return $this->text;
  }

In other forums they also do not recommend to combine getter and setter in one method. I thought that combining both would be an useful and elegant way - so I have learnt something new ?!

Thanks! It helps me a lot!!

  • Like 1
Link to comment
Share on other sites

2 hours ago, Juergen said:

In other forums they also do not recommend to combine getter and setter in one method. I thought that combining both would be an useful and elegant way - so I have learnt something new ?! 

Just to expand on this, having seperate methods for getting and setting are preferable because you can use typehints to declare argument and return types. This way, your methods become more robust (invalid arguments produce errors instead of propagating through your application and causing errors elsewhere), and your IDE / code editor can use them to provide better hints while using the methods. If you have just one method for both, you can't use a return typehints, because the function might return a string or an object. To expand on your two methods:

public function setText(string $value): self
{
	$this->text = trim($value);
	return $this;
}

public function getText(): string
{
	return $this->text;
}

I'm looking forward to PHP 7.4 which will have typed class properties. Then we'll be able to get rid of the getText method altogether:

public string $text;

public function setText(string $value): self
{
	$this->text = trim($value);
	return $this;
}

 

  • Like 5
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...