0
class A {
    public $a = "BooMBa";

    public function fun1() {
        echo $this->a; 
     // echo (new self)->a;
    }
}

class B extends A {

    public static function fun2() {
        return (new self)->fun1();
     // return static::fun1();
    }
}

B::fun2();  // returns BooMBa

If I change fun2() to return static::fun1() then it gives

'Fatal Error: Using $this when not in object context'
But if I change fun1 to echo (new self)->a; then works fine.
Can someone explain why static:: hate $this but not (new self).

PS: Please consider that I went through these below given Q&A sections and some more articles yet couldn't get an exact hold of this particular scenario that what's going on.
What does new self(); mean in PHP?
PHP : Difference b/w new self and new object()
PHP: The Basics Manual
in PHP, what is the difference between self and $this?

PPS: This Q&A PHP Fatal error: Using $this when not in object context has nothing to do with mine other than the same error message. It's totally different context. In that question he simply calls a non-static method statically. Meanwhile my question is more complex with late static bindings and keywords (new self). It's not possible at all to understand my problem with the answer in the above mentioned Q&A so please go through both Q&A before marking it duplicate. Thank you.

Jeeva Raam
  • 47
  • 1
  • 10
  • is fun1 a static function? (hint: I believe not) – Ofir Baruch Nov 02 '17 at 06:54
  • No, fun1() is not an static method. – Jeeva Raam Nov 02 '17 at 07:00
  • It is because fun1 is not a static method. You can call something in static context only with a tool that is in static context too. That is the reason why fun1 fail to execute and fun2 executes without problems. So when you call B::fun1() you call method fun1 as a static method without instantiating the object. $this keyword is only for instantiated objects. To call fun1() with the current code you must first create an object $a = new A(), and then call method $a->fun1() – Bartosz Herba Nov 02 '17 at 07:07
  • Read this http://php.net/manual/en/language.oop5.static.php. You'll find better explaination – TarangP Nov 02 '17 at 07:13
  • Possible duplicate of [PHP Fatal error: Using $this when not in object context](https://stackoverflow.com/questions/2350937/php-fatal-error-using-this-when-not-in-object-context) – Progman Nov 02 '17 at 09:53

2 Answers2

1

This questions comes to "what is difference between class and instance".

I will simplify your example and go step by step.

class A {
    public $a = "BooMBa";
    public function fun1() {
        echo $this->a; 
    }
    public static function fun2() {
        return (new self)->fun1();
    }
}
A::fun2();  // returns BooMBa
  1. A::func2() - static call to A::func2
  2. (new self)->fun1() - creates instance of A and calls fun1 of that instance
  3. echo $this->a - echo contents of a of current(created in step 2) instance

Every call to A::func2 creates new instance of A in step 2


class A {
    public $a = "BooMBa";
    public function fun1() {
        echo $this->a; 
    }
    public static function fun2() {
        return static::fun1();
    }
}
A::fun2();  // fails
  1. A::func2() - static call to A::func2
  2. static::fun1() - static call to A::func1, there is no instance. AFAIK this should generate warning since you make static call to instance method
  3. echo $this->a; - echo contents of a of current instance, but there is no instance since we came here from static call, we are in class scope. Error

class A {
    public $a = "BooMBa";
    public function fun1() {
        echo (new self)->a;
    }
    public static function fun2() {
        return static::fun1();
    }
}
A::fun2();  // returns BooMBa
  1. A::func2() - static call to A::func2
  2. static::fun1() - static call to A::func1, there is no instance
  3. echo (new self)->a - create new instance of A and echo contents of variable a of just created instance

Every call to A::func2 creates new instance of A in step 3


class A {
    public $a = "BooMBa";
    public function fun1() {
        echo $this->a; 
    }
    public function fun2() {
        return $this->fun1();
    }
}
$a = new A();
$a->fun2();  // returns BooMBa
  1. $a = new A() - create new instance of A
  2. $a->fun2() - call method fun2 of instance $a
  3. $this->fun1() - call method fun1 of current instance ($a)
  4. echo $this->a - echo contents of a of current instance ($a)

$this refers to current instance of class, but if you static call, there is no instance. new self creates new instance of class which allows you to use $this since you have instance to refer to


Let's make example on cats. Instance of Cat is some $cat that stands in front of you. You can ask your $cat to purrr and since you refer to concrete instance of cat, inside of method purrr of that cat you can refer to $this and call echo $this->purrrSound. When you make static call you make call to abstract concept of Cat, there is no particular instance of Cat and there is no $this to refer to.

class Cat {
    public $purrrSound = "purrrrr...";
    public function purrr() {
        echo $this->purrrSound;
    }
}
$cat = new Cat();
$cat->purrr(); // kittty purrrr, please?
// Cat::purrr(); // all the Cats in the universe, purrr now?  
mleko
  • 11,650
  • 6
  • 50
  • 71
  • which is good practice ? step 1 or 3 ? I've simplified the example from a complex one, I tried this method instead of using 'global $a' in fun2() in class B in order to get full use of OOP. – Jeeva Raam Nov 02 '17 at 07:27
  • @JeevaRaam there is no good in this case. They are just different and all of them have their uses. I don't know what is your particular case, but check fourth example I just added, this might be just what you need – mleko Nov 02 '17 at 07:36
0

Static context

In PHP you can call method statically with The Scope Resolution Operator operator ::. So, this expression is just a static call:

return static::fun1()

When you're in a static context (after static call) $this doesn't work - it's a language assertion. Even in a static context this expression is still valid:

(new self)->a

Just because you're creting a new instance of object and then getting it's public property.


Deprecated note:

Caution In PHP 5, calling non-static methods statically generates an E_STRICT level warning.

Warning In PHP 7, calling non-static methods statically is deprecated, and will generate an E_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.

To your consideration:

Consider not to use static methods, because it's a coupling for other classes, and it's usually just a procedural code closes in a static method. For example implement this function in a new class and use dependency injection if you need it.

John Smith
  • 1,091
  • 9
  • 17