I just wrote a sample class to better understand the static methods and variables in PHP. I understand how the static variables work but the static function is not working as expected. If you see the below code
class Car{
static $wheels=4;
static function getWheels(){
echo Car::$wheels=10;
}
}
$car1 = new Car();
$car1->getWheels();
I was expecting
$car1->getWheels(); to throw and error since getWheels is a static method.
Why is this not throwing an error or warning?
I think it comes from the PHP 4 times, where there was no static keyword but you could call static methods whether with the -> or the :: operator
In fact, tecnically speaking, calling $car1->getWheels() was (and is) translated by PHP to Car::getWheels() at run time
With the advent of PHP5 this option was mantained for backward compatibility purposes
If you enable E_STRICT error reporting though, this should raise a warning now
Related
I've found some odd behaviour in some legacy code that I am trying to understand. I have boiled it down to a simple test-case.
<?php
class Foo {
function DoFoo() {
print("[" . get_called_class() . "]");
}
}
class Bar {
function DoBar() {
Foo::DoFoo();
}
}
// Called by direct static call.
Foo::DoFoo();
// Called by indirect static call, without an object context.
Bar::DoBar();
// Called by indirect static call, from within an (unrelated) object context.
// (But still, ultimately, a static call).
$Bar = new Bar();
$Bar->DoBar();
This code gives the following output:
[Foo][Foo][Bar]
However, the description of get_called_class() says that this function "Gets the name of the class the static method is called in.". As DoFoo() is always called statically on the Foo class, you would therefore expect get_called_class() to return Foo, in which case you should get the following output:
[Foo][Foo][Foo]
Ignore the fact that the above code generates strict standards warnings (these are suppressed in the original code-base) and that the issue being described can be fixed by properly declaring the static functions as static (which is the correct 'solution' to the problem). What I am interested in, for the sake of my curiosity, is why PHP emits this output in these circumstances.
Is this a PHP bug?
If so, why has it never been fixed?
Or, if not, what is the rationale for this unintuitive output?
Update
It has been pointed out in the comments that PHP 7 behaves as described. This problem therefore only exists between PHP 5.3 (where late static binding was introduced) and 5.6. (demonstration)
I would still be interested to know why it took so long to fix it as it seems like an obvious (and, in some cases, critical) mistake, but maybe it was just standard open-source inertia.
If anyone has anything to add in that regard, I'd be happy to accept an answer that provides the information (e.g. link to/summary of a bug report), otherwise I'll close this down in a day or two.
Ignore the fact that the above code generates strict standards warnings (these are suppressed in the original code-base)
Those warnings should not be supressed. The warning is "Non-static method Foo::DoFoo() should not be called statically".
If you declare DoFoo() as a static method then on PHP 5 get_called_class() will work as you expect it to work (and how it does work in PHP 7).
It appears to me that in certain versions of PHP, the Late Static Binding feature only works correctly on methods declared as static.
I thought that the use of the static keyword in the declaration of a class function meant that you could call the function without an instance of the class using the scope resolution operator (::).
For example:
class Foo
{
public static function static_function() {
return 'x';
}
public function non_static_function() {
return 'y';
}
}
// to call static_function:
echo Foo::static_function();
// to call non_static_function:
$foo = new Foo();
echo $foo->non_static_function();
The PHP.net documentation on static seems to support this idea.
I came across some code yesterday that someone had wrote accessing class functions using the scope resolution operator that had NOT been defined with the static keyword. I was surprised and confused to see this worked.
Given my class defined above, Foo, it turns out you can actually do:
echo Foo::static_function();
echo Foo::non_static_function();
Resulting in output xy without generating any errors or warnings.
If you can access non-static class functions without the static keyword, what is the point in it?
Resulting in output xy without generating any errors or warnings.
No way. The error reporting must have been turned off on that environment. That would have definitely produced a Strict Standards warning notice.
I have TestClass and a public method in it.
I am able to call the same method using :: operator like static method and using an object.
What are the advantages or use of static functions in PHP, if we able to call public functions without creating object of the same class?
<?php
class TestClass {
public function testMethod() {
echo 'Method called';
}
}
TestClass::testMethod();
$classObj = new TestClass();
$classObj->testMethod();
?>
In this case, there is no difference.
However, the point of static functions is to say that some functions don't need an instance of the class in order to be executed. It is possible to call functions statically even if they are not marked as static, but it is technically incorrect to do so. If you have error_reporting(E_ALL) set, it will give you a strict standards error.
This is not because the code won't work, but because it might not.
class TestClass {
private $name = 'Rakesh';
public function doSomething() {
echo "Hi there";
}
public function doSomethingElse() {
echo "Hi there " . $this->name;
}
}
You can call the first function statically and it will work fine. But if you call doSomethingElse statically, it won't work, because it tries to access $this, which is only possible if you have an object.
So we apply the static keyword to doSomething to let (a) PHP and (b) the programmer using the class know that it is possible to call it statically. It's a promise that it will work.
The assumption should be that, if it is not marked as static, you shouldn't call it statically.
PHP's strict standards errors are meant to make your code better, even if it already works. The documentation for the E_STRICT constant says:
Enable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.
In low-level terms, a static function in PHP isn't much different than a member function. The only real difference is that $this isn't provided to a static function.
That means the use of the static keyword is mostly of semantic benefit, as it helps you define the architecture and intended behaviour of your classes.
With that said, you shouldn't abuse the semantics. PHP can (optionally) warn you about those kinds of mistakes, and you should always pay attention to such warnings. The language specification is there for a reason, and it's designed to work in certain ways. If you use static (or any other language feature) incorrectly, then it may not always work as you expect. Future PHP updates or configuration changes could break your code unexpectedly.
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).
For compatibility with PHP 4, if no visibility declaration is used, then the property or method will be treated as if it was declared as public.
Advantages are ...
1>Hash memory will not create ,hence no wastage of Memory (no memory leak problem)
2>
// This makes little sense
Math m = new Math();
int answer = m.sin(45);
// This would make more sense
int answer = Math.sin(45);
It's like a shortchut, one feature more of php. But, to access to their properties you must declare them like constants. For example:
<?php
class Math{
const pi=3.1416;
}
echo Math::pi;
?>
The static keyword was introduced in PHP5, which kinda makes one come to the conclusion that PHP4 didn't support static methods or variables. And yet when I run the following code on PHP 4.4.9 it works without the constructor ever being called.
<?php
class a {
function a() {
echo "CONSTRUCTOR CALLED\r\n";
}
function b($var) {
return $var . 'x';
}
}
print_r(array_map(array('a', 'b'), array('a', 'b')));
You can play around with the code with this PHP "fiddle":
http://sandbox.onlinephpfunctions.com/code/1d6882a8264620a0165d7345791f8680586a869e
Any ideas as to how this is working?
All the static keyword does is tell PHP that a function should be called statically. In actual fact, even the latest versions will let you call any function statically if you want, as this online demo with your code in multiple PHP versions shows.
If you turn error reporting to the max, as in this demo you will see that newer versions of PHP give an E_STRICT message that you're using a function statically that hasn't been declared as such, but otherwise run the code exactly as before.
All that's needed to make a static function call is ::, and that was present and correct in PHP 4. It's really the non-static methods that were tidied up in PHP 5, and further in 5.3
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.