4
<?php
class A {
  public function instanceFunc() {
    echo "instance";
  }

  public static function staticFunc() {
    echo "static";
  }
}

A::instanceFunc(); // instance
$a = new A();
$a->staticFunc(); // static

This means in PHP static method and instance method have no different at all. Zend doesn't even complain about it(WITHOUT WARNING).

In Zend Engine. both static method and instance method all saved in zend_class_entry.function_table.

Why PHP behave like this? It's a bug or feature?

Charles
  • 50,943
  • 13
  • 104
  • 142
reeze
  • 37
  • 1
  • 5
  • 4
    Testing your code made me cry... – Shoe Apr 19 '11 at 17:18
  • To paraphrase Ian Malcom: "Just because you can doesn't mean you should!" :) – Chris Baker Apr 19 '11 at 17:38
  • possible duplicate of [Does static method in PHP have any difference with non-static method?](http://stackoverflow.com/questions/2439036/does-static-method-in-php-have-any-difference-with-non-static-method) – danorton Mar 25 '14 at 18:58

3 Answers3

3

This is a potential duplicate of Does static method in PHP have any difference with non-static method?.

You will get an error message if you have E_STRICT warnings enabled, otherwise, you are able to silently call a nonstatic method as if it were static. As mentioned in answers here and at the other question, a real-world static/nonstatic method would not get far without having access to $this or self as it was written to expect.

Refer to the docs: http://www.php.net/manual/en/language.oop5.static.php

Here's something to play with:

http://codepad.org/Gbu9T6Zv

Community
  • 1
  • 1
Chris Baker
  • 49,926
  • 12
  • 96
  • 115
  • call a static method instancely nothing would happen – reeze Apr 24 '11 at 03:38
  • @reeze, I'm unsure of the meaning of your comment, but there is absolutely nothing wrong with invoking a static method via an instance object, and _everything_ happens exactly as if it were invoked via a class literal. – danorton Mar 25 '14 at 18:55
2

If you try running the code below and look at the backtrace output you will see that PHP converts instanceFunc() to a static method when called in a static context. However, in an instance context it will treat it as a instance call.

If you introduce instance variables in to the mix (remove commented out lines) then a fatal error is encountered when called instanceFunc() from a static call.

This implies that PHP allows all methods that are static in nature (no instance variables are worked with) to be called from a static context, as soon as this contract is broken however an error will be produced. Therefore the use of static functions seems to be only good practice in keeping with other Object Orientated languages.

With regards to staticFunc() both calls show that PHP interprets these as static calls, which is to be expected.

class A {
  private $x = 5;
  private $y = 6;
  private $z;
  public function instanceFunc() {
    //$this->z = $this->y * $this->x;
    //echo $this->z;
    var_dump(reset(debug_backtrace()));
  }

  public static function staticFunc() {
    var_dump(reset(debug_backtrace()));
  }
}
$a = new A();
A::instanceFunc(); // static call of intended instance method
$a->instanceFunc(); // instance call of instance method
A::staticFunc();
$a->staticFunc();

Example output (code running with comments):

array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(19) ["function"]=>  string(12) "instanceFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=>  array(0) { } } 
array(7) { ["file"]=> string(59) "test.php" ["line"]=> int(22) ["function"]=> string(12) "instanceFunc" ["class"]=> string(1) "A" ["object"]=> object(A)#8 (3) { ["x:private"]=> int(5) ["y:private"]=> int(6) ["z:private"]=> NULL } ["type"]=> string(2) "->" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(24) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(26) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } }
GordyD
  • 5,063
  • 25
  • 29
  • Interesting stuff on the backtrace, +1. In light of the fact the doing this will throw an E_STRICT error only, I am assuming this is maintained for some legacy/backwards compatibility reasons - with an intent to eventually eliminate it. Otherwise, the "convert this method to static" behavior is nonsense - you're totally correct about it, but it is nonsense all the same! – Chris Baker Apr 19 '11 at 17:53
  • I agree, it is nonsensical, but PHP was not born an OO language and so I imagine your suspicions of this 'bug' existing for legacy reasons is correct. – GordyD Apr 19 '11 at 18:03
1

I am not sure why it would not throw a warning or at least an error. However, there are some major differences in the static and instance. A static method cannot use class variables that are non-static. Which is easily tested by adding a public / private variable that is non-static and trying to echo it in the staticFunc that will throw an error.

I think the main goal is to understand the differences between the two and how to properly use them. As far as why PHP does not at least raise a Notice, I do not know, perhaps it is due to its laid back nature. I am interested in the response someone who has more knowledge on it can give, this is kind of just a bit of extra information.

I did test it with full error reporting on, and sure enough it really does not throw a notice or warning.


UPDATE

Doing some testing, it seems as though when you call a non marked static function as a static function, you still cannot use the private/public variables. Which, for normal functions, will most likely error them out. Which could be why the error or notice was never thrown. However, it would be nice for it to throw something about it, as using a non-marked static function in such a way is surely not good to do.

Jim
  • 18,673
  • 5
  • 49
  • 65