PHP and Static Variables in Object Member Functions - php

Up until today, I thought I had a fairly good grasp of how the static modifier worked. I know that (in laymans terms) a static variable in a function does not 'reset' across calls to that function, and I know that static variables and functions on a class are accessible by calling upon them through the class itself (not an instantiation of the class).
My problem is this: today I found that if I declare a static variable inside of a non-static function on a class, all instantiations of that class share that static variable in separate calls to the member function.
For example:
class A {
public function GetValue() {
static $value = 0;
$value++;
return $value;
}
}
$instance_1 = new A();
$instance_2 = new A();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
echo $instance_2->GetValue();
echo $instance_2->GetValue();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
Notice that the GetValue function is neither declared as static or used in a static way (as in, called on the class itself).
Now, I always assumed that this would output: 121234
Instead, I find that it will output: 123456
Like I say, I would understand this if the static variable $value was inside of a static function. However, with it being inside a non-static function I just assumed that it would only be 'tied' to the function 'within' each individual instantiation.
I guess my question is twofold, then... 1) is this a bug or expected behaviour? 2) do other languages treat these 'static inside non-static' variables the same way, or is this unique to PHP?

This is expected.
This is also the case in C++ (and probably others as well).
You should think of non-static class member functions as if they were just like ordinary functions, but with an implicit $this argument that is automatically provided by the interpreter. (That's exactly how they're implemented in most languages.)

I've copied the following information from this article by Josh Duck: http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/
Static variables have been available since PHP 4 and allow you to define a persistent variable that is only accessible from the current function. This allows you to encapsulate state into a function or method and can eliminate the need for classes where a single function will suffice.
When a static variable is defined inside a class method they will always refer to the class on which the method was called. In doing this they act almost like properties referenced through static, though there are subtle differences.
Static variables can’t preserve the calling class scope. This can be potentially problematic if you have an inherited method containing a static variable that is called from both inside and outside its class.

As far as I know, all languages with static variables treat them this way. Think of static variables as global variables that can only be accessed from a certain scope.

Related

PHP static methods

I understand that static methods have no access to state of instance objects of their class types and hence referencing $this inside them results in an error.But objects can reference static methods using object to member operator ->
$obj->staticMethod();
and can even pass it their state via paramaters.
$para1 = $obj->para1;
$para2 = $obj->para2;
$obj->staticMethod($para1, $para2);
How is this last example possible when statics are resolved in static context. If someone can explain to me the general behaviour of statics in php code. you can even talk about C related concepts if it will help.
Since you state that you already understand what static means, I'll skip over that.
However, it may still be good to reference PHP's documentation on the static keyword. In particular the following two alerts are important (and hard to glance over, really).
Caution In PHP 5, calling non-static methods statically generates an E_STRICT level warning.
And this one (italic emphasis mine).
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.
So, to cut a long story short: yes, your example will run (for now), because the PHP interpreter will try to fix up your mistake for you. You should however never do this. What the PHP interpreter will do is:
Say your $obj is of type Foo. Then it will read
$obj->staticMethod($para1, $para2);
conclude that staticMethod is static and instead execute
Foo::staticMethod($para1, $para2);
It is of course perfectly fine to pass parameters that are properties of an instance of Foo. It doesn't matter to staticMethod where the parameters come from.
To elaborate a bit more on why this works, while using $this in a static method is not allowed.
You can think of normal methods as static functions that have one extra: they receive an implicit parameter $this. The value of $this is simply the object on which the method is called. Thus, $obj->do($a, $b, $c) is equivalent to calling Foo::do($obj, $a, $b, $c) and naming the first argument of do, $this. This is convenient, because we can now easily define methods that work on an instance of an object without having to explicitly state over and over again that this instance is a parameter of our methods. Great.
Now back to static functions. The only difference with normal methods is that they do not receive this implicit $this parameter. Thus, using $this inside of them is invalid. Not because it is forbidden, but because it does not reference anything. PHP does not (and cannot) have a clue what $this should refer to.
Another way to look at it. Say that our Foo class has two properties: $para1 and $para2, both numbers. Say that you write a method that returns the sum of these numbers. One way is to do this:
public static function sum($para1, $para2) {
return $para1 + $para2;
}
Great. Works. However, it is annoying to have to call it like this
$sum = Foo::sum($obj->para1, $obj->para2);
So, this is what methods are for!
public function sum(/* implicit $this parameter */) {
// write looking up the properties once inside the function, instead
// of having to write it every time we call the function!
return $this->para1 + $this->para2;
}
// ...
$sum = $obj->sum(); // $obj is passed implicitly as $this
Because static functions do not receive an implicit $this parameter, using $this inside of them is like trying to use $undefined when you have never defined it. Thus, invalid.
Static means class members in simple terms , A static data member is accessible within a class regardless object is created or not . The static function are also functions dedicated to whole class . Static function works with static data only bit it can sometimes vary . Though statics are class dedicated, you can access them using object. It is allowed in all languages. Why ? Because of feasibility . If an object is not being able to access static members , that is a limitation.

using functions inside constructors php

In an effort to keep my code clean, I am attempting to replace a whole bunch of code in my constructor with a function. I believe I am calling the function correctly but i'm not able to assign values to the variables as intended.
public function __construct($docID) {
self::getDocumentInfo($docID);
self::getTranscriptionInfo($docID);
}
private static function getTranscriptionInfo($docID) {
$this->documentTranscription = 5;
}
Im getting an error "PHP Fatal error: Using $this when not in object context in ...". This is simplified for postings purpose, but would it be better just have a very large constructor and skip the functions all together? Or is their a better way to assign values?
A static method is not a part of the class instance. The static keyword means the method can be called within your class but it won't have any of the instance variables.
Remove the static keyword and change this:
self::getDocumentInfo($docID);
self::getTranscriptionInfo($docID);
to this:
$this->getDocumentInfo($docID);
$this->getTranscriptionInfo($docID);
Using $this means it will be calling it within the right instance context.
Some info the static keyword (added emphasis in italics):
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static cannot 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.
Source
http://php.net/manual/en/language.oop5.static.php

Are there best practices for working with static members in PHP?

PHP allows use of static member functions and variables, since 5.3 including late static bindings:
class StaticClass {
public static $staticVar;
...
}
$o = new StaticClass();
Currently, there are various options to access those static members:
$o->staticVar; // as instance variable/ function
$o::staticVar; // as class variable/ function
Other options exist for accessing members from inside the class:
self::$staticVar; // explicitly showing static usage of variable/ function
static::$staticVar; // allowing late static binding
Restructuring some existing classes that make some use of static members I've asked myself if there are best practices for working with static members in PHP?
Well, obviously, they all do different things.
$o->staticVar
This is invalid, since you cannot/should not access static properties with the instance property syntax.
StaticClass::$staticVar
This very plainly accesses a specific static variable on a very specific class.
$o::$staticVar
This accesses the static variable on the class that $o is an instance of. It's mostly used as a shorthand for the previous method and is equivalent in all respects. Obviously though, which class is used exactly depends on what class $o is an instance of.
self::$staticVar
This can be used only inside a class, and will always refer to the class that it's written in. It's a good idea to use this inside a class instead of StaticClass::$staticVar if the class refers to itself, since you don't need to worry about anything if you change the class name later. E.g.:
class Foo {
protected static $bar = 42;
public function baz() {
self::$bar; // good
Foo::$bar // the same, but should be avoided because it repeats the class name
}
}
static::$staticVar
This can also only be used inside a class and is basically the same as self above, but resolves with late static binding and may hence refer to a child class.
What the "best practice" is is debatable. I'd say you should always be as specific as necessary, but no more. $o::$staticVar and static::$staticVar both allow the class to vary through child classes, while self::$staticVar and StaticClass::$staticVar do not. Following the open/closed principle, it's a good idea to use the former, more variable method to allow for extensions.
Properties, both static and non-static, should also not be public to not break encapsulation.
Also see How Not To Kill Your Testability Using Statics.
First of all, don't use $this->staticVar. I am unsure when this changed (I believe PHP 5.4), but in recent versions it is no longer possible to retrieve static variables this way.
As for using late static binding, don't use it if you don't need it. The reason to use it would be if you plan to use inheritance and expect to change the value of the static variable in a derived class.

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

Difference in Class Calling PHP

With learning fuelPHP, I am introduced on calling classes using scope resolution, or :: in sense. Typically, when we call a method in a class we do this ...
$myclass = new myclass();
$myclass->mymethod();
On fuel, methods are usually called in this manner ...
myclass::mymethod();
I was wondering if there are any difference between the two? Is the scope resolution is something of an update on 5.3 as well ... if not, which one is ideal, or when should I use these.
Thanks.
The scope resolution operator is used to access either class constants like ::const, static variables like ::$var or call static methods like ::method().
See http://php.net/manual/en/language.oop5.static.php
Static methods can be called without having an instance of the class they are defined in. They're defined in that class with the static keyword.
For example, one of CakePHP's static methods is defined like this:
class ClassRegistry {
// ...
public static function &getInstance() {
// ...
}
}
... which you can call like ClassRegistry::getInstance().
Without the static keyword, you'd need an instance of the ClassRegistry class to call that function.
You can read more here, especially about why using static methods in your own code can sometimes be a bad idea: http://kore-nordmann.de/blog/0103_static_considered_harmful.html
I am not sure how would myclass::mymethod(); work, since I use such syntax only when I am calling a STATIC class.
MyClass::DoSomething();
would call a static method named DoSomething()
while
$instance = new MyClass();
$instance->DoSomething();
would call the instance method.
I have not tested it but I believe you will run into an error if you do $instance::DoSomething()
I think the best way to understand why there is a static call and what it does behind the scene is to check this FuelPHP blog's entry: http://fuelphp.com/blog/2011/05/why-did-you-do-that
The obvious difference is that the first solution $myObject->myMethod() it's a dynamic call : you need an instance to execute myMethod().
In the second solution, MyClass::myMethod() is a static call. The class acts as a sort of namespace where a function belong. You don't need an instance for that.

Categories