7

In PHP it's not possible to return self to chain static methods. This limits the usage of static methods, because chaining is pretty useful and you have to use instances to chain methods.

Are there any reasons why the PHP developers decided not to allow returning self? Or is it not possible to return self in OOP in general?

Community
  • 1
  • 1
js-coder
  • 8,134
  • 9
  • 42
  • 59
  • 5
    to be honest, chaining is being overused to the point of impacting readability because everyone seems to think that the purpose of clean readable code is to make the longest chain possible (in a similar way people used to think that nested ternaries where cool); anyways, see here http://stackoverflow.com/questions/125268/chaining-static-methods-in-php – scibuff Feb 28 '12 at 12:45
  • 1
    I think that's a matter of personal preference. – js-coder Feb 28 '12 at 12:49
  • 7
    If you need to chain static methods then you probably have made some design mistake. – Crozin Feb 28 '12 at 12:52
  • @Crozin Can you explain that a bit more? Maybe I understood some OOP concepts wrong. – js-coder Feb 28 '12 at 12:58
  • Complely agree. Keep you top level interacting with the objects but never any deeper than that (or at least avoid it). Otherwise you'll end up with Spaghetti objects and a maintainence mess when you alter object structures later on. – Luc Feb 28 '12 at 12:59
  • FYI: when you are using static methods, it is not OOP. That you do is "class oriented programming". Basically, you are using global variables in simple functions , which have been wrapped in a namespace ( which is just masked as declaration of class ). – tereško Feb 29 '12 at 00:03

6 Answers6

7

Try return new static() or return new self():

class Calculator
{
    private static $_var = 0;

    public static function startFrom($var)
    {
        self::$_var = $var;
        return new static();
    }

    public static function add($var)
    {
        self::$_var += $var;
        return new static();
    }

    public static function sub($var)
    {
        self::$_var -= $var;
        return new static();
    }

    public static function get()
    {
        return self::$_var;
    }
}

This could be used for chain static methods:

echo Calculator::startFrom(10)
    ->add(5)
    ->sub(10)
    ->get(); // return 5

New self vs. new static

Nick Tsai
  • 3,799
  • 33
  • 36
4

I cannot give you a reason why other than the syntax itself isn't supported. It almost could work in PHP 5.3:

class Foo
{
  public static function A()
  {
    return __CLASS__;
  }

  public static function B() { }
}

$chain = Foo::A();
$chain::B();

If PHP would parse Foo::A()::B() then it would work.

Matthew
  • 47,584
  • 11
  • 86
  • 98
3

You can't return a 'self' because no OOP language I know allows to return a type as a type (don't know how to rephrase that). However everyone allows to returns an instance of a type. A static method is part of a class definition and it is callable as long as the application runs.

When doing OOP, you should use the static keyword very carefuly, as it's very easy to abuse it. If you want to chain methods then use an object. Static methods should be used only when no state is required and the function simply process an input and returns a result.

When chaining you have to maintain state and that's where you don't use static classes/methods at all (ok there are some cases but those are exceptions and it's not the case here).

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • 1
    In Python or Ruby, `return cls/self` works just fine in class methods (because actually classes are first-class objects themselves in these and many other languages). – Niklas B. Feb 28 '12 at 15:44
  • I don't know python nor ruby :). However is still strange to me to return the static class as itself, only to save typing a few characters?! – MikeSW Feb 28 '12 at 15:46
  • MikeSW: I didn't say it would be sensible to do that, but it should at least be possible in object-based languages (object-based as in everything is an object, including types). – Niklas B. Feb 28 '12 at 15:48
1

If you really had to, you can use self::class:

class Foo
{
    public static function returnSelfClass(): string
    {
        return self::class;
    }
}

You can even use static::class for late static binding:

class Bar
{
    public static function returnStaticClass(): string
    {
        return static::class;
    }
}

class Baz extends Bar
{
}

For instance:

Foo::returnSelfClass()::returnSelfClass(); // Works
echo Baz::returnStaticClass(); // Prints "Baz"
MAChitgarha
  • 3,728
  • 2
  • 33
  • 40
1

In PHP 7.0 forward, this works

class test {
    public static function a(){
        echo 1;
        return __CLASS__;
    }
    public static function b(){
        echo 2;
        return __CLASS__;
    }
}

test::a()::b();
John
  • 158
  • 1
  • 5
0

If somebody that had no relationship to you asked you to give up yourself and return yourself to something that didn't exist how would you feel?

Luc
  • 985
  • 7
  • 10