Static methods in PHP: what for? - php

I'm terribly sorry for asking such a silly question, but I'm new to OOP and trying to figure out what static methods are used for. Here's an example PHP code:
class foo{
static function bar(){
//do something here
}
public function baz(){
//do something different
}
}
Documentation says:
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class
However, the both methods from the example above can be accessed from outside of the class with like:
foo::bar();
foo::baz();
It works (at least for PHP 5.3 that I'm using) without instantiation of the class foo.
So, what's the point of using static methods, if the both ways work??
Forgive me once again for such a noob question. I've been really trying hard to find it out myself with no success. Thanks.

Static methods are globally available tools (helpers) and are often overused. Static methods are death to testability and should be avoided almost completely.
Their advantage as well as disadvantage is that they live in the global scope, you can call them from anywhere, which makes them code smells in most cases because they break encapsulation.
On language level, as Kolink mentions, things like mysqli:real_escape_string() make sense of course, but on application level, you usually don't want to pollute your global scope and break encapsulation like that. You'd rather think of what tools you really need and where and inject them bundled into meaningful groups (classes).
Your foo::baz() raises a warning in strict mode (which should always be on):
Strict standards: Non-static method foo:baz() should
not be called statically in yourfile.php on line x

Generally they can be used for "helper" functions, such as mysqli::real_escape_string(), where the function is relevant to the class but not locked to any specific instance of it.

Related

Why does PHP support calling static functions as non-static member methods?

Code beforehand fully valid code from 5.0.0 (without E_STRICT or E_DEPRECATED)
class A{
static public function b() {
}
public function c(){
$this->b();
}
}
$d = new A();
$d->c();
$d->b();
It's looks like inconsistent behaviour because you cannot use static properties from instance.
The PHP way is to steal and borrow from other languages whenever
possible ...
But I cannot find any programming language that supports similar behavior.
Why does PHP support it? What is the point of calling static methods as non-static?
Some explanation from support: Expected behavior
Actually, C++ and Java support this. It seems the PHP developers, after discussion, decided on implementation to match them.
After a bit of digging, I found this thread from February 2004, which is essentially their discussion about the implementation choices. Important tidbits from the discussion:
From Cristiano Duarte:
C++ allows $a->bar() when bar() is a static method (yes, it is called
in a static context there too).
IMO, there should be no error, warning or notice here.
I Agree. PHP is fine the way it is.
From Art:
Regardless of the final implementation, I think access to static methods and
static class variables should be consistent. Currently, you cannot access a
class variable via an object instance.
And for what it's worth, I see no reason why static methods cannot be called
from objects. Follow Java/C++ in this case.
Ultimately, a final decision From Wez:
Please drop this thread; we're not changing the behaviour of static.
It looks to me that it is just a syntax consideration here. Nothing here is inconsistent with the logic of static methods, it's still impossible to use $this in your static function, and therefore the function will not have access to instance properties or methods. It feels more like a shortcut than an inconsistency to me.
I have no use case of that, but I guess someone may find it useful with objects created with dynamic class names: you can still use the function even if you don't know it's class name.

What is the difference between static functions and function outside of a class in PHP?

I need to have method to get something from a database, but I don't understand the difference between static and normal functions in PHP.
Example code
class Item {
public static function getDetail($arg) {
$detail = $this->findProductId($arg);
return $detail;
}
private function findProductId($id) {
//find product_id in database where id = $arg
//return detail of product
}
}
and function outside of a class
function getDetail($arg) {
$detail = findProductId($arg);
return $detail;
}
If I use $item = Item::getDetail(15); and $item = getDetail(15); — they're the same.
What is the difference between static and function outside of a class?
If they are difference, How to use static function and function outside of a class? (I'd appreciate a really simple example.)
What are the performance properties between static and function outside of a class? Which is better?
1) What is difference between static function and normal function
While they are functions, I'd prefer to call them methods of a given class. One is a static method and the other is an instance method.
Static Method: $item = Item::getDetail(15);
Instance Method: $item = getDetail(15);
(refer to FuzzyTree's correct syntax above in the comments, however.)
2) How to use static function and normal function (if you simple exemplify is good)
Static means you do not have to instantiate (declare an object reference). That is, you can simply use the method. So, in your example, while the answer may be the same, the way you called that method/function is different, as you noted above.
In Java, for example, you have the Math class. It does not require instantiation to use, and in fact you cannot that I know of because its constructor is private. You can simply use a method by referencing the class and the method name you wish to use,
Math.pow(d1, d2); //no instantiation needed
in PHP this might be,
MyClass::pow(d1,d2); //no instantiation needed
Java: when to use static methods
3) Ask performance between static function and normal function. Which is better?
Better is a matter of your design. If you have to create an object every time you want to do the power of a number that will create more memoryusage than simply using the class directly. I do not have benchmark proof, but it seem logical since you are not handling the method the same way in memory. I do not think it will matter in real world unless you are doing a lot of complicated actions.
Performance of static methods vs instance methods
might also interest you.
I'm assuming you're asking about the difference between a static method:
class Item {
public static function getDetail($arg){}
}
And a function written outside of a class definition:
function getDetail($arg){}
Static methods should be used over functions written outside of a class for organizational reasons. In an application with many files, having Item::getDetails($arg) will give a hint of where that function is defined. Also, having just a function written outside of a class runs the risk of name collision, if you start writing many functions outside classes.
Especially if you are writing in the OOP style, you should be using static methods over functions outside of class definitions, but I think even in general, using static methods is the better way to go.
The difference about static and non static functions is a big answer and we have to look at Object Oriented Programming (OOP) in general.
OOP in general, as you should know, is about Classes and Object, a class describe and creates objects based of it's description.
If you tell the class to contain the function "A" the object will have a callable function "A" who will have access to the objects parameters.
However if you tell the class to have a static function you tell the class to have a callable function WITHOUT instantiate an object.
Confusing? Can be at first and hard to understand why it's sometimes needed when you take your first OOP steps. Static functions is a good way to share info about classes without the need to make an object.
An analgy would be:
Take the class Car and the object BMW.
the objects functions is about THE BMW, a static functions is about cars in general.
As of performance, it's not about performance at all, it's about design patterns. So performance-wise there is nothing to gain if the functions is static or non static.
1.Entire difference is, you don't get $this supplied inside the static function. If you try to use $this, you'll get a Fatal error:
Static functions are associated with the class, not an instance of the class
and You will get an E_strict warning in the second case.
2.Now static calling of non-static methods works but is deprecated. so use normal function.
3.Technically speaking Static methods and variables are useful when you want to share
information between objects of a class, or want to represent something
that's related to the class itself, not any particular object.
For some reason, PHP allows you to call non-static and static methods
interchangeably,So performance wise or in whatever way you may say just use a normal function.Static is not going to help you at all
The difference between static and non static is that you can access a static method without having an instance of the class.
$item = getDetail(15); shouldn't work because detDetail is a method in a class and not a function.
Performance of Static Methods
There used to be a big penalty when calling a static method - but it's fixed in 5.4.0. See http://www.micro-optimization.com/global-function-vs-static-method
From what the other guy said, if it uses more memory one way versus the other it will absolutely cause a performance difference. If you're using so much memory to the point of going into GC, it can cause queuing of processes due to backup, due to gc and take the whole system down potentially if it's an enterprise system with thousands of concurrent users. It may depend on the scale of the application.
We should never be of the opinion that a change in memory utilization is "minor". It's never minor in big systems...

Is good to use static variable inside a PHP class method

I am doing a class "Container" to hold all my model/service instances, the class is a singleton.
Consider the following code portion (from a CodeIgniter project):
public function getReviewModel()
{
static $loaded = false;
if (!$loaded)
{
$this->load->model('review_model');
$loaded = true;
}
return $this->review_model;
}
I am wondering if is still ok to use static inside method like this or should I use only class property (I mean about performance and coding standard) ?
In your example, nothing prevents the programmer to instanciate the class more than once (with dire results), so it is rather a confusing bit of code.
Static variables have their uses, be them local to a function or defined at class level.
Especially in PHP scripts, when the output is often a single piece of data that can conveniently be handled as a class defining only static properties and methods.
That would be a true, foolproof singleton class.
Since mistaking a static variable for a dynamic one is a common pitfall, I tend to favor static class variables to avoid the confusion (i.e. the self::$... syntax makes them stand out clearly).
General consensus as far as statics are concerned in PHP is: Avoid, if at all possible. And yes, 99% of the time, it is possible to avoid statics.
Singletons should be avoided 100% of the time. For reasons you can find here and virtually everywhere else on the web. Singletons are like communism: sounds like a nice idea, but when put in to practice, it turns out there's one or two things you didn't anticipate.
A Singletons' main purpouse is to retain state, but PHP itself is stateless, so come the next request, the singleton needs to be re-initialized anyway.
If I write getters like yours, I tend to create them in a lazy-load kind of way:
class Example
{
private $reviewModel = null;//create property
public function getReviewModel()
{
if ($this->reviewModel === null)
{//load once the method is called, the first time
$this->reviewModel = $this->load->model('review_model');
}
return $this->reviewModel;
}
}
This basically does the same thing, without using statics. Because I'm using a property, I still retain the instance, so if the getReviewModel method is called again, the load->model call is skipped, just as it would be using a static.
However, since you're asking about performance as well as coding standards: statics are marginally slower than instance properties: Each instance has a HashTable containing for its properties, and a pointer to its definition. Statics reside in the latter, because they are shared by all instances, therefore a static property requires extra lookup work:
instance -> HashTable -> property
instance -> definition -> HashTable -> property
This isn't the full story, check answer + links here, but basically: the route to a static propery is longer.
As for coding standards: They exist, though still unofficial, most major players subscribe to them, and so should you: PHP-FIG
Things like $this->_protectedProperty; don't comply with the PSR-2 standard, for example, which states, quite unequivocally:
Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.

Should a function be used in both static and object context

In my company's codebase, i see functions used in both static and object context. For e.g. a class A has a function b() which is called both using A::b() and/or object_of_type_A->b(). I know this throws an error if strict is turned on. But I wanted to know if this is a bad practice and if yes, then why? Thanks for any answers.
Let me know if I don't make sense anywhere. I would be happy to clarify.
I'm not a php guy, but this sounds just like Java, where it's allowed but discouraged.
If it's static, I would strongly recommend only calling it in a static way. Otherwise it looks like it depends on the state of the object you're supposedly calling it on.
In Java the best example of this is Thread.sleep(). It's a static method which puts the current thread to sleep, always. But look at this code:
Thread t = new Thread(someTask);
t.start();
t.sleep(1000);
What does it look like that code is doing? It appears to be putting the other thread to sleep, whereas in fact it'll be the current thread that's sleeping. When you change it to a plain static call, it's more obvious:
Thread.sleep(1000);
That doesn't refer to t, so must be about the current thread.
Unless there's something specific to php where calling the static method via a variable gives you some sort of polymorphism, I suggest you stick to calling it in the static way. The fact that strict mode tells you to do this is a pretty strong hint, IMO :)
Here's some test code:
<?php
error_reporting(E_ALL | E_STRICT);
class Foo{
public function a(){
}
public static function b(){
}
}
$MyFoo = new Foo;
Foo::a(); // Strict Standards: Non-static method Foo::a() should not be called statically
Foo::b();
$MyFoo->a();
$MyFoo->b(); // No complaints
?>
PHP/5.3 warns about static calls to non-static methods, which is fine since they are subject to failure as soon as you want to access $this. But it does not complain about object context calls to static functions: there's nothing that can go wrong. This behaviour is documented:
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)
[...]
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, as far as PHP is concerned, what you found in the code base is not wrong. However, I think it's slightly confusing.
There is 'currently' no harm in using it either way except of course when called as a static function you can't access the $this member.
The reason it errors in strict is because not writing your code to strict standards can result in errors occurring due to a lack of diligence. in the future it may also cause your code to break. a static function has no $this member and it may break parameter passing.
Play it safe only call static functions with A::b() type calls.
DC
Regarding accessing $this in a static function I found something a bit strange a while back (might be changed in later versions of PHP though, think I ran 5.2 or something).
You can read about it here but it's in swedish. But use google translate and it should be understandable.
http://www.phpportalen.net/viewtopic.php?p=560080#560080

Why does PHP 5.2+ disallow abstract static class methods?

After enabling strict warnings in PHP 5.2, I saw a load of strict standards warnings from a project that was originally written without strict warnings:
Strict Standards: Static function Program::getSelectSQL() should not be abstract in Program.class.inc
The function in question belongs to an abstract parent class Program and is declared abstract static because it should be implemented in its child classes, such as TVProgram.
I did find references to this change here:
Dropped abstract static class functions. Due to an oversight, PHP 5.0.x and 5.1.x allowed abstract static functions in classes. As of PHP 5.2.x, only interfaces can have them.
My question is: can someone explain in a clear way why there shouldn't be an abstract static function in PHP?
It's a long, sad story.
When PHP 5.2 first introduced this warning, late static bindings weren't yet in the language. In case you're not familiar with late static bindings, note that code like this doesn't work the way you might expect:
<?php
abstract class ParentClass {
static function foo() {
echo "I'm gonna do bar()";
self::bar();
}
abstract static function bar();
}
class ChildClass extends ParentClass {
static function bar() {
echo "Hello, World!";
}
}
ChildClass::foo();
Leaving aside the strict mode warning, the code above doesn't work. The self::bar() call in foo() explicitly refers to the bar() method of ParentClass, even when foo() is called as a method of ChildClass. If you try to run this code with strict mode off, you'll see "PHP Fatal error: Cannot call abstract method ParentClass::bar()".
Given this, abstract static methods in PHP 5.2 were useless. The entire point of using an abstract method is that you can write code that calls the method without knowing what implementation it's going to be calling - and then provide different implementations on different child classes. But since PHP 5.2 offers no clean way to write a method of a parent class that calls a static method of the child class on which it is called, this usage of abstract static methods isn't possible. Hence any usage of abstract static in PHP 5.2 is bad code, probably inspired by a misunderstanding of how the self keyword works. It was entirely reasonable to throw a warning over this.
But then PHP 5.3 came along added in the ability to refer to the class on which a method was called via the static keyword (unlike the self keyword, which always refers to the class in which the method was defined). If you change self::bar() to static::bar() in my example above, it works fine in PHP 5.3 and above. You can read more about self vs static at New self vs. new static.
With the static keyword added, the clear argument for having abstract static throw a warning was gone. Late static bindings' main purpose was to allow methods defined in a parent class to call static methods that would be defined in child classes; allowing abstract static methods seems reasonable and consistent given the existence late static bindings.
You could still, I guess, make a case for keeping the warning. For instance, you could argue that since PHP lets you call static methods of abstract classes, in my example above (even after fixing it by replacing self with static) you're exposing a public method ParentClass::foo() which is broken and that you don't really want to expose. Using a non-static class - that is, making all the methods instance methods and making the children of ParentClass all be singletons or something - would solve this problem, since ParentClass, being abstract, can't be instantiated and so its instance methods can't be called. I think this argument is weak (because I think exposing ParentClass::foo() isn't a big deal and using singletons instead of static classes is often needlessly verbose and ugly), but you might reasonably disagree - it's a somewhat subjective call.
So based upon this argument, the PHP devs kept the warning in the language, right?
Uh, not exactly.
PHP bug report 53081, linked above, called for the warning to be dropped since the addition of the static::foo() construct had made abstract static methods reasonable and useful. Rasmus Lerdorf (creator of PHP) starts off by labelling the request as bogus and goes through a long chain of bad reasoning to try to justify the warning. Then, finally, this exchange takes place:
Giorgio
i know, but:
abstract class cA
{
//static function A(){self::B();} error, undefined method
static function A(){static::B();} // good
abstract static function B();
}
class cB extends cA
{
static function B(){echo "ok";}
}
cB::A();
Rasmus
Right, that is exactly how it should work.
Giorgio
but it is not allowed :(
Rasmus
What's not allowed?
abstract class cA {
static function A(){static::B();}
abstract static function B();
}
class cB extends cA {
static function B(){echo "ok";}
}
cB::A();
This works fine. You obviously can't call self::B(), but static::B()
is fine.
The claim by Rasmus that the code in his example "works fine" is false; as you know, it throws a strict mode warning. I guess he was testing without strict mode turned on. Regardless, a confused Rasmus left the request erroneously closed as "bogus".
And that's why the warning is still in the language. This may not be an entirely satisfying explanation - you probably came here hoping there was a rational justification of the warning. Unfortunately, in the real world, sometimes choices are born from mundane mistakes and bad reasoning rather than from rational decision-making. This is simply one of those times.
Luckily, the estimable Nikita Popov has removed the warning from the language in PHP 7 as part of PHP RFC: Reclassify E_STRICT notices. Ultimately, sanity has prevailed, and once PHP 7 is released we can all happily use abstract static without receiving this silly warning.
static methods belong to the class that declared them. When extending the class, you may create a static method of the same name, but you are not in fact implementing a static abstract method.
Same goes for extending any class with static methods. If you extend that class and create a static method of the same signature, you are not actually overriding the superclass's static method
EDIT (Sept. 16th, 2009)
Update on this. Running PHP 5.3, I see abstract static is back, for good or ill. (see http://php.net/lsb for more info)
CORRECTION (by philfreo)
abstract static is still not allowed in PHP 5.3, LSB is related but different.
There is a very simple work around for this issue, which actually makes sense from a design point of view. As Jonathan wrote:
Same goes for extending any class with static methods. If you extend that class and create a static method of the same signature, you are not actually overriding the superclass's static method
So, as a work around you could do this:
<?php
abstract class MyFoo implements iMyFoo {
public static final function factory($type, $someData) {
// don't forget checking and do whatever else you would
// like to do inside a factory method
$class = get_called_class()."_".$type;
$inst = $class::getInstance($someData);
return $inst;
}
}
interface iMyFoo {
static function factory($type, $someData);
static function getInstance();
function getSomeData();
}
?>
And now you enforce that any class subclassing MyFoo implements a getInstance static method, and a public getSomeData method. And if you don't subclass MyFoo, you can still implement iMyFoo to create a class with similar functionality.
I know this is old but....
Why not just throw an exception the that parent class's static method, that way if you don't override it the exception is caused.
I would argue that an abstract class/interface could be seen as a contract between programmers. It deals more with how things should look/ behave like and not implement actual functionality. As seen in php5.0 and 5.1.x it's not a natural law that prevents the php developers from doing it, but the urge to go along with other OO design patterns in other languages. Basically these ideas try to prevent unexpected behavior, if one is already familiar with other languages.
I don't see any reason to forbid static abstract functions. The best argument that there is no reason to forbid them is, that they are allowed in Java.
The questions are:
- Are the technically feasable? - Yes, since the existed in PHP 5.2 and they exist in Java.
So whe CAN do it. SHOULD we do it?
- Do they make sense? Yes. It makes sense to implement an part of a class and leave another part of a class to the user. It makes sense in non-static functions, why shouldn't it make sense for static functions? One use of static functions are classes where there must not be more than one instance (singletons). For example an encryption engine. It does not need to exist in several instances and there are reasons to prevent this - for example, you have to protect only one part of the memory against intruders. So it makes perfect sense to implement one part of the engine and leave the encryption algorithm to the user.
This is only one example. If you are accustomed to use static functions you'll find lots more.
In php 5.4+ use trait:
trait StaticExample {
public static function instance () {
return new self;
}
}
and in your class put at the beggining:
use StaticExample;
Look into PHP's 'Late Static Binding' issues. If you're putting static methods on abstract classes, you're probably going to run into it sooner rather than later. It makes sense that the strict warnings are telling you to avoid using broken language features.

Categories