what's the point of declaring static functions in PHP? - php

So in PHP you can have
Class A{
function B(){}
}
and you can call this as if it were a static function:
A::B();
My question is...if I can do this, then why should I ever declare the function B() as static since doing so makes $this unavailable, so there's less flexibility, so you have everything to lose but nothing to gain...
or is there an advantage of declaring the function as static that I'm not aware of?
also I heard that "static calling of non static methods" are "deprecated"....what does that exactly mean especially in relation to this scenario? is calling A::B() when B() is not declared static something that I shouldn't be doing? if so, why is that the case?

Because PHP tends to be a bit loosy-goosy around strictness (?) these sort of things work. The fact that they are deprecated means that sometime in a future release, it is likely not to work anymore. So if you are calling a non-static function in a static context, your program may break in a future PHP upgrade.
As for using it right now - the advantage to declaring a function as static is that you are deciding right there how that function should be used. If you intend to use a function in a static context, you can't use $this anyway, so you are better of just being clear on what you plan to do. If you want to use the function statically, make it static. If you don't, then don't. If you want to use a function both statically and non-statically, then please recheck your requirements :P

For compatibility mode. Now calling non-static methods statically generates an E_STRICT level warning.
Why static and not instantiate the object? Each programmer will tell you a reason. I particulary preffer instantiate object than use static methods. It's clear, traceable and more reusable.
I did a test bench and the difference was minimal between instantiate and call a method than call it staticaly.
Tip: if you foresee calling methods statically defines them as well;-)

First off, you couldn't do stuff like that in your post in a strict typed language like Java. Java code doesn't compile, if you call non-static stuff in a static context. PHP is not that strict on these things (yet), but still you shouldn't do things just because you can, although it's bad practice and in some languages even 'incorrect' practice.
There sure are advantages using static methods. And it's not quite right that you gain nothing or even lose flexibility. Let's have an example:
class A {
private static $prop_a = 'property_a';
public static function b() {
echo 'called b()';
echo self::$prop_a;
$A = new A();
$A->c();
}
public function c() {
echo 'called c()';
}
}
Now we can call the class this way:
A::b();
which outputs
called_b
property_a
called_c
But you can do the same with:
$a = new A();
$a->b();
$a->c();
c() is executed twice now, but you get the idea. Within your class, you can instanciate the class itself and work with it like with a regular object. But from outside, it's simply one line of code while it's 3 lines using the non-static way. Pretty cool, huh?
And as you see, you can use the static function in a non-static context, which means, you can declare your method static, but if you instanciate your class, you can simply call it like a regular method. Sounds pretty flexible to me ;)
And no, you can't use $this in a static context, but that's what self is for ;)

If it is a static function you don't have to instantiate the class in order to use the method.
Class A {
static function hello($arg)
{
echo 'Hello, ' . $arg;
}
}
A::hello('world');
VS
Class A {
public function hello($arg)
{
echo 'Hello, ' . $arg;
}
}
$a = new A;
$a->hello('world');
The important thing here is the instantiation of the object. After you've instantiated an object, it can be manipulated, and calling your methods may yield unexpected results. If your values and functions are statically declared in the class, they cannot be modified at the time you call the function.
This is not to say they you should always use static methods either. take the following example.
class My_math {
static function pi()
{
return 3.14
}
}
class My_bakery {
private var $pie;
function set_pie($pie)
{
$this->pie = $pie;
}
function pie()
{
echo "I made you a " . $this->pie . "pie";
}
}
I've made My_Math return a constant value, because I know pi doesn't change. But in My_bakery, some days I want blueberry pie and some days I want peach pie.

Related

Method invocation in PHP

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;
?>

When is necessary to use static methods?

I thought usually we use static method because we do not need to instantiate objects. and we can use className::staticFunction to call static method, bub today found:
test1.php
<?php
class Foo {
static public function helloWorld() {
print "Hello world " ;
}
}
Foo::helloWorld();
test2.php
<?php
class Foo {
public function helloWorld() {
print "Hello world " ;
}
}
Foo::helloWorld();
Question:
Both of above scripts work. We did not declare function as static, we can still use className::staticFunction to call the function. Why do we need use static methods?
We did not declare function as static, we can still use className::staticFunction
What you probably didn't notice is that PHP complains about the second type of invocation:
PHP Strict Standards: Non-static method Foo::helloWorld() should not be called statically in php shell code on line 1
Strict Standards: Non-static method Foo::helloWorld() should not be called statically in php shell code on line 1
To make these notices visible you need to set the value of error_reporting to -1, either using ini_set() or via the php.ini configuration file; btw, this is recommended during development.
Conclusion
A function that's called statically should be declared as static function xyz().
Update
Btw, using the scope resolution operator :: doesn't necessarily mean you're making a static call; consider this example:
class Foo
{
public function helloWorld()
{
print "Hello world ";
}
public function doSomething()
{
self::helloWorld();
}
}
$f = new Foo;
$f->doSomething();
This works because using self:: as opposed to Foo:: doesn't change the invocation "mode" (unless the method you're calling is defined as static).
The "problem" with static methods is the way they're called:
Foo::bar();
Any call to a static method is by necessity hardcoded and cannot easily be substituted. Compare with:
$foo->bar();
$foo is a variable here, meaning the exact object and implementation of bar() can be substituted. This is important for and the basis of dependency injection.
You'd use a static method for:
first and foremost cases where you don't need individual object instances
anything you need to do before an object can be instantiated
alternative object constructors, for instance DateTime::createFromFormat() instead of new DateTime
idempotent utility functions which you are 100% sure never need to be substituted or mocked
You may use static functions in other scenarios here and there, but these are the main points. You need to be aware that declaring a method static means you need to call it statically, which means its call-time use cannot really be altered. For a long treaty on this subject, read How Not To Kill Your Testability Using Statics.
Well a simply hello world program might not be able to show a big difference is the usage of static vs not but take a look at this class
class foo {
private $a = 1;
private static $b = 2;
public function foobar()
{
echo $this->a;
}
}
in this above class if you call foobar statically then $this->a will not resolve.
PHP is funny like that, but I'll usually have a utilities class which takes arguments of things to perform logic on and return. Stuff like this doesn't need an instantiated class. It's up to the user/developer to correctly call methods (read: use the correct method accessors).
When you are working on a large OOP based project, you’ll no doubt be working with many classes (both parent and child classes). An unfortunate consequence of this is that in order to access elements from different classes, they must manually be passed through each class (or worse, storing an instance in a global variable). This can be painstakingly frustrating and can lead to messy code and overall bad project design. Thankfully, static elements are accessible from any context (i.e. anywhere in your script), so you can access these methods without needing to pass an instance of the class from object to object.
As you don’t need to declare an object instance to access static elements, you can be saved from unnecessary declarations to access seemingly simple functions.
Static elements are available in every instance of a class, so you can set values that you want to be available to all members of a type.
From the above example test1.php
helloworld() function cannot be overriden or overloaded since you have added a static keyword.
However in the second example, test2.php
helloworld() function can be overloaded and overriden
Illustration:1 (Works)
<?php
class Foo {
function helloWorld() {
print "Hello world " ;
}
}
class Foo1 extends Foo
{
function helloWorld()
{
echo "Foo's World";
}
}
$Foo1 = new Foo1();
$Foo1->helloWorld(); //Foo's World
Illustration:2 (Fails)
Cannot make static method Foo::helloWorld() non static
<?php
class Foo {
static function helloWorld() {
print "Hello world " ;
}
}
class Foo1 extends Foo
{
function helloWorld()
{
echo "Foo's World";
}
}
$Foo1 = new Foo1();
$Foo1->helloWorld();

__callStatic is not called?

I know the following could potentially create problems elsewhere and is probably bad design, but I still would like to know why this fails (for my own edification):
class Test {
// singleton
private function __construct(){}
private static $i;
public static function instance(){
if(!self::$i){
self::$i = new Test();
}
return self::$i;
}
// pass static requests to the instance
public static function __callStatic($method, $parameters){
return call_user_func_array(array(self::instance(), $method), $parameters);
}
private $someVar = 1;
public function getSomeVar(){
return $this->someVar;
}
}
print Test::getSomeVar();
The error is Using $this when not in object context
Obviously $this is unavailable from a static method, but the static method is handing it off to an instance method invokation via call_user_func_array, which should make $this the instance...
/EDIT
I'm aware that $this is not available in static context. However, this works:
print call_user_func_array(array(Test::instance(), 'getSomeVar'), array());
Which is exactly what's happening in the __callStatic overload, so something's amiss...
/EDIT 2
scope is definitely getting handled strangely. if you pull the singleton instance to any other class, it works as expected:
class Test {
// singleton
private function __construct(){}
private static $i;
public static function instance(){
if(!self::$i){
self::$i = new Blah();
}
return self::$i;
}
// pass static requests to the instance
public static function __callStatic($method, $parameters){
return call_user_func_array(array(static::instance(), $method), $parameters);
}
}
class Blah {
private $someVar = 1;
public function getSomeVar(){
return $this->someVar;
}
}
print Test::getSomeVar();
You can not staticfy your object methods through __callStatic calls in PHP. It will only be invoked when the method so far does not exist (incl. not being visible from the calling context). In your case Test::getSomeVar() is already defined.
Because of backwards compatibility, PHP does not check if only a static method exists, but actually if generally a method exists.
In your case you are calling the non-static method statically, so $this is not defined because __callStatic has not been invoked. If you would have enabled warnings and notices to the highest level (recommended for development), PHP would have warned you about that.
The correct usage therefore is:
echo Test::instance()->getSomeVar();
As with any other implementation of a Singleton.
So you are just using __callStatic wrong, it only works for methods not yet defined. Choose another tool/design for the job, like the aggregation example you use with your Blah class.
A further note:
You should normally prevent to use any static context in PHP anyway, especially as you exploit a lot of magic functionality here, too, which is another smell. It looks like you have a pile of design issues before you even finished your code. You will only increase the likelihood to run into hard to debug and maintain code with all this. But that just so you do not say in some time you have not been warned.
See Who needs singletons? in case you want to learn more.
It doesn't work like that. In a static call you have no instance, no object and no $this. Call static only works with static methods in which $this is unavailable.
The documentation says:
__callStatic() is triggered when invoking inaccessible methods in a static context.
I know this is not the answer you were hoping for. As you have anticipated: you don't need of overloading in PHP, just create your app and leave this thing out.

php static methods question

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.

In PHP, is it a problem to call a static class function using the -> dereferencer

I am using PHP 5.2
I have the following code:
class MyClass {
public function __construct() {}
public static function stuff() {
echo 'This is static! <br />';
}
}
$myClass = new MyClass();
MyClass::stuff(); // Reference by class.
$myClass->stuff(); // Reference by instance of class.
The output works in both cases here is the output:
This is static!
This is static!
Is there a problem using the 2nd way of referencing versus the 1st?
Since I am not allowed to have a non-static function with the same signature as the static one above that won't be an issue. I want the function to be static because there is also a speed boost when using static functions.
Am I missing anything or is the only issue here regarding the semantics of how the -> dereference syntax does not indicate this is a static function?
The docs explicitly say it's okay:
A property declared as static can not
be accessed with an instantiated class
object (though a static method can).
However, it's clearer to use ::. I also question the idea that the static method is significantly faster, particularly when no instance fields are used. You should do profiling before you start altering the semantics of your application for performance.

Categories