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
How to Make Pdo Run Set Names Utf8 Each Time I Connect, in Zendframework
PHP - Your PHP Installation Appears to Be Missing the MySQL Extension Which Is Required by Wordpress
Remove Index.Phproute=Common/Home from Opencart
Subquery in Doctrine2 Notin Function
How to Echo Out Table Rows from the Db (Php)
Warning: Preg_Match() [Function.Preg-Match]: Unknown Modifier '/'
How to Iterate Over Non-English File Names in PHP
How to Pass Jquery Variables to PHP Variable
How to Get Insert Id in Mssql in PHP
How to Resolve "Must Be an Instance of String, String Given" Prior to PHP 7
Outputting All PHP Errors to Database Not Error_Log
Strange Behaviour with Numbers That Have a Leading Zero