What will happen if I create a class with a static property and create two instances of it?
Will the static property be shared between both instances and not be duplicated?
Yes, that is the definition of a static property.
Static properties belong to the class, not instances of the class.
class SomeClass {
private static $instanceCount = 0;
function __construct() {
self::$instanceCount++;
//do other stuff.
}
function instanceCount() {
return self::$instanceCount;
}
}
$one = new SomeClass();
echo $one->instanceCount(); //1
$two = new SomeClass();
echo $one->instanceCount(); //2
echo $two->instanceCount(); //2
Related
When I want to use a class's methods and properties in another class, I instantiate those classes in the constructor and set them as instance properties.
<?php
class ClassA
{
private $classB;
private $classC;
public function __construct()
{
// Instantiate class B and C and set the instance properties
$this->classB = new ClassB();
$this->classC = new ClassC();
}
// Example
public function getTest()
{
if ($this->classB->isTest1()) {
return 'some value';
} elseif ($this->classC->isTest1()) {
return 'some other value';
} else {
return 'some other value';
}
}
}
$ClassA = new ClassA();
$test = $ClassA->getTest();
There are some times where I want to instantiate a class in the constructor, and that other class has also instantiated the other class the constructor too:
<?php
class ClassA
{
private $classB;
public function __construct()
{
// Instantiate class B and set classB instance propert.
$this->classB = new ClassB();
}
}
class ClassB
{
private $classA;
public function __construct()
{
// Instantiate class A and set classA property so we can use class A methods and properties in this class.
$this->classA = new ClassA();
}
}
$ClassA = new ClassA();
$ClassB = new ClassB();
This will fail though because Class A instantiates class B in the constructor, class B instantiates class A in the constructor, and it keeps doing this going back and fourth until I get the PHP error message, 'Allowed memory size of ##### bytes exhausted'.
What would be the best workaround for this? Any help appreciated.
If your aim is to have a back-and-forth relation between two objects, then one of the many solutions is to provide the back-reference when you have it:
class ClassA {
public $objB;
public function __construct($other = null) {
$this->objB = $other ? $other : new ClassB($this);
}
}
class ClassB {
public $objA;
public function __construct($other = null) {
$this->objA = $other ? $other : new ClassA($this);
}
}
$objA = new ClassA();
var_dump($objA->objB->objA === $objA); // true
NB: I prefer to name the variables $objA instead of $classA, as they are not classes, but instances of classes.
NB2: I declared those variables as public members only to be able to demonstrate with var_dump that the references are working.
I have some problems with my class Model and other classes so I made this simple example to explain my problem :
class person{
public static $a = "welcome";
public function __construct(){
}
public static function getobject()
{
$v = new person();
return $v;
}
}
class student extends person{
public static $b = "World";
}
$st = student:getobject();//this will return person object but I want student object
echo $st->$b; // There is an error here because the object is not student
So I want to know what to write instead $v = new person(); to get the object of the last inherited class.
Use the late static binding's static keyword.
public static function getobject()
{
$v = new static();
return $v;
}
So, with student::getobject() you get an instance of student.
To retrieve the static (but why?) $b propriety, you can do $st::$b, or simply student::$b.
class parents{
public $a;
function __construct(){
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
parent::__construct();
}
}
$new = new child();//print 1
This code above print 1,which means whenever we create an instance of a child class,and assign value to properties inherited from its parent,the property in its parent class also has been assigned.But the code below shows different:
class parents{
public $a;
function test(){
$child = new child();
echo $this->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();//print nothing
Where I assign value to its child class and the parent apprently didn't have the value it assigned to its child class,why?
Thanks!
In the top example, since the construct function is being called from the child class, it is treating the object being used as if it were the child object that is just using a function in the parent class as if it were it's own.
In the bottom example you have two separate objects acting independently. The parent object has it's $a and so does the child, but they are not the same $a since they are contained in separate objects. so when you print $this->a in the parent class, it is referring to the parent's instance of $a whereas if you echo $a after setting $this->a =1 in the child class it would display the child's instance of $a.
Hope this cleared some stuff up for you.
You are mixing object composition and class inheritance.
Inheritance (realized through the extends keyword) defines an is a relationship.
Composition defines a has a relationship.
To illustrate this concept we will start with inheritance.
class Person {
public $name;
public function talk(){};
public function poop(){};
}
class Parent extends Person {
public function __construct($name) {
$this->name = $name;
}
}
class Child extends Person {
public function __construct($name){
$this->name = $name;
}
}
In this example we are defining a class of things called People. From that definition we are deriving two different subtypes of People, Parent and Child. When we subtype a class then the subtype gains it's own copy of all of the properties and has access to all of the methods defined in the base type, so without defining it a Child and Parent have a name and can both talk and poop by virtue of also being a person.
For example:
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->talk();
$child->poop();
Composition is used when you want to implement a has a relation ship. Lets revise our type definition of Parent.
class Parent extends Person {
public $children = array();
public function __construct($name) {
$this->name = $name;
}
public function addChild(Child $child){
$this->children[] = $child;
}
}
What we have now allowing if for a Parent to have a child.
$parent = new Parent("Homer");
$child = new Child("Bart");
$parent->addChild($child);
// now I can access homers first child
echo $parent->children[0]->name;
When you instantiate parent, the instance of child created extends the parent class with to test() function. However, that doesn't change the value of $a.
That happens, because you have two different instances, which have nothing in common(except the the inheritance..)
The behavior you except could be generated with inner classes - which php don't support.
If you want to share an var accros every instance, you have to make it static
class parents{
public static $a;
function test(){
$child = new child();
echo self::$a;
}
}
class child extends parents{
function __construct(){
self::$a = 1;
}
}
$new = new parents();
$new->test();
which isn't probably what you want. Or you tell exactly, where you want to change your var
class parents{
public $a;
function test(){
$child = new child();
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();
It's because in the first example you instantiate child
$new = new child();//print 1
and in the second you instantiate parents
$new = new parents();
The second works the same as the first using $new = new child();
If you want to access $a by instantiating child() you need to do it like this:
class parents{
public $a;
function test(){
$child = new child(); //CHANGE HERE
echo $child->a;
}
}
class child extends parents{
function __construct(){
$this->a = 1;
}
}
$new = new parents();
$new->test();
Let's say I have a class Bla that contains the variable $x.
I want this variable $x to keep its value for other objects once it's set by the first created object.
For example:
$object1 = new bla(.....);
$object1->setx();
$object1->getx();
$object2 = new bla(.....);
$object2->getx();
So I want:
$object2->getx()
...to give me the value I already set by object1.
I tried using $x as a globale variable inside the class, it turns out that it's not possible.
Can I use it outside the class and then access this variable inside the class?
What are the other methods?
Use static variables if you want them to have one and the same value, available regardless of their class instances (tutorial):
class bla
{
private static $x;
public function setx($x) {
self::$x = $x;
}
public function getx() {
return self::$x;
}
}
$object1 = new bla();
$object1->setx(5);
echo $object1->getx();
echo '<br>';
$object2 = new bla();
echo $object2->getx();
Output:
5
5
class Bla {
static private $x = "X!";
}
If you know what x should be at initialisation then just use the above. If x is computed then you can ensure it's only set once:
class Bla {
static private $x = null;
public function getX(){
if($this->x === null){
$this->x = theLogicToGetX();
}
return $this->x;
}
}
Only the first call will set x and subsequent calls will use that value.
See with example:
<?php
class Foo {
private static $my_static = 'foo';
/**
* Set static class property
*
* #param string $v
*/
public function setStaticValue($v) {
self::$my_static = $v;
}
/**
* Get static class property value
*
* #return string
*/
public function getStaticValue() {
return self::$my_static;
}
}
// show class static property value
echo foo::getStaticValue(); // foo
// now set new value in static property
foo::setStaticValue(' zoo ');
// show value
echo foo::getStaticValue(); // zoo
// make an object of class
$f = new Foo();
// show value
echo $f->getStaticValue(); // zoo
// make new object of class
$f2 = new Foo();
// show value
echo $f2->getStaticValue(); // zoo
It is possible with references
class A
{
private $a;
public function &getA(){return $this->a;}
public function setA($a) { $this->a = $a;}
}
class B
{
public function useA(&$a) { $a+=5 ;}
}
$objA = new A();
$objB = new B();
$objA->setA(5); //seting value of a in A class to 5
$objB->useA($objA->getA()); //modify the reference of A class $a variable in B class object
echo $objA->getA(); //echo the value from A class object
Output: 10
My solution doesn't have static limitations. So it can be used on multiple objects of same class. If you want to have access to class variable by same class objects use static as suggested above by Lukas.
There is also registry pattern which you should take a look at. Registry pattern makes you able to access variable in whole php application.
The idea of a Registry is simple: providing a dynamic possibility for discovering collaborator objects, so that we not hardcode static calls to global objects like Singletons in each of them. In the testing environment, we can fill the Registry with mocks.
class Registry
{
private static $instance;
private $registry = array();
private function __construct()
{
}
public function getInstance()
{
if(self::$instance == null) self::$instance = new Registry();
return self::$instance;
}
public function __set($var,$val)
{
$this->registry[$var] = $val;
}
public function __get($var)
{
if(isset($this->registry[$var]))
return $this->registry[$var];
else throw new Exception("Value $var doesn't exists in registry");
}
}
class A
{
public function useVar()
{
Registry::getInstance()->myVar += 10;
}
public function echoVar()
{
echo Registry::getInstance()->myVar;
}
}
Registry::getInstance()->myVar = 5;
$obj1 = new A();
$obj2 = new A();
$obj1->useVar();
$obj2->echoVar();
OUTPUT: 15
Yeah, you can make this functionality.
From here "global variable" means kind of variables, mentioned in the question.
You can use static variable of the class to store the value of global variable.
class Bla {
static private $x;
}
To access this variable we can use couple of methods:
Make special setters and getters, I would recommend this as most simple and clear way:
class Bla {
static private $x = 'init value';
public function getX() {
return self::$x;
}
public function setX($value) {
self::$x = $value;
}
}
// Usage:
$obj1 = new Bla();
echo $obj1->getX();// init value
$obj1->setX('changed value');
Of course if appropriate you can use just static access syntax (public variables or static setters and getters), which is even more simple and clear, than first method. For example:
class Bla {
static public $x = 'init value';
}
// Usage:
echo Bla::$x;
Bla::$x = 3;
Also take in mind that objects are passing by references in PHP5.
class Bla {
private $date;
public function __construct(DateTime $x) {
$this->date = $x;
}
public function getDate() {
return $this->date;
}
}
$date = new DateTime();
// Usage:
$obj1 = new Bla($date);
$obj2 = new Bla($date);
/* now play with $objN->getDate()->.. and $date->..
* to see, that $x in both objects are referring to same variable. */
Now lets see at some not so good ways.
We can use magic setters and getters, which combined of a phpDoc can "emulate" behaviour of a real object variable (i mean in runtime it will get and set variable and in IDE, which supports phpDoc, you can even see variable in auto-completion). This solution violates the principle of encapsulation, so i wouldn't recommend common usage of it.
/**
* #property mixed $x My global var.
*/
class Bla {
static private $x = 'init value';
public function __set($name, $value) {
if ($name == 'x') {
self::$x = $value;
}
}
public function __get($name) {
if ($name == 'x') {
return self::$x;
}
}
}
// Usage:
$obj1 = new Bla();
echo $obj1->x;// init value
$obj1->x = 'changed value';
Same behaviour without magic we can get using references:
class Bla {
static $storage = 'init value';
public $x;
public function __construct() {
$this->x = &self::$storage;
}
}
Also we can make $x here private and add special access methods, what makes sense only if you HATE to use static syntax (self::).
I saw this example from php.net:
<?php
class MyClass {
const MY_CONST = "yonder";
public function __construct() {
$c = get_class( $this );
echo $c::MY_CONST;
}
}
class ChildClass extends MyClass {
const MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>
But $c::MY_CONST is only recognized in version 5.3.0 or later. The class I'm writing may be distributed a lot.
Basically, I have defined a constant in ChildClass and one of the functions in MyClass (father class) needs to use the constant. Any idea?
How about using static::MY_CONST?
Since php 5.3:
Use static::MY_CONST
More details on static
In this case the keyword static is a reference to the actually called class.
This illustrates the difference between static $var, static::$var and self::$var:
class Base {
const VALUE = 'base';
static function testSelf() {
// Output is always 'base', because `self::` is always class Base
return self::VALUE;
}
static function testStatic() {
// Output is variable: `static::` is a reference to the called class.
return static::VALUE;
}
}
class Child extends Base {
const VALUE = 'child';
}
echo Base::testStatic(); // output: base
echo Base::testSelf(); // output: base
echo Child::testStatic(); // output: child
echo Child::testSelf(); // output: base
Also note that the keyword static has 2 quite different meanings:
class StaticDemo {
static function demo() {
// Type 1: `static` defines a static variable.
static $Var = 'bar';
// Type 2: `static::` is a reference to the called class.
return static::VALUE;
}
}
Instead of
$c = get_class( $this );
echo $c::MY_CONST;
Do this
$c = get_class( $this );
echo constant($c . '::MY_CONST');
I couldn't get it to work with const as it prints "yonderyonder" (that's the thing about constants, they don't change), but it works fine with var:
<?php
class MyClass {
var $MY_CONST = "yonder";
public function __construct() {
echo $this->MY_CONST;
}
}
class ChildClass extends MyClass {
var $MY_CONST = "bar";
}
$x = new ChildClass(); // prints 'bar'
$y = new MyClass(); // prints 'yonder'
?>
If you need to access constants, properties, methods of classes or objects you can use reflection, it provides much more details about structure of the object.
example:
class MainClass
{
const name = 'Primary';
public $foo = 'Foo Variable';
}
class ExtendedClass extends MainClass
{
const name = 'Extended';
}
/**
* From Class Name
*/
//get reflection of main class
$mainReflection = new ReflectionClass('MainClass');
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionClass('ExtendedClass');
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended
/**
* From Objects
*/
$main = new MainClass();
$extended = new ExtendedClass();
//get reflection of main class
$mainReflection = new ReflectionObject($main);
if($mainReflection->hasConstant('name'))
var_dump($mainReflection->getConstant('name'));//Primary
//get reflection of extended class
$extendedReflection = new ReflectionObject($extended);
if($extendedReflection->hasConstant('name'))
var_dump($extendedReflection->getConstant('name'));//Extended