Update values of all public variables of class using get_object_vars() - php

I have class with 100 public members. How can I update them in an automated way, ie without specifying their name. I have tried this and I'm getting variables but the changes made doesn't reflect on actual object. Please advice.
class foo {
public $b = 1;
public $c = 2;
function __construct()
{
$x = get_object_vars($this);
foreach ($x as $obj) {
$obj = 9;
}
}
}
$test = new foo;
echo $test->c;
It prints vale of 'c' as 2 instead of 9

function __construct()
{
$x = get_object_vars($this);
foreach ($x as $key => $value) {
$this->$key = 9;
}
}

Related

Automatically updating a PHP object value based on sum of other object values

Here is a simplified version of the problem.
class A{
public $value = 0;
}
class B{
public $values;
public $total = 0;
function __construct($values) {
foreach($values as $value){
$this->values[] = &$value;
$this->total += $value->value;
}
}
}
$a = new A;
$a->value = 10;
$b = new A;
$b->value = 20;
$x = new B(array($a, $b));
echo $x->total . "\r\n";
$b->value = 40;
echo $x->total;
The output is:
30
30
I want the total to be automatically updated to 50 without iterating on the array and recalculating the sum. Is it possible using PHP pointers?
Desired Output:
30
50
Sums cannot change if there origins change. This information is lost. However you can use the magic __set method to add additional logic to plain setting. There you can call the "calculator" to change the total.
If you do not need to keep the previous interface, you should use a real setter for value (setValue) to achieve this, as __set is not good practice.
For example:
class A
{
private $value = 0;
private $b;
public function setObserver(B $b)
{
$this->b = $b;
}
public function __get($name)
{
if ($name == 'value') {
return $this->value;
}
}
public function __set($name, $value)
{
if ($name == 'value') {
$prev = $this->value;
$this->value = $value;
if ($this->b instanceof B) {
$this->b->change($prev, $this->value);
}
}
}
}
class B
{
public $total = 0;
public function __construct($values)
{
foreach ($values as $v) {
if ($v instanceof A) {
$this->total += $v->value;
$v->setObserver($this);
}
}
}
public function change($prevValue, $newValue)
{
$this->total -= $prevValue;
$this->total += $newValue;
}
}
Prints:
30
50

PHP - can't add objects into array

I've created a simple class:
class Event {
var $a;
var $b;
var $c;
function __construct($a, $b, $c)
{
$this->a= $a;
$this->b = $b;
$this->c= $c;
}
}
Then I've created another class which extends Thread:
class WorkerThread extends Thread
{
private $myUrl;
private $eventsArr;
private $counterDebug;
private $postdata;
public function __construct($myUrl, $postdata)
{
$this->myUrl = $myUrl;
$this->postdata = $postdata;
$this->eventsArr = array();
$this->counterDebug=0;
}
public function run()
{
$flag=false;
foreach ($json as $key => $value) {
$this->counterDebug++;
/* Death event */
$event= new Event($a, $b, $c);
array_push($this->eventsArr, $event);
}
}
}
}
echo (count($this->eventsArr));
echo (json_encode($event));
echo ("\n" . $this->counterDebug);
if($flag && count($this->events)>0){
...
When trying to add new created objects into the array, it stays empty.
What I've figured from debugging:
1) The objects are created.
2) neither eventsArr[]= $event, nor array_push are working.
3) I've set a counter that verifies the objects are being created and should be added to the array.
What am I doing wrong?
p.s-
I've removed irrelevant parts of code in order to simplify things.
i think you should create temp array which have all your events and then give it to $eventsArr like this.
$temp = array();
foreach ($json as $key => $value) {
$this->counterDebug++;
/* Death event */
$event= new Event($a, $b, $c);
$temp[] = $event;
}
$this->eventsArr = $temp;
OR
foreach ($json as $key => $value) {
$this->counterDebug++;
/* Death event */
$event= new Event($a, $b, $c);
$this->eventsArr[] = $event;
}

getStaticProperties of ReflectionClass returns inherited class properties

This is my code:
class A {
public static $a = '1';
}
class B extends A {
public static $b = '2';
}
$refclass = new ReflectionClass('B');
foreach ($refclass->getStaticProperties() as $key => $property)
echo $key;
This code prints $a and $b.
Is there any way to get the class properties without getting the inherited parents class properties.
foreach ($refclass->getStaticProperties() as $key => $property)
if ($refclass->getProperty($key)->getDeclaringClass() == $refclass) {
echo $key;
}
}
Or, perhaps more elegant:
$props = array_filter($refclass->getProperties(ReflectionProperty::IS_STATIC), function ($prop) use ($refclass) {
return $prop->getDeclaringClass() == $refclass;
});

Sharing array inside object through classes in php

My problem is that I have an object shared through two classes that contains an array inside of it and along the script, someone will request some of the classes the value and a foreach loop will change such value and I want this change to affect every reference of the value.
class bar {
protected $obj;
function __construct(&$obj) {
$this->obj = $obj;
}
public function output() {
print_r($this->obj->value);
}
}
class foo {
protected $obj;
function __construct(&$obj) {
$this->obj = $obj;
}
public function val() {
$result = array();
foreach($this->obj->value as $it){
$result[] = $it;
}
return $result;
}
}
// Shared Object
$obj = new stdClass();
// Default value
$obj->value = array('teste', 'banana', 'maca');
// Class 1
$bar = new bar($obj);
// Class 2
$foo = new foo($obj);
// Someone requests from class 2 the values and changes it
$new = $foo->val();
$new[] = 'abc';
// Class 1 outputs the value
$bar->output(); // this will print the default value. I want this to also have 'abc' value.
The main problem, is that you are building a new array at foo:val, you must return the original object to be modified.
I suggest use ArrayObject, have the same behavior of array but is a object, then always is passed by reference.
<?php
class MyArrayObject extends ArrayObject {
public function replace(Array $array)
{
foreach($this->getArrayCopy() as $key => $value) {
$this->offsetUnset($key);
}
foreach ($array as $key => $value) {
$this[$key] = $value;
}
}
}
class bar {
protected $obj;
function __construct(MyArrayObject $obj) {
$this->obj = $obj;
}
public function output() {
print_r($this->obj);
}
}
class foo {
protected $obj;
function __construct(MyArrayObject $obj) {
$this->obj = $obj;
}
public function val() {
$result = array('foo', 'bar');
$this->obj->replace($result);
return $this->obj;
}
}
// Shared Object
$obj = new MyArrayObject(array('teste', 'banana', 'maca'));
// Class 1
$bar = new bar($obj);
// Class 2
$foo = new foo($obj);
// Someone requests from class 2 the values and changes it
$new = $foo->val();
$new[] = 'abc';
// Class 1 outputs the value
$bar->output(); // this will print the default value. I want this to also
var_dump($obj);

variable variables + objects in fields

I am trying to do something with variable variables and I got stuck on an object problem. Imagine this class setup:
class A
{
public $field = 10;
}
class B
{
public $a;
public function __construct()
{
$this->a = new A();
}
}
Now everyone knows that this pice of code works:
$a = new A();
$var = 'field';
echo $a->$var; // this will echo 10
Is there any possibility I could make something like this work?:
$b = new B();
$var = 'a->field';
echo $b->$var; // this fails
Note: any option which does not use eval function?
How about using a closure?
$getAField = function($b) {
return $b->a->field;
};
$b = new B();
echo $getAField($b);
Though, it's only possible in newer versions of PHP.
Or, as a more generic version, something like this:
function getInnerField($b, $path) { // $path is an array representing chain of member names
foreach($path as $v)
$b = $b->$v;
return $b;
}
$b = new B();
echo getInnerField($b, array("a", "field"));
You can write a custom __get method on your class to access the childrens property. This works:
class A
{
public $field = 10;
}
class B
{
public $a;
public function __construct()
{
$this->a = new A();
}
public function __get($property) {
$scope = $this;
foreach (explode('->', $property) as $child) {
if (isset($scope->$child)) {
$scope = $scope->$child;
} else {
throw new Exception('Property ' . $property . ' is not a property of this object');
}
}
return $scope;
}
}
$b = new B();
$var = 'a->field';
echo $b->$var;
Hope that helps
I don't recommend it, but you could use eval:
$b = new B();
$var = 'a->field';
eval( 'echo $b->$'.$var );
This should also work I guess:
$b = new B();
$var1 = 'a';
$var2 = 'field'
echo ($b->$var1)->$var2;

Categories