Juergen Posted June 25, 2019 Share Posted June 25, 2019 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 More sharing options...
teppo Posted June 25, 2019 Share Posted June 25, 2019 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 ? 7 1 Link to comment Share on other sites More sharing options...
Juergen Posted June 26, 2019 Author Share Posted June 26, 2019 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!! 1 Link to comment Share on other sites More sharing options...
MoritzLost Posted June 26, 2019 Share Posted June 26, 2019 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; } 5 Link to comment Share on other sites More sharing options...
Juergen Posted June 26, 2019 Author Share Posted June 26, 2019 2 hours ago, MoritzLost said: 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: That will be great ?! Thanks for you contribution @MoritzLost 1 Link to comment Share on other sites More sharing options...
Recommended Posts