Why is the 'self'-call to a non-satic method in this example working?
class A{
protected function aNonStaticMethod(){
return __class__;
}
public function aEcho(){
echo self::aNonStaticMethod();
}
}
Thanks for explanation.
In your simple example $this and self is interchangable. But be aware of the different method resolving when dealing with inheritance (i added static for completeness):
class A {
protected function aNonStaticMethod(){
return __class__;
}
public function selfEcho(){
echo self::aNonStaticMethod();
}
public function staticEcho(){
echo static::aNonStaticMethod();
}
public function thisEcho(){
echo $this->aNonStaticMethod();
}
}
class B extends A {
protected function aNonStaticMethod(){
return __class__;
}
}
$b = new B();
$b->selfEcho(); // A
$b->staticEcho(); // B
$b->thisEcho(); // B
Calling non-static method statically
Theoretically it should not work, but as this comment says:
There was no static keyword in php4 but php4 did allow for static
calls. To maintain backwards compatibility this was left in when the
static keyword was added in php5.
This comment is supported by this official php.net wiki:
This is already deprecated if the call occurs from an instance method.
Not annotating methods as static is an obsolete PHP4-ism.
You really should not call non-static method statically - it does not make sense (if there is a static keyword).
Avoid calling non-static methods statically completely!
...because a) it is a bad approach and b) the PHP docs say:
Caution
In PHP 5, calling non-static methods statically generates an E_STRICT level warning.
AND
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.
Using :: operator for non-static calls - may be a good approach!
As #Kontrollfreak pointed out and as this docs say the :: operator is not limited to static calls:
the double colon, is a token that allows access to static, constant,
and overridden properties or methods of a class
So it is OK if you reference this way a method or properties from a parent class - which is not limited to a direct parent.
EDIT: do not mistake this for Fascade etc. software patterns!
During writing this answer I forgot to mention that there might be cases, when the call is static, but internally it is calling dynamic method - for more info see patterns like Facade or Singleton.
However do NOT mistake these with issue described above! (issue above is about using direct static call on dynamic thing that should be called dynamically, these patterns are about calling static methods statically, which then may dynamically invoke something dynamic (internally)).
Related
I have a web application that I just updated from 5.3 to 5.5 on my server and i get around 200-300 errors like below. I understand this is a deprecation error and is it possible to solve all in one go and not hide the errors?
Strict standards: Non-static method xyz() should not be called statically.
Calling non-static methods statically generates an E_STRICT level warning.
Function xys is not static, but is clled statically. See difference below.
<?php
// Calling non-static function, first create object by class
$foo = new Foo();
$foo->xyz();
// Calling static function (you are doing this)
Foo::xyz();
?>
You should define your function like this. Find where xyz is defined.
public static function xyz(){}
Then it wont throw strict standard error. Just add static to your function and all errors will be gone.
You don't have to change it in all 200 files. This function is just called in 200 files. That dosen't meen that you have bug in all of them.
NOTE: from docs
Because static methods are callable without an instance of the object created, the pseudo-variable $this is not available inside the method declared as static.
So, if your are using $this in function xyz, you have to use my first example. Then it means fixing all 200 files.
See docs for static keyword.
Just make the function static.
The fix is a simple one , but it has to done in all places where you called a static method that way. I think there is no other way.
I came across something like this, and am not sure what to make off it. Is there any good reason to do this, or to avoid it?
class Foo {
static public function bar() {}
}
someMethod() {
$instanceOfFoo->bar();
}
The PHP documentation says:
[...] A property declared as static can not be accessed with an instantiated class object (though a static method can).
[...] Static properties cannot be accessed through the object using the arrow operator ->.
without specifying anything special for static methods being called by ->. You should definitely avoid it though, because it causes confusion to the reader who's expecting $obj->meth() to be a non-static method and Cls::meth() a static method.
Surprisingly this behavior is not triggering any error. The reason for this is that a static method, called by $object->method() is internally translated to className::method() at run time (with the only difference being that $this = NULL is set).
You can call the particular function as below.
Foo::bar();
You don't have to create an object to call a static function. Basically we write static functions to call the function without an instance of the class in which it's defined.
It's okay to call a static function with an object but why do so when you have a simpler and cleaner method.
I am studying PHP,OOP and i am at Static,
At this php.net/static i didnt understand this sentence
Calling non-static methods statically generates an E_STRICT level warning.
I did understand it's Valid for methods only (not for Properties) by the sentence above,
but i didn't succeed to understand It practically,
I'm glad if anything could please show me code that explains the sentence above,
Wishing you a pleasant week.
class Foo
{
public static $my_static = 'foo';
public $my_non_static = 'bar';
public function staticValue() {
return self::$my_static;
}
public function nonStaticValue() {
return self::$my_non_static;
}
}
print Foo::$my_static . "\n"; // OK
print Foo::staticValue(). "\n"; // E_STRICT
print Foo::$my_non_static . "\n"; // Fatal
print Foo::nonStaticValue(). "\n"; // Fatal
print Foo::$my_static . "\n"; is OK - static property accessed statically.
print Foo::staticValue(). "\n"; gives E_STRICT - non-static method accessed statically, but not Fatal error, because this method doesn't access non-static properties.
Other two give Fatal error because non-static field cannot be accessed statically.
Here is an example of what they mean with the sentence you are asking about.
Consider the following class with one method (it is not static).
class Test
{
function method()
{
echo "Hello from method";
}
}
Test::method(); // attempt to statically call a non-static method
This is the output:
Strict Standards: Non-static method Test::method() should not be
called statically in /obj.php on line 12
Hello from method
As you can see, it did execute the method when called static even though it is not a static method, however a strict error message was displayed.
If the method method() referenced the keyword $this, then you would encounter a fatal error because $this does not exist in the context of a static method call. So while it is technically possible to call a non-static class method statically, it should not be done.
EDIT:
The reason you are even allowed to call a non-static class member statically is because the static keyword did not exist in PHP4 in the context of class methods so if you were designing a static class or method in PHP4, there was no keyword to indicate it, you would simply call it in the static fashion. Now PHP5 emits the warning if the method is called statically but doesn't have the static keyword in the declaration.
It's because even if you can call non-static methods statically, you shouldn't and it will be logged.
class Foo {
function bar(){
print "you should not do that";
}
}
Foo::bar(); would actually works, but you will get a E_STRICT warning because you can do that, but you shouln't.
If a method is non-static, it means that it belongs to an instance of a class. For example, if we have a class Car with a method called getDamage() (which computes how much damaged the car is), then you should not call this method in a static way.
You should only create an instance of the Car class and call getDamage() on that instance. This makes sense because a particular car can be damaged for 25% while another car can be damaged for 70%.
But calling getDamage() in a static way makes no sense: a static method does not belong to a particular instance of the class but to the class itself. And a Car class has no useful way of giving a result for getDamage(). You could still compute a value (perhaps 0) but it does not make sense.
http://codepad.viper-7.com/I0Zqoi
I don't understand what's wrong with this or how to fix it or why. Can someone who knows a little about programming please explain what's happening behind the scenes, like on the interpreter level? Also, how can I fix my problem, and why do I need to write my code in the way of the correction? Can you tell me, in human language, what is wrong with this and how to make it better? I guess my book isn't explaining well, and the code inside of it doesn't work. :/ Thank you.
class A
{
private $foo = 'bar';
function read()
{
echo self::$foo;
}
}
$a = new A();
a::read();
Strict Standards: Non-static method A::read() should not be called statically in /code/I0Zqoi on line 13
Fatal error: Access to undeclared static property: A::$foo in /code/I0Zqoi on line 8
The only workaround seems to be to add "static" in front of the method. Apparently, non-static methods cannot be accessed by static means (e.g., class A{function read(){echo "whatever"};} cannot be accessed by a::read() because the -> operator is necessary). Also, static properties cannot be accessed by object code, even if they exist within a function (e.g., class A{static $variable; function read(){echo $this->variable};} a->read(); won't work because the -> operator is being used to access a function that calls a static property.). By changing both the method and the property to static, the method can be accessed by static means. By changing both the method and property to non-static makes it so that either can be accessed with object instanciation. It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods. So, is the debugger broken? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static. :(((
The Strict Standards part is because a::read() is being called in a static context with ::. After declaring $a as a class instance of A, you should call the read() method on the variable using the -> operator:
// Proper non-static method call
$a = new A();
$a->read();
In the class definition, $foo is declared as a private property, but without the static keyword. It is then referred to in static context using the :: operator instead of the ->. The proper way to access it would beL
// Proper reference to non-static $foo
function read() {
echo $this->foo;
}
Now what does static mean anyway? Static methods and properties refer to class methods and properties that are shared by all current and future class instances. If A::$foo had been declared as:
private static $foo;
then there would be only the one $foo for all of class A in your code. Changing $foo would affect all instances of class A, and $foo can be accessed without even creating an instance of the class (like new A();)
Likewise, static methods can be called without creating an instance of the class because they do not modify class properties that are not also static.
// Static method call:
A::read();
To declare properties and methods as static, just add the static keyword:
// Property
private static $foo;
// Method
public static function foo() {}
EDIT for more examples:
class A
{
// Private property (non-static)
private $foo;
// Public property (static)
public static $bar = 12345;
// Public (non-static) function to access private $foo
public function getFoo() { return $this->foo; }
// Public (non-static) function to set private $foo
public function setFoo($newfoo) { $this->foo = $newfoo; }
// Static function
public static function incrementBar() { self::$bar++; }
}
Now see it in action:
// We haven't created any class instances yet (with the 'new' operator)
// But we can access the static properties & functions:
echo A::$bar . " ";
// prints 12345
A::incrementBar();
echo A::$bar . "\n";
// prints 12346
// Now we'll start working with class instances.
// Create 2 instances of class A
$a = new A();
$a->setFoo(8888);
$b = new A();
$b->setFoo(9999);
// It's a violation of strict standards to call getFoo() statically
// And it's meaningless to do so, because $foo only exists inside a class instance!
// Can't do this... Issues a strict warning since we're calling non-static getFoo() statically
//echo A::getFoo();
// But we can call getFoo() on the class instances:
echo $a->getFoo() . " " . $b->getFoo() . "\n";
// Prints 8888 9999
// Remember $bar was 12346...
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12346 12346
// Now modify the static property $bar again
// This affects all class instances.
A::incrementBar();
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12347 12347
I stuffed this whole thing into the codepad as well: http://codepad.viper-7.com/tV6omK
The book you're reading must not be paying attention to strict standards. If a non-static function does not attempt to access/modify a non-static property, you can call it statically successfully, but it WILL issue a strict warning. If the non-static function does modify or access a non-static property with $this->property, it will be a fatal error. You can't do that.
In PHP's error_reporting, the setting of E_ALL for show all errors actually does not include strict warnings. That has to be done with E_ALL & E_STRICT.
:: is used to access a static attribute. If you want to access an object attribute then use ->.
$a->read();
...
echo $this->$foo;
Although the other answers are definitely correct, here's an answer to your concrete question:
It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods. So, is the debugger broken? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static. :(((
The author of your book was under the impression that not getting an error message is considered clean code. It's not. You shouldn't have a method that can be called both statically as well as dynamically, as the two simply differ too much. Dynamic calls are for objects, where static calls are for classes. If you have the opportunity, I would always try to go the dynamic way, as that yields less coupling in the application.
As to why "the debugger is throwing errors" (it's the interpreter throwing E_STRICT warnings, but hey ;)): this behaviour has been changed in PHP five dot something. In PHP 4 you could call every method statically, even if it was a dynamic method. Possibly, your book is running behind on the facts.
What is the difference between these two pieces of code?
class something {
static function doit() {
echo 'hello world';
}
}
something::doit();
and the same but without the static keyword
class something {
function doit() {
echo 'hello world';
}
}
something::doit();
They both work the same is it better to use the static keywords? Am i right in understanding that it doesn't instantiate the class if you use the static method?
The second example is technically incorrect - if you turn on E_STRICT error reporting you'll see that PHP is actually throwing an error.
PHP Strict Standards: Non-static
method something::doit() should not be
called statically in...
In other words, it's being nice and letting you call the function anyway.
In addition to the other valid answers, the reason for the 2nd example working is also due to a quirk in how PHP handles objects and calls (Besides PHP 4 compatibility). Calling a non-static declared method statically from within another instance will let you access class methods on other classes as if they were local. To understand, let's take an example:
class A {
public function foo() {
echo get_class($this) . "\n";
}
}
class B {
public function bar() {
A::foo();
}
}
$a = new a();
$a->foo(); // "A"
$b = new B();
$b->bar(); // "B"
Did you see what happened there? Because you called the A::foo() method from within another class's instance, PHP treated the call as if it was on the same instance. Note that there is no relationship between A and B other than the fact that B calls A. Within A->foo(), if we did $this instanceof A (or $this instanceof self), it would fail and return false! Quite unusual...
Now, I first thought it was a bug, but after reporting it, it's apparently as designed. It's even in the docs.
Note that this will not work with E_STRICT mode enabled. It also will not work if you declare a method as static.
The difference is that static functions can be used without having to create an instance of the class.
Have a look at this great PHP OOP beginner tutorial here. It explains in more detail with an example under the Static Properties and Methods section.
Second bit shouldn't work as you should call it by
$something = new something();
$something->doit();
Static functions allows you to call a function within a class without consturcting it.
So basically if you have a class to handle users, so a function that logs the user in should be a static function, as in the constructor of that class you will probably gather the user information and you cannot do so without logging him in.
Your second example is wrong. Using a static method does not create an instance of the class. Your second example should look like this:
$x = new something();
$x->doit();
Static methods should be declared static for minimum two reasons:
a) when using E_STRICT error_reporting, calling non static method as static will generate error:
Strict standards: Non-static method something::doit() should not be called statically
b) based on keyword static some IDE's filter method possible to run at auto-complete.