2

I want to have a class that i can use it this way:

Thing::doThis()->doThat()->doImportantThing(); 

OR

Thing::doThat()->doImportantThing(); 

OR

Thing::doImportantThing(); 

But currently i can only use it this way:

$thing = new Thing(); $thing->doThis()->doThat()->doImportantThing(); 

What do i have to change in the class so i can use it the way i want? I already return a Thing instance in every function call.

I want to use that for a simple reason, imagine a mail class, in the constructor you define a default from and to, but you might want to change it, so you do Mail::setFrom()->send(). If you want to change the to, you use Mail::setTo()->send(). It just makes it easier to use if it's going to be used in different projects by different people.

I want by calling Mail::{something} to have like a constructor call and then run the {something} function.

6
  • 2
    I couldn't help but wonder, why? Commented Sep 2, 2014 at 11:17
  • Maybe this will help somehow Commented Sep 2, 2014 at 11:32
  • @Sami Thank you, but that question partially helps, but what i want to achieve, by that example, is avoid the getInstance() call. Commented Sep 2, 2014 at 11:35
  • The real answer to this question is to tell you to stop using static methods. Commented Sep 2, 2014 at 11:50
  • 1
    Well for one because you need an instance here (in any sane setup). More important it most likely produces tightly coupled code, hides dependencies, is a maintenance and debugging nightmare and kills testability. Commented Sep 2, 2014 at 11:54

2 Answers 2

3

You can do this

class Thing { public static function __callStatic($name, $arguments){ $thing = new self; return $thing->$name($arguments); } public function __call($name, $arguments){ return $this->$name($arguments); } private function doThis(){ echo 'this'.PHP_EOL; return $this; } private function doThat(){ echo 'that'.PHP_EOL; return $this; } private function doImportantThing(){ echo 'Important'.PHP_EOL; return $this; } } Thing::doThis()->doThat(); Thing::doThat()->doImportantThing(); 

It is a really ugly work-around, though. And it disables you to have private methods.

DEMO

Sign up to request clarification or add additional context in comments.

6 Comments

I want to use that for a simple reason, imagine a mail class, in the constructor you define a default from and to, but you might want to change it, so you do Mail::setFrom()->send(). If you want to change the to, you use Mail::setTo()->send(). It just makes it easier to use if it's going to be used in different projects by different people.
So you would like to do method chaining, or just static calling?
@MichelTomé why not just pass optional parameters to the send() method?
Both, it's kind of hard to explain... I want by calling Mail::{something} to have like a constructor call and then run the {something} function
@MichelTomé: I added your explanations to the question, I think it's clearer now.
|
0

One great thing for static methods is that they can work in object context, and can be called like this: $instance->staticMethod()

Here it is (even you get code completion in ide, and works as axpected as you want):

class Mail { public static $from; public static $to; public static $subject; public static $message; protected static $onlyInstance; protected function __construct () { // disable creation of public instances } protected static function getself() { if (static::$onlyInstance === null) { static::$onlyInstance = new Mail; } return static::$onlyInstance; } /** * set from * @param string $var * @return \Mail */ public static function from($var) { static::$from = $var; return static::getself(); } /** * set to * @param string $var * @return \Mail */ public static function to($var) { static::$to = $var; return static::getself(); } /** * set subject * @param string $var * @return \Mail */ public static function subject($var) { static::$subject = $var; return static::getself(); } /** * set message * @param string $var * @return \Mail */ public static function message($var) { static::$message = $var; return static::getself(); } public static function send() { echo "<pre><b>Hurrah mail sent</b>" . "\nFrom:\t ".static::$from."" . "\nTo:\t ".static::$to." " . "\nSubject: ".static::$subject."" . "\nMessage: ".static::$message; echo "</pre>"; } } 

Example usage:

Mail::from('george@garcha') ->to('michel@tome') ->subject('hehe works') ->message('your welcome') ->send(); 

Output

Hurrah mail sent From: george@garcha To: michel@tome Subject: hehe works Message: your welcome 

Example 2 (this also works):

 Mail::from('george@garcha') ->to('michel@tome'); Mail::subject('hehe works') ->message('your welcome') ->send(); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.