Static variables in PHP - php

I have found different information regarding static variables in PHP but nothing that actually explains what it is and how it really works.
I have read that when used within a class that a static property cannot be used by any object instantiated by that class and that a static method can be used by an object instantiated by the class?
However, I have been trying to research what a static variable does within a function that is not in a class. Also, does a static variable within a function work somewhat like closure in javascript or am I totally off in this assumption?

I have read that when used within a class that a static property cannot be used by any object instantiated by that class
It depends on what you mean by that. eg:
class Foo {
static $my_var = 'Foo';
}
$x = new Foo();
echo $x::$my_var; // works fine
echo $x->my_var; // doesn't work - Notice: Undefined property: Foo::$my_var
and that a static method can be used by an object instantiated by the class???
Yes, an instantiated object belonging to the class can access a static method.
The keyword static in the context of classes behave somewhat like static class variables in other languages. A member (method or variable) declared static is associated with the class and rather than an instance of that class. Thus, you can access it without an instance of the class (eg: in the example above, I could use Foo::$my_var)
However, I have been trying to research what a static variable does within a function that is not in a class.
Also, does a static variable within a function work somewhat like closure in javascript or am I totally off in this assumption.
Outside of classes (ie: in functions), a static variable is a variable that doesn't lose its value when the function exits. So in sense, yes, they work like closures in JavaScript.
But unlike JS closures, there's only one value for the variable that's maintained across different invocations of the same function. From the PHP manual's example:
function test()
{
static $a = 0;
echo $a;
$a++;
}
test(); // prints 0
test(); // prints 1
test(); // prints 2
Reference: static keyword (in classes), (in functions)

static has two uses in PHP:
First, and most commonly, it can be used to define 'class' variables/functions (as opposed to instance variables/functions), that can be accessed without instantiating a class:
class A {
public static $var = 'val'; // $var is static (in class context)
public $other_var = 'other_val'; // non-static
}
echo A::$var; // val
echo A::$other_var // doesn't work (fatal error, undefined static variable)
$a = new A;
echo $a->var // won't work (strict standards)
echo $a->other_var // other_val
Secondly, it can be used to maintain state between function calls:
function a() {
static $i = 0;
$j = 0;
return array($i++, $j++);
}
print_r(a()); // array(0, 0)
print_r(a()); // array(1, 0)
print_r(a()); // array(2, 0)
//...
Note that declaring a variable static within a function works the same regardless of whether or not the function is defined in a class, all that matters is where the variable is declared (class member or in a function).

A static variable in a function is initialized only in the first call of that function in its running script.

At first i will explain what will happen if static variable is not used
<?php
function somename() {
$var = 1;
echo $var . "<br />";
$var++;
}
somename();
somename();
somename();
?>
If you run the above code the output you gets will be 1 1 1 . Since everytime you called that function variable assigns to 1 and then prints it.
Now lets see what if static variable is used
<?php
function somename() {
static $var = 1;
echo $var . "<br />";
$var++;
}
somename();
somename();
somename();
?>
Now if you run this code snippet the output will be 1 2 3.
Note: Static keeps its value and stick around everytime the function is called. It will not lose its value when the function is called.

class Student {
static $total_student = 0;
static function add_student(){
return Student::$total_student++;
}
}
First: for the add_student function, the best practice is to use static not public.
Second: in the add_student function, we are using Student::$total_student,not use $this->total_student. This is big different from normal variable.
Third:static variable are shared throughout the inheritance tree.
take below code to see what is the result:
class One {
static $foo ;
}
class Two extends One{}
class Three extends One{}
One::$foo = 1;
Two::$foo = 2;
Three::$foo = 3;
echo One::$foo;
echo Two::$foo;
echo Three::$foo;`

Related

PHP : Calling classes - Whats the diference? [duplicate]

There are two distinct ways to access methods in PHP, but what's the difference?
$response->setParameter('foo', 'bar');
and
sfConfig::set('foo', 'bar');
I'm assuming -> (dash with greater than sign or chevron) is used for functions for variables, and :: (double colons) is used for functions for classes. Correct?
Is the => assignment operator only used to assign data within an array? Is this in contrast to the = assignment operator which is used to instantiate or modify a variable?
When the left part is an object instance, you use ->. Otherwise, you use ::.
This means that -> is mostly used to access instance members (though it can also be used to access static members, such usage is discouraged), while :: is usually used to access static members (though in a few special cases, it's used to access instance members).
In general, :: is used for scope resolution, and it may have either a class name, parent, self, or (in PHP 5.3) static to its left. parent refers to the scope of the superclass of the class where it's used; self refers to the scope of the class where it's used; static refers to the "called scope" (see late static bindings).
The rule is that a call with :: is an instance call if and only if:
the target method is not declared as static and
there is a compatible object context at the time of the call, meaning these must be true:
the call is made from a context where $this exists and
the class of $this is either the class of the method being called or a subclass of it.
Example:
class A {
public function func_instance() {
echo "in ", __METHOD__, "\n";
}
public function callDynamic() {
echo "in ", __METHOD__, "\n";
B::dyn();
}
}
class B extends A {
public static $prop_static = 'B::$prop_static value';
public $prop_instance = 'B::$prop_instance value';
public function func_instance() {
echo "in ", __METHOD__, "\n";
/* this is one exception where :: is required to access an
* instance member.
* The super implementation of func_instance is being
* accessed here */
parent::func_instance();
A::func_instance(); //same as the statement above
}
public static function func_static() {
echo "in ", __METHOD__, "\n";
}
public function __call($name, $arguments) {
echo "in dynamic $name (__call)", "\n";
}
public static function __callStatic($name, $arguments) {
echo "in dynamic $name (__callStatic)", "\n";
}
}
echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";
echo '$b->func_instance():', "\n", $b->func_instance(), "\n";
/* This is more tricky
* in the first case, a static call is made because $this is an
* instance of A, so B::dyn() is a method of an incompatible class
*/
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
* instance of B (despite the fact we are in a method of A), so
* B::dyn() is a method of a compatible class (namely, it's the
* same class as the object's)
*/
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";
Output:
B::$prop_static: B::$prop_static value
B::func_static(): in B::func_static
$b->prop_instance: B::$prop_instance value
$b->func_static(): in B::func_static
$b->func_instance():
in B::func_instance
in A::func_instance
in A::func_instance
$a->dyn():
in A::callDynamic
in dynamic dyn (__callStatic)
$b->dyn():
in A::callDynamic
in dynamic dyn (__call)
:: is used in static context, ie. when some method or property is declared as static:
class Math {
public static function sin($angle) {
return ...;
}
}
$result = Math::sin(123);
Also, the :: operator (the Scope Resolution Operator, a.k.a Paamayim Nekudotayim) is used in dynamic context when you invoke a method/property of a parent class:
class Rectangle {
protected $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
class Square extends Rectangle {
public function __construct($x) {
parent::__construct($x, $x);
}
}
-> is used in dynamic context, ie. when you deal with some instance of some class:
class Hello {
public function say() {
echo 'hello!';
}
}
$h = new Hello();
$h->say();
By the way: I don't think that using Symfony is a good idea when you don't have any OOP experience.
Actually by this symbol we can call a class method that is static and not be dependent on other initialization...
class Test {
public $name;
public function __construct() {
$this->name = 'Mrinmoy Ghoshal';
}
public static function doWrite($name) {
print 'Hello '.$name;
}
public function write() {
print $this->name;
}
}
Here the doWrite() function is not dependent on any other method or variable, and it is a static method. That's why we can call this method by this operator without initializing the object of this class.
Test::doWrite('Mrinmoy');
// Output: Hello Mrinmoy.
But if you want to call the write method in this way, it will generate an error because it is dependent on initialization.
The => operator is used to assign key-value pairs in an associative array. For example:
$fruits = array(
'Apple' => 'Red',
'Banana' => 'Yellow'
);
It's meaning is similar in the foreach statement:
foreach ($fruits as $fruit => $color)
echo "$fruit is $color in color.";
The difference between static and instantiated methods and properties seem to be one of the biggest obstacles to those just starting out with OOP PHP in PHP 5.
The double colon operator (which is called the Paamayim Nekudotayim from Hebrew - trivia) is used when calling an object or property from a static context. This means an instance of the object has not been created yet.
The arrow operator, conversely, calls methods or properties that from a reference of an instance of the object.
Static methods can be especially useful in object models that are linked to a database for create and delete methods, since you can set the return value to the inserted table id and then use the constructor to instantiate the object by the row id.
Yes, I just hit my first 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. My bad, I had a $instance::method() that should have been $instance->method(). Silly me.
The odd thing is that this still works just fine on my local machine (running PHP 5.3.8) - nothing, not even a warning with error_reporting = E_ALL - but not at all on the test server, there it just explodes with a syntax error and a white screen in the browser. Since PHP logging was turned off at the test machine, and the hosting company was too busy to turn it on, it was not too obvious.
So, word of warning: apparently, some PHP installations will let you use a $instance::method(), while others don't.
If anybody can expand on why that is, please do.

Do I need to declare a variable before initialise it in PHP constructor

I have a question about variable declare in PHP, I know this question may be little bit stupid. I have the following code
<?php
Class Test{
function __construct(){
$this->test = 'helloworkd';
}
function test(){
echo $this->test;
}
}
$test = new Test();
$test->test();
It seems like I can use the test variable without declaring it. My question is why the test() method can access the test variable? Is the test a global variable?
Thanks for your help!
My question is why the test() method can access the test variable?
PHP unlike some other languages allows you to assign values to variables without first declaring them. The interpreter will initialize them for you. This is poor practice because it makes code harder to read and debug, and because it can cause errors if you try to read a variable that was never declared:
<?php
$nonexistentArray['key'] = 7; //Bad practice, but PHP won't complain
$a = $fakeArray['key']; //Undefined variable error
Even in the second case, PHP will continue to execute the rest of the script, but it will complain.
Is the test a global variable?
No. It lives in the local scope.
<?php
function myFunc(){
//$arr was never declared, but PHP won't complain
$arr['key'][]=7;
}
myFunc();
//Undefined var error. The $arr that was initialized in myFunc is not global
print_r($arr);
A good IDE will complain if you try to use a variable that you never declared. In your case, when in the constructor you do:
$this->test = 'helloworkd';
PHP will initialize this class property for you. Now the rest of your code can use it, including the test() method. If it seems like a global var, it's not. It's a class property. If you tried to access it as just test from outside the class, you would not be able to. You'd have to use the accessor operator -> in $test->test or $this->test.
Many "test"! You have asign test="helloworld" in the contructor, so it takes a value for every new Test() is made.
$x = new Test();
$y = new Test();
echo $x->test(); //"helloworld"
echo $y->test(); //"helloworld"
I would declare your variable. This makes the code more readable for yourself any any others that see your code.
For example:
<?php
Class Test {
public $test;
function __construct($test){
$this->test = $test;
}
function test(){
echo $this->test;
}
So now we have a public variable that is accessible through an instance of this class by calling
$instance->test;
If you do not want this then you can change public to private or protected
You can read about this here: http://php.net/manual/en/language.variables.scope.php
Whatever you pass as an argument when creating an instance of this class will be assigned to the $test variable.
My question is why the test() method can access the test variable?
It can't. It is trying to access a constant test, if you want to access the class variable, use $this->test.
For example:
<?php
echo foo;
Will echo out a string "foo" and also spits out a notice: Use of undefined constant foo - assumed 'foo' in ...
<?php
class test{
public $test;
public function __construct(){
$this->test = 'helloworkd';
}
$newtest = new Test();
echo $newtest->test;
?>

assigning static var to non-static var, method to return the values not working

I'm new to PHP and practicing using static variables. I decided to grab an example that I learnt from C++ and re-write it for PHP (example from the bottom of this article).
There's a class with two private variables (one static), a constructor and a get-method. The constructor assigns the static variable's value to the second private variable, and then increments.
<?php
class Something
{
private static $s_nIDGenerator = 1;
private $m_nID;
public function Something() {
$m_nID = self::$s_nIDGenerator++;
echo "m_nID: " . $m_nID . "</br>"; //for testing, can comment this out
}
public function GetID() {
return $m_nID;
}
}
// extra question:
// static variable can be assigned a value outside the class in C++, why not in PHP?
// Something::$s_nIDGenerator = 1;
$cFirst = new Something();
$cSecond = new Something();
$cThird = new Something();
echo $cFirst->GetID() . "</br>";
echo $cSecond->GetID() . "</br>";
echo $cThird->GetID() . "</br>";
?>
Using the echo test in line 9 to see if m_nID is getting a value I see:
m_nID: 1
m_nID: 2
m_nID: 3
But these values are not being returned by the "->GetID()" calls. Any ideas why?
Edit: both replies so far have solved this, I wish I could "check" them both, so thank you! I'll leave the original code in the question as-is for any future people who have a similar problem
Your background in C++ led up to this issue, which is an easy mistake to make. In PHP, all instance (or object) variables are referenced using $this->, and static (or class) variables with self::. Based on your code:
public function GetID() {
return $m_nID;
}
Access to the private variable $m_nID should be scoped like this:
public function GetID() {
return $this->m_nID;
}
And inside your constructor:
$m_nID = self::$s_nIDGenerator++;
It should have been:
$this->m_nID = self::$s_nIDGenerator++;
Q & A
Why is there no need to put $ before m_nID when using $this->
The above two ways of referencing instance and class variables come with a very different kind of syntax:
$this is the instance reference variable and any properties are accessed using the -> operator; the $ is not repeated for the property names themselves, although they're present in the declaration (e.g. private $myprop).
self:: is synonymous to Something:: (the class name itself); it doesn't reference an instance variable and therefore has no $ in front of it. To differentiate static variables from class constants (self::MYCONST) and class methods (self::myMethod()) it's prefixed with a $.
Extra
That said, $this->$myvar is accepted too and works like this:
private $foo = 'hello world';
function test()
{
$myvar = 'foo';
echo $this->$foo; // echoes 'hello world'
}
class Something{
private static $s_nIDGenerator = 1;
private $m_nID;
public function Something() {
$this->m_nID = self::$s_nIDGenerator++;
}
public function GetID() {
return $this->m_nID;
}
}
It is interesting to note the difference between using self::$s_nIDGenerator on a static variable vs using $this->s_nIDGenerator on a static variable, whereas $this-> will not store anything.

Using Global Variable [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
To pass value of a variable in one function to another function in same class
Can a value of a variable in one function be made available in another function on the same class using "GLOBAL" in PHP. If so please suggest how can this be achieved using Global.
You don't need to make a variable GLOBAL if you're within an object.
class myClass {
public $myVar = "Hello";
function myFunction() {
echo $this->$myVar;
}
}
This is one of the main points of objects - that you can assign different values to variables and get/set those variables within the different methods. And also that you can create multiple instances of objects each holding different information within the same structure and with the same methods available.
Additionally to what #Codecraft said (about using public properties), you can use:
indeed global variable (which is really something you should avoid doing),
passing values in parameters,
static variable within class,
Below is the example of using static variable (private), because I think this suits your needs best:
class MyClass {
private static $_something;
public function write() {
static::$_something = 'ok';
}
public function read() {
return static::$_something;
}
}
$x = new MyClass();
$x->write();
var_dump($x->read());
which outputs:
string(2) "ok"
This is in fact something like a global, but available only from inside your class (because of the keyword "private") and common among every instance of the class. If you use setting some non-static property, it will change across different instances of the class (one object may have different value stored in it than the other object has).
Comparison of solutions based on static and non-static variables:
Solution based on static variable will give you really global-like behaviour (value passed across different instances of the same class):
class MyClass {
private static $_something;
public function write() {
static::$_something = 'ok';
}
public function read() {
return static::$_something;
}
}
// first instance
$x = new MyClass();
$x->write();
// second instance
$y = new MyClass();
var_dump($y->read());
which outputs:
string(2) "ok"
And the solution based on non-static variables will look like:
class MyClass {
private $_something;
public function write() {
$this->_something = 'ok';
}
public function read() {
return $this->_something;
}
}
// first instance
$x = new MyClass();
$x->write();
// second instance
$y = new MyClass();
var_dump($y->read());
but will output:
NULL
which means that in this case the second instance has no value assigned for the variable you wanted to behave like "global".
Yes, a value of a variable in one function can be made available in another function on the same class using "GLOBAL". The following code prints 3:
class Foo
{
public function f1($arg) {
GLOBAL $x;
$x = $arg;
}
public function f2() {
GLOBAL $x;
return $x;
}
}
$foo = new Foo;
$foo->f1(3);
echo $foo->f2();
However, the usage of global variables is usually a sign of poor design.
Note that while keywords in PHP are case-insensitive, it is custom to use lower case letters for them. Not also that the superglobal array that contains all global variables is called $GLOBALS, not GLOBAL.

Difference between access class methods

Up until the yesterday I though that both of these methods for accessing a class where identical. Google turned up noting (either that or my keywords were bad). What is the difference between accessing a class by defining a new instance of the class rather than just calling the class methods directly.
I hardly understood what I just ask, since I have not a clue what I'm asking but allow me to give a few examples to help out.
For as long as I have been using classes in PHP I have been defining a instance of the class then accessing the methods from that variable. Here is an example:
<?php
class Myclass
{
public function my_method() {
return "This is my method";
}
}
$myclass = new Myclass();
echo $myclass->my_method(); // output: This is my method
?>
What is the difference between that and doing this?
<?php
class Myclass
{
public function my_method() {
return "This is my method";
}
}
echo Myclass::my_method(); // output: This is my method
?>
I hope I was clear enough. If not a brief synopsis would be - What is the difference between creating a new instance of a class then calling a method of the class with "$class->mymethod();," or just directly calling the method like so: "Myclass::mymethod();"?
Thanks in advance.
The :: notation is used to call the function as static. See these pages from the PHP manual for more info:
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/en/language.oop5.static.php.
In essence, static functions are just like regular functions outside classes. The function is not in object context when called as such, so the pseudo-variable $this is not available.
Note that the function should be declared as static if you are planning on calling it as such:
class SomeClass {
static public function StaticFunction() {
...
}
}
The Myclass::my_method() call should be throwing an E_STRICT warning, as you're calling a non-static method in a static context.
Static methods are methods that belong to the class rather than to the instance. These methods cannot access any non-static variables, as they have no reference for them (because non-static variables belong to the instance, not the class).
After using Java and C#, I'm mildly disturbed that this isn't considered an E_WARNING or E_ERROR, particularly since E_STRICT is not logged by default.
First, you should understand the difference between a class and an object, or a class and an instance of a class.
For example, where class is "Circle", an instance might be "this particular circle". Class Circle might have members $center and $radius - every point has these. But the values of these are different for every point.
$class->mymethod() is a call to an instance method, for instance $circle->Length(). You are saying something to a particular instance of an object. This method will have access to class members - variables that belong to the instance. In PHP you gain access to these instance variables using keyword $this.
For instance $circle->Length() might be implemented as return 2*Pi*$this->radius;
What happens when you say Circle::Length()? Nothing. This is syntax for calling static methods. Because you did not say which circle. Circle as a class does not have length.
Static method is declared with keyword static. Whatever it does it has no access to any instances of the class. It's something that a class as a whole does.
For instance, if you want to calculate length of the circle without actually creating one, then there might be static function calculateLength($radius) in the class circle. And you would call it as Circle::calculateLength($myRadius)
In my opinion you should not even think about static methods until you understand the non-static ones.
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php
I don't think you can call methods that way. I thought that was how you called static members of the class.
In my understanding when you create an instance of the class you are creating an object and so you call methods/properties from that object.
When you call a method/property via a static call you are calling on the class itself.
So if you have something like this:
class acs {
public $var = 'bla';
}
and then you do
$a = new acs();
$b = new acs();
echo $a->var . '<br>';
echo $b->var . '<br>';
$a->var = 'hey';
$b->var = 'Yooo';
echo $a->var . '<br>';
echo $b->var . '<br>';
You now have 2 instances of class acs which started with the same values but now have different values.
But if you have this:
class acs {
public static $var = 'bla';
}
And then do:
$a = new acs();
$b = new acs();
echo $a->var . '<br>';
echo $b->var . '<br>';
$a->var = 'hey';
$b->var = 'Yooo';
echo $a->var . '<br>';
echo $b->var . '<br>';
echo acs::$var;
What you are doing is:
You create the instances as before.
You echo nothing, because the public property var does not exist.
You create the public property var in both the instances
You echo their values (hey and Yoo)
You echo the static property var (which is 'bla' and has not changed)
Hope this helps!

Categories