PHP - Indirect Modification of Overloaded Property

PHP - Indirect modification of overloaded property

Nice you gave me something to play around with

Run

class Sample extends Creator {

}

$a = new Sample ();
$a->role->rolename = 'test';
echo $a->role->rolename , PHP_EOL;
$a->role->rolename->am->love->php = 'w00';
echo $a->role->rolename , PHP_EOL;
echo $a->role->rolename->am->love->php , PHP_EOL;

Output

test
test
w00

Class Used

abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}

public function __set($name, $value) {
$this->{$name} = new Value ( $name, $value );
}

}

class Value extends Creator {
private $name;
private $value;
function __construct($name, $value) {
$this->name = $name;
$this->value = $value;
}

function __toString()
{
return (string) $this->value ;
}
}

Edit : New Array Support as requested



class Sample extends Creator {

}

$a = new Sample ();
$a->role = array (
"A",
"B",
"C"
);

$a->role[0]->nice = "OK" ;

print ($a->role[0]->nice . PHP_EOL);

$a->role[1]->nice->ok = array("foo","bar","die");

print ($a->role[1]->nice->ok[2] . PHP_EOL);

$a->role[2]->nice->raw = new stdClass();
$a->role[2]->nice->raw->name = "baba" ;

print ($a->role[2]->nice->raw->name. PHP_EOL);

Output

 Ok die baba

Modified Class

abstract class Creator {
public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}
return $this->{$name};
}

public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;

}

}

class Value {
private $name ;
function __construct($name, $value) {
$this->{$name} = $value;
$this->name = $value ;
}

public function __get($name) {
if (! isset ( $this->{$name} )) {
$this->{$name} = new Value ( $name, null );
}

if ($name == $this->name) {
return $this->value;
}

return $this->{$name};
}

public function __set($name, $value) {
if (is_array ( $value )) {
array_walk ( $value, function (&$item, $key) {
$item = new Value ( $key, $item );
} );
}
$this->{$name} = $value;
}

public function __toString() {
return (string) $this->name ;
}
}

PHP Indirect modification of overloaded property - With ARRAYS

Modify your __get magic method to return a reference to the property stored in the array. The notice is saying that you are getting a copy of $this->data[fields] by value and appending something to it. You are appending to a copy of the fields variable, not the actual fields stored in the class. Which would have no effect on the variable stored in the class.

You should also either throw an exception when you try to get a key that doesn't exist (similar to the notice undefined variable) or create an index and return the reference to that. This example uses the latter.

Example:

public function &__get($name)
{
if (!array_key_exists($name, $this->data))
{
$this->data[$name] = null;
}
return $this->data[$name];
}

Demo: https://3v4l.org/sdIWH

What causes Notice: Indirect modification of overloaded property?

What version are you using?

PRE v2.0: In this case changing the variable does not "make the code work as it should*" and you'll be missing your breadcrumbs. You should not change the variable - it should be left as $this->data. You just need to initialize the property first like this:

$this->data['breadcrumbs'] = array();

Then afterward you can modify the array. The product controller should already have that line so I'm assuming you've modified the core code.

POST v2.0+: The variable should indeed to $data['breadcrumbs'] and not a class property. Again, it looks like someone has modified the core code and introduced this bug.

Try not to modify core code unless you're sure you know what you're doing.

Indirect modification of overloaded property Illuminate\Http\Request::$values has no effect

I refactord my code to do the dame but with an new array instead of filling the existing $request

foreach ($request->values as $id => $value) {
$values[$id][0] = $request->values[$id][0];
for ($i = 1; $i <= 4; $i++) {
if (isset($this->repository->getById($request->id)->values[$id][$i])) {
$values[$id][$i] = $this->repository->getById($request->id)->values[$id][$i];
} else {
$values[$id][$i] = '';
}
}
}

PHP + Laravel: Indirect modification of overloaded element of Illuminate\Support\Collection has no effect

Hope it helps:

  $clients = $this->data();
foreach ($clients as $cIndex => $client) {
foreach ($client['returns'] as $rIndex => $return) {
if ($return['valueType'] === "absolute return" && $return["returnMethod"] === "time-weighted") {
foreach ($return as $key => $value) {
if (is_numeric($value)) {
$return[$key] = $value * 100;
}
}
$client['returns'][$rIndex] = $return;
}
}
$clients[$cIndex] = $client;
}

If you prefer to use map:

  $clients = collect($this->data())
->map(function ($client) {
$client["returns"] = collect($client["returns"])
->map(function ($return) {
if ($return["valueType"] === "absolute return" && $return["returnMethod"] === "time-weighted") {
$return = collect($return)
->map(function ($value) {
return is_numeric($value) ? $value * 100 : $value;
})->toArray();
}
return $return;
})->toArray();
return $client;
})->toArray();

Indirect modification of overloaded property App\Dossier::$program has no effect

The problem is that calling $dossier->program does not actually access the property directly in Eloquent type models but rather calls a __get method.

That get method does not return a reference to the property. What you should do is grab the original property, modify it and then put it back:

$dossier=Dossier::where('_id',(int)$request->input('dossier_id'))->first();
$originalProgram = $dossier->program;
$originalProgram[$request->input('program')]['cities'][$request->input('city')]['services'][$request->input('service')][$request->input('name')]=$request->input('value');
$dossier->program = $originalProgram;
$dossier->save();

Getting Indirect modification of overloaded property has no effect notice

This behavior has been reported as a bug a couple times:

  • https://bugs.php.net/bug.php?id=42030
  • https://bugs.php.net/bug.php?id=41641

It is unclear to me what the result of the discussions was although it appears to have something to do with values being passed "by value" and "by reference". A solution that I found in some similar code did something like this:

function &__get( $index )
{
if( array_key_exists( $index, self::$_array ) )
{
return self::$_array[ $index ];
}
return;
}

function &__set( $index, $value )
{
if( !empty($index) )
{
if( is_object( $value ) || is_array( $value) )
{
self::$_array[ $index ] =& $value;
}
else
{
self::$_array[ $index ] =& $value;
}
}
}

Notice how they use &__get and &__set and also when assigning the value use & $value. I think that is the way to make this work.



Related Topics



Leave a reply



Submit