Storing php object's property in another object as a reference - php

Is it possible to store a reference to an object's property (class member variable which holds a scalar data such as string or integer) within an object of a different class?
I am trying to have the following two echo statements produce identical results.
<?php
$x = new Type;
$x->name = 'abcd';
echo "x.name=" . $x->name . '<br/>';
echo "x.obj.name=" . $x->obj->value . '<br/>';
class Type
{
public $obj; //Instance of Property (Property class defined below)
public $name;
function __construct()
{
$this->obj = new Property($this->name);
}
}
class Property
{
public $value;
function __construct($v)
{
$this->value = $v;
}
}

$this->obj = new Property($this->name);
Is called at the time of object creation. Which is executed before the assignment.
i.e.
When you call $x = new Type;
The constructor is called and you try to copy 'name' which is empty by then
May be what you want it following, rather than passing the value, pass $this and keep the referance.
<?php
class Type
{
public $obj; //Instance of Property (Property class defined below)
public $name;
function __construct()
{
$this->obj = new Property($this);
}
}
class Property
{
public $value;
function __construct($ref)
{
$this->value = $ref;
}
}
$x = new Type;
$x->name = 'abcd';
echo "x.name=" . $x->name . '<br/>';
echo "x.obj.name=" . $x->obj->value->name . '<br/>';

You can pass the name value inside the constructor.
$x = new Type('abcd');
Without doing that, your constructor will not know what $this->name is yet. So we use it in the constructor and set the classes property before using it.
function __construct($p_name){
$this->name = $p_name;
$this->obj = new Property($this->name);
}
You could just as easily set the value after calling the constructor and then initialize the reference afterwards -
class Type {
public $obj;
public $name;
function setProperty(){
$this->obj = new Property($this->name);
}
}
$x = new Type;
$x->name = 'abcd';
$x->setProperty();
echo "x.name=" . $x->name;
echo "x.obj.name=" . $x->obj->value;

This is an old question but just to add to this.
You can have an object with methods and properties inside of another object..
Example
$obj1 = new class1();
$obj2 = new class2($obj1); // you just grabbed $obj1 and stuck it inside $obj2
Now you can use the stored object's methods like so:
$obj2->obj1->method_from_obj1();
or access the stored object's properties like so:
$obj2->obj1->property_of_obj1;
This is SUPER convenient if you instantiated an object of some API and want to use the API methods inside of your own object.

While at the time of answering this question is 9+ years old, I've encountered a similar issue today and found a way to do what's requested.
In short: you should use references. Here's a a working example (PHP 8):
<?php
class Source
{
public int $counter = 10;
}
class Consumer
{
public int $value = 0;
public function __construct(int &$value)
{
$this->value = &$value;
}
}
$source = new Source();
// Pass property of Source instance to the consumer.
$consumer = new Consumer($source->counter);
assert($consumer->value === 10);
// Changing value in the Source instance.
$source->counter = 15;
// ... and value in the consumer updated as well.
assert($consumer->value === 15);
exit;
So, the answer is yes, it is possible.

Related

PHP 8: is it possible to change a class outside the class? [duplicate]

How can I create a property from a given argument inside a object's method?
class Foo{
public function createProperty($var_name, $val){
// here how can I create a property named "$var_name"
// that takes $val as value?
}
}
And I want to be able to access the property like:
$object = new Foo();
$object->createProperty('hello', 'Hiiiiiiiiiiiiiiii');
echo $object->hello;
Also is it possible that I could make the property public/protected/private ? I know that in this case it should be public, but I may want to add some magik methods to get protected properties and stuff :)
I think I found a solution:
protected $user_properties = array();
public function createProperty($var_name, $val){
$this->user_properties[$var_name] = $val;
}
public function __get($name){
if(isset($this->user_properties[$name])
return $this->user_properties[$name];
}
do you think it's a good idea?
There are two methods to doing it.
One, you can directly create property dynamically from outside the class:
class Foo{
}
$foo = new Foo();
$foo->hello = 'Something';
Or if you wish to create property through your createProperty method:
class Foo{
public function createProperty($name, $value){
$this->{$name} = $value;
}
}
$foo = new Foo();
$foo->createProperty('hello', 'something');
The following example is for those who do not want to declare an entire class.
$test = (object) [];
$prop = 'hello';
$test->{$prop} = 'Hiiiiiiiiiiiiiiii';
echo $test->hello; // prints Hiiiiiiiiiiiiiiii
Property overloading is very slow. If you can, try to avoid it. Also important is to implement the other two magic methods:
__isset();
__unset();
If you don't want to find some common mistakes later on when using these object "attributes"
Here are some examples:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
EDITED after Alex comment:
You can check yourself the differences in time between both solutions (change $REPEAT_PLEASE)
<?php
$REPEAT_PLEASE=500000;
class a {}
$time = time();
$a = new a();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
$a->data = 'bye'.$a->data;
}
echo '"NORMAL" TIME: '.(time()-$time)."\n";
class b
{
function __set($name,$value)
{
$this->d[$name] = $value;
}
function __get($name)
{
return $this->d[$name];
}
}
$time=time();
$a = new b();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
//echo $a->data;
$a->data = 'bye'.$a->data;
}
echo "TIME OVERLOADING: ".(time()-$time)."\n";
Use the syntax: $object->{$property}
where $property is a string variable and
$object can be this if it is inside the class or any instance object
Live example: http://sandbox.onlinephpfunctions.com/code/108f0ca2bef5cf4af8225d6a6ff11dfd0741757f
class Test{
public function createProperty($propertyName, $propertyValue){
$this->{$propertyName} = $propertyValue;
}
}
$test = new Test();
$test->createProperty('property1', '50');
echo $test->property1;
Result: 50

PHP: Creating class properties from within function [duplicate]

How can I create a property from a given argument inside a object's method?
class Foo{
public function createProperty($var_name, $val){
// here how can I create a property named "$var_name"
// that takes $val as value?
}
}
And I want to be able to access the property like:
$object = new Foo();
$object->createProperty('hello', 'Hiiiiiiiiiiiiiiii');
echo $object->hello;
Also is it possible that I could make the property public/protected/private ? I know that in this case it should be public, but I may want to add some magik methods to get protected properties and stuff :)
I think I found a solution:
protected $user_properties = array();
public function createProperty($var_name, $val){
$this->user_properties[$var_name] = $val;
}
public function __get($name){
if(isset($this->user_properties[$name])
return $this->user_properties[$name];
}
do you think it's a good idea?
There are two methods to doing it.
One, you can directly create property dynamically from outside the class:
class Foo{
}
$foo = new Foo();
$foo->hello = 'Something';
Or if you wish to create property through your createProperty method:
class Foo{
public function createProperty($name, $value){
$this->{$name} = $value;
}
}
$foo = new Foo();
$foo->createProperty('hello', 'something');
The following example is for those who do not want to declare an entire class.
$test = (object) [];
$prop = 'hello';
$test->{$prop} = 'Hiiiiiiiiiiiiiiii';
echo $test->hello; // prints Hiiiiiiiiiiiiiiii
Property overloading is very slow. If you can, try to avoid it. Also important is to implement the other two magic methods:
__isset();
__unset();
If you don't want to find some common mistakes later on when using these object "attributes"
Here are some examples:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
EDITED after Alex comment:
You can check yourself the differences in time between both solutions (change $REPEAT_PLEASE)
<?php
$REPEAT_PLEASE=500000;
class a {}
$time = time();
$a = new a();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
$a->data = 'bye'.$a->data;
}
echo '"NORMAL" TIME: '.(time()-$time)."\n";
class b
{
function __set($name,$value)
{
$this->d[$name] = $value;
}
function __get($name)
{
return $this->d[$name];
}
}
$time=time();
$a = new b();
for($i=0;$i<$REPEAT_PLEASE;$i++)
{
$a->data = 'hi';
//echo $a->data;
$a->data = 'bye'.$a->data;
}
echo "TIME OVERLOADING: ".(time()-$time)."\n";
Use the syntax: $object->{$property}
where $property is a string variable and
$object can be this if it is inside the class or any instance object
Live example: http://sandbox.onlinephpfunctions.com/code/108f0ca2bef5cf4af8225d6a6ff11dfd0741757f
class Test{
public function createProperty($propertyName, $propertyValue){
$this->{$propertyName} = $propertyValue;
}
}
$test = new Test();
$test->createProperty('property1', '50');
echo $test->property1;
Result: 50

how to store constructed variable name

I wold like to get the following variable name:
class ClassA
{
public $my_name_is = "";
function __construct($tag,$cont = null)
{
$this->my_name_is = ???;
}
}
$OBJ = new ClassA();
echo($OBJ->my_name_is);
This should output
OBJ
Is it possible?
I make tag HTML generator and the id of the tag should be the object name so I must not write it twice:
$input_pwd = new tag("td>input TYPE=PASSWORD.box_lg#input_pwd"); //old way
$input_pwd = new tag("td>input TYPE=PASSWORD.box_lg"); //upgraded way
should generate:
<td><input TYPE=PASSWORD ID='input_pwd' CLASS='box_lg'></td>
No, it's not. An object doesn't know the names of variables that refer to it.
"Needing" this is usually a design flaw.
You can use the magic constant __CLASS__ for retrieving the name of the current class, but there is no way for a class to get the name of the variable which stores the class. You may want to extend your class and still use __CLASS__:
class OBJ extends ClassA {
public function getName() {
return __CLASS__;
}
}
$OBJ = new OBJ();
$OBJ->getName();
See also: http://php.net/manual/en/language.constants.predefined.php
If you simply want to ensure that each reference to the object has a unique ID, you can do that with a static variable.
class ClassA {
public function getUniqueName() {
static $count = 0;
++$count;
return __CLASS__ . '.' . $count;
}
}
$OBJ = new ClassA();
echo($OBJ->getUniqueName();
Every time that method is called, it will give you a different result. If you call it only once on each variable, you should be fine.

Why does Static member variable inherits the value when instantiatiing object number of times in PHP?

i was testing the Static Keyword on how exactly does it work and i came across this which i don't understand what is happening.
Consider two Classes ClassNameA & ClassNameB with the following codes.
ClassNameA without Static Keyword
class ClassNameA
{
private $name;
public function __construct($value) {
if($value != '') {
$this->name = $value;
}
$this->getValue();
}
public function getValue() {
echo $this->name;
}
}
ClassNameB with Static Keyword
class ClassNameB
{
private static $name;
public function __construct($value) {
if($value != '') {
self::$name = $value;
}
$this->getValue();
}
public function getValue() {
echo self::$name;
}
}
When i instantiate the object multiple times using ClassNameA
$a = new ClassNameA(12);
echo '<br/>';
$a = new ClassNameA(23);
echo '<br/>';
$a = new ClassNameA(''); //Argument given is Empty here
it outputs the folowing
12
23
And now when i instantiate the object multiple times using ClassNameB
$a = new ClassNameB(12);
echo '<br/>';
$a = new ClassNameB(23);
echo '<br/>';
$a = new ClassNameB(''); //Argument given is Empty here
It outputs the following
12
23
23
Note the extra value 23 it is taking even if the Argument Passed is Empty. Is this a bug? or am i missing something?
This is the nature of static property. The static property is a kind of property of class not the property of object.
When you passed the blank, according to the condition the value of static property will not get updated and last value is still there in the static property.
Since the static property is not bounded with any of the object hence it is available without a need any object.
$a = new ClassNameB(12); //static property is set to 12
echo '<br/>';
$a = new ClassNameB(23); //static property is update to 23
echo '<br/>';
$a = new ClassNameB(''); //static property is not updated here it is still 23
EDIT
You can understand like this:-
if($value != '') {
$this->name = $value; //
}
What the code above is doing it is setting the property value for current object (object which is initializing right now).
So when you wrote
$a = new ClassNameA(12);
What it is doing it is setting the name property to 12 for object a;
$a = new ClassNameA(23);
What it is doing it is setting the name property to 23 for object a;
But when the property is static that is for the whole class not for any object.
so when you wrote
if($value != '') {
self::$name = $value;
}
The code above is setting the static property value. Note that here you wrote self instead of $this which make it use for this class only and not for any of the object.
I tried to explain it better but don't know how it is explaining for you.
A static member is a single instance across the entire application, not once per object. For example
class Example {
static public $var;
static public MyFunction() {
echo "MyFunction\n";
}
}
Example::$var = 123;
echo Example::$var;
Example::MyFunction();
Note how we did not need to create an instance of "Example", essentially its name-spacing the variable to the class. This would be invalid:
$example = new Example();
echo $example->var;
$example->MyFunction();
You can also reference it inside the class as
self::$var
self::MyFunction();
Which makes it safe to rename the class later if you need to. A static function can not access non static member or method though.

Get a static property of an instance

If I have an instance in PHP, what's the easiest way to get to a static property ('class variable') of that instance ?
This
$classvars=get_class_vars(get_class($thing));
$property=$classvars['property'];
Sound really overdone. I would expect
$thing::property
or
$thing->property
EDIT: this is an old question. There are more obvious ways to do this in newer
PHP, search below.
You need to lookup the class name first:
$class = get_class($thing);
$class::$property
$property must be defined as static and public of course.
From inside a class instance you can simply use self::...
class Person {
public static $name = 'Joe';
public function iam() {
echo 'My name is ' . self::$name;
}
}
$me = new Person();
$me->iam(); // displays "My name is Joe"
If you'd rather not
$class = get_class($instance);
$var = $class::$staticvar;
because you find its two lines too long, you have other options available:
1. Write a getter
<?php
class C {
static $staticvar = "STATIC";
function getTheStaticVar() {
return self::$staticvar;
}
}
$instance = new C();
echo $instance->getTheStaticVar();
Simple and elegant, but you'd have to write a getter for every static variable you're accessing.
2. Write a universal static-getter
<?php
class C {
static $staticvar = "STATIC";
function getStatic($staticname) {
return self::$$staticname;
}
}
$instance = new C();
echo $instance->getStatic('staticvar');
This will let you access any static, though it's still a bit long-winded.
3. Write a magic method
class C {
static $staticvar = "STATIC";
function __get($staticname) {
return self::$$staticname;
}
}
$instance = new C();
echo $instance->staticvar;
This one allows you instanced access to any static variable as if it were a local variable of the object, but it may be considered an unholy abomination.
classname::property;
I think that's it.
You access them using the double colon (or the T_PAAMAYIM_NEKUDOTAYIM token if you prefer)
class X {
public static $var = 13;
}
echo X::$var;
Variable variables are supported here, too:
$class = 'X';
echo $class::$var;
You should understand what the static property means. Static property or method is not for the objects. They are directly used by the class.
you can access them by
Class_name::static_property_name
These days, there is a pretty simple, clean way to do this.
<?php
namespace Foo;
class Bar
{
public static $baz=1;
//...
public function __toString()
{
return self::class;
}
}
echo Bar::$baz; // returns 1
$bar = new Bar();
echo $bar::$baz; // returns 1
You can also do this with a property in PHP 7.
<?php
namespace Foo;
class Bar
{
public static $baz=1;
public $class=self::class;
//...
}
$bar = new Bar();
echo $bar->class::$baz; // returns 1
class testClass {
public static $property = "property value";
public static $property2 = "property value 2";
}
echo testClass::$property;
echo testClass::property2;

Categories