PHP object property in variable - php

I want to create dynamic object property as variable in php.
For example
$b = '';
if($b != '') $b = "->b";
$a = new stdClass();
$a. $b->c;
My Target Output is
If(b == '') $a->c;
else $a->b->c;

For $b->c to work, you have to make $b an object of stdClass class. But since you made $b as a string using $b = "->b";, the former statement $b->c would throw error.
So the workaround is - make b as a property of object $a and assign an object of class stdClass to this member property. The following block of code would make this concept more clearer.
$b = '';
$a = new stdClass();
if($b != ''){
$a->b = new stdClass();
$a->b->c = 'something';
}else{
$a->c = 'something else';
}
Later, you can have the desired target output like this:
if($b == '') echo $a->c;
else echo $a->b->c;

Related

Are PHP zvals mutable?

I've been reading about memory management in PHP and learned that variables in PHP copy the reference to zvals as long as you don't do a write operation (copy on write paradigm).
https://www.phpinternalsbook.com/php5/zvals/memory_management.html#reference-counting-and-copy-on-write
However, it does not describe what happens when you reassign a value to an already copied zval.
Here's what the book says:
$a = 1; // $a = zval_1(value=1, refcount=1)
$b = $a; // $a = $b = zval_1(value=1, refcount=2)
$c = $b; // $a = $b = $c = zval_1(value=1, refcount=3)
$a++; // $b = $c = zval_1(value=1, refcount=2)
// $a = zval_2(value=2, refcount=1)
Now, if you do another $a++, will it change the value in zval,
$a++; // $a = zval_2(value=3, refcount=1)
or will it create a new zval once again?
$a++; // $a = zval_3(value=3, refcount=1)
Following the logic of the PHP Language Reference, I guess it should be more likely option #1 as long as refcount = 1 (you would not manipulate another variable).

Can I use the eval function in this case?

how could I get the following code to print out aaa.bbb.ccc ??
Currently all I get is a parse error for each eval() line.
This is a abstract code version. Finally I want the users to be able to select fields of a database table to be searched through. Something like a combination of
if (strpos("$field1.$field2.$field3",$search) !== false) ...
$filter = "\$x=\$a.\$b.\$c";
$a = "a";
$b = "a";
$c = "a";
eval($filter);
echo $x.",";
$a = "b";
$b = "b";
$c = "b";
eval($filter);
echo $x.",";
$a = "c";
$b = "c";
$c = "c";
eval($filter);
echo $x;
To fix your current code, change the following:
$filter = "\$x=\$a.\$b.\$c";
To
$filter = '$x=$a.$b.$c;';
But to use eval() on user input is a big security hole in your code. Try some different approach, like checking if the input is present in $search by use of a regular expression and the preg_match_all() function.

Difference between clone object and normal object

In PHP How it differs when I create cloned object in a variable and new object created using a variable with the same class
For example
$a = new classA();
$b = clone $a;
$c = new classA();
What is the difference between $b and $c ?
You should look at the following example
<?php
class classA {
public $x=0;
}
$a = new classA();
$a->x = 20;
echo $a->x."<br />";
$b = clone $a;
$a->x = 30;
echo $a->x."<br />";
echo $b->x."<br />"; // 20 because x was 20 before cloning $a to $b
$a->x = 50;
echo $a->x."<br />"; // changed to 50
echo $b->x."<br />"; // stil 20, $a
$c = new classA();
echo $c->x;
Using cloning make, you have property x in object $b the same as in object $a because cloning simple copies object. And when creating new object, you will have new object and property value will be 0.
Cloning is simple copying object because by default for objects:
$a = $b;
PHP won't do copying (as for simple types) but will point to exact place in memory.
So for simple types you use:
$a = 5;
$b = $a;
if you want to make a copy, but for objects you need to use clone:
$a = new classA();
$a->x = 20;
$b = clone $a;
to have the same effect.
You should look in manual at Object and references and Cloning to understand those things.

Is there a function like is_reference_of in php?

I'd like to be able to inquire my program as to what variable a variable is a reference of. Is there a way to do this? I looked in all the usual sources and couldn't find anything, perhaps my search terms were goofy. Thanks.
you can just compare references with === operator
Note: this only compares object references.
$obj1 = new DateTime();
$obj2 = $obj1;
if($obj2 === $obj1){
echo "Equal";
}else {
echo "Not Equal";
}
// Outputs Equal
$obj2 = new DateTime();
if($obj2 === $obj1){
echo "Equal";
}else {
echo "Not Equal";
}
// Outputs Not Equal
The only code I personally know is to directly query what a class is of, not to retrieve it:
if($var instanceof Your_Class) { }
If you know the variable is strictly a class, you can use:
get_class();
If you use the function on a non-object, it appears to return an E_WARNING. I'd suggest code such as this:
$class_known = false;
if(is_object($class))
{
$class_name = get_class($class);
$class_known = false;
}
if($class_known)
{
echo $class_name;
}
If you're dealing with objects, I believe === performs the test you want.
$obj1 = new Object;
$obj2 = $obj1;
echo ($obj1 === $obj2) ? 'same' : 'not same'; // same
$obj2 = new Object;
echo ($obj1 === $obj2) ? 'same' : 'not same'; // not same
As far as I know, there's no direct way to test if two variables point to the same thing. Something like this might work:
function is_reference_of(&$a, &$b)
{
// if an object, use strict comparison
if (is_object($a)) return $a === $b;
// definitely not a reference to each other if they aren't the same value
if ($a !== $b) return false;
$tmp = $a;
if (is_array($a))
{
$a = 0;
// if $b is no longer an array, then it must be a reference to $a
$is_ref = !is_array($b);
}
else
{
$a = !$a;
// if $b is no longer equal to $tmp, then it must be a reference to $a
$is_ref = ($b !== $tmp);
}
// make sure to reset $a back to what it was
$a = $tmp;
return $is_ref;
}
$a = 0;
$b = 0;
is_reference_of($a, $b); // false
$b = &$a;
is_reference_of($a, $b); // true
Huge disclaimer: I haven't really thought this through carefully. There could be all sorts of side effects to doing something like the above. Consider this just a proof of concept to get you started
If you are always working with arrays or classes, you could try setting a temporary field or property in one and seeing if it exists in the other, etc. That would be less prone to errors than the above code that changes the entire variable.
Note that the order of the parameters in the above function does not matter.
Update: With objects, you can use === and skip the function altogether. I've updated the function slightly to detect what type of variable is being tested and react accordingly. The disclaimer still applies.

Is it possible to delay variable implement(?)/recognize(?) in PHP?

For example:
A.php (the config file):
<?php
$a = array('name'=>'wine[$index][name]',
'value'=>'wine[$index][value]'
)
?>
B.php:
include_once(a.php)
...
//for simple
$index = 0;
$b = $a;
//actual code like
foreach($data as $index=>$value)
$b += $a
I know this example won't work, just for explaination, i wanna if it is possible (if possible, how?) to delay variable $index to take value when $b = $a ?
make "a" a function
function a($index) { global $data; return $data[$index] ... }
$b = a($index);

Categories