I have an object $obj as
$obj->{' Property1'} = " value1";
$obj->{'Property2 '} = "value2 ";
I want to get this object $obj as
$obj->{'Property1'} = "value1";
$obj->{'Property2'} = "value2";
I am able to trim all the values using
foreach($obj as $prop => &$val)
{
$val = trim($val);
}
but doing this (below) causing an error
foreach($obj as &$prop => &$val)
{
$prop = trim($prop);
$val = trim($val);
}
Please tell a solution.
Thanks in advance.
You can't reference a key.
What you have to do is unset it, and set the trimmed version like this:
<?php
$obj = new stdClass;
$obj->{' Property1'} = " value1";
foreach($obj as $prop => $val)
{
unset($obj->{$prop});
$obj->{trim($prop)} = trim($val);
}
var_dump($obj);
A little comment to Daan's answer. In his case script will fall into infinite loop if $obj have more than one property. So a working code looks like this.
<?php
$obj = new stdClass;
$obj->{' Property1'} = " value1";
$obj->{'Property2 '} = "value2 ";
$newObj = new stdClass;
foreach($obj as $prop => $val)
{
$newObj->{trim($prop)} = trim($val);
}
$obj = $newObj;
unset($newObj);
var_dump($obj);
Because you're trying to trim the property of the object. You can't do that.
That would work for an array, but not for an object. If you need to alter the properties of an object you need to change the properties of the class.
Related
I'm trying to remove stdClass property by reference. Because I don't know how deeply the property is nested, a reference is made in the loop. But the unset method does not remove variables by reference. How can I resolve it without just setting a null value?
<?php
$data = new stdClass();
$data->foo = new stdClass();
$data->foo->bar = 'value';
$pathToRemove = 'foo.bar';
$dataReference = &$data;
foreach (explode('.', $pathToRemove) as $field) {
$dataReference = &$dataReference->$field;
}
unset($dataReference);
var_dump($data);
Loop over all the elements except the last. Then use the last element as the field to delete.
$pathArray = explode('.', $pathToRemove);
$lastField = array_pop($pathArray);
$dataReference = &$data;
foreach ($pathArray as $field) {
$dataReference = &$dataReference->{$field};
}
unset($dataReference->{$lastField});
unset($dataReference); // don't need the reference variable any more
The problem is simple:
I have an object like
{a:'A', b:'B'}
and i want it to be like
{a:'A', new_a:'A', b:'B', new_b:'B'}
The code used is:
<?php
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
The output is:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 21290 bytes) in /path/to on line 9
Line 9 is this:
$obj->{'new_'.$field} = $value
I do have alternatives to solve the problem, but i don't understand why this particular code generates this error.
Does anybody know the reason for this error, eventually an explanation.
Thank you!
The problem is, as you're iterating the source object properties, you're adding more properties to the source object, so the foreach loop can never end.
You can see this happening by adding a var_dump call to the loop:
foreach ($obj as $field => $value)
{
$obj->{'new_'.$field} = $value;
var_dump($obj);
}
Results in:
object(stdClass)#1 (29) {
["a"]=>
string(1) "A"
["b"]=>
string(1) "B"
["new_a"]=>
string(1) "A"
["new_b"]=>
string(1) "B"
["new_new_a"]=>
string(1) "A"
["new_new_b"]=>
string(1) "B"
["new_new_new_a"]=>
...
Instead, create a new object and replace the old one:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$newObj = new stdClass();
// Copy old properties
foreach ($obj as $field => $value) {
$newObj->{$field} = $value;
}
// Create new properties
foreach($obj as $field => $value) {
$newObj->{'new_' . $field} = $value;
}
Or even:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$newObj = new stdClass();
// Copy old properties and create new
foreach ($obj as $field => $value) {
$newObj->{$field} = $value;
$newObj->{'new_' . $field} = $value;
}
I'm not sure why there are so many suggestions to create a second object to work around this. In my opinion, the simplest thing to do would just be to grab the fields before the loop with get_object_vars, so that you're only iterating over the initial fieldset:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$fields = get_object_vars($obj);
foreach ($fields as $field => $value) {
$obj->{'new_'.$field} = $value;
}
See https://eval.in/937616
You are appending more data unto the same object you are Looping through, using also the properties of the same Object.... To counter that, you can just do something like this:
<?php
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = clone $obj;
foreach($obj as $field=>$value)
{
$key = 'new_'.$field;
$obj2->{$key} = $value;
}
// IF YOU STILL WISH TO HAVE $obj AS YOUR MAIN OBJECT,
// YOU CAN AS WELL RE-CLONE $obj2 INTO $obj AND DELETE $obj2 LIKE SO:
$obj = $obj2;
unset($obj2);
var_dump($obj);
var_dump($obj2);
UPDATE
If you wish to be consistent (ie: without Cloning) and also for reasons that #Dan has mentioned, You could simply use stdClass() like so:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$key = 'new_'.$field;
$obj2->{$field} = $value;
$obj2->{$key} = $value;
}
$obj = clone $obj2;
unset($obj2);
var_dump($obj);
// YIELDS:
object(stdClass)[3]
public 'a' => string 'A' (length=1)
public 'new_a' => string 'A' (length=1)
public 'b' => string 'B' (length=1)
public 'new_b' => string 'B' (length=1)
AS told you have to create another $obj
instead of using the object inside the loop
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$obj2->{$field} = $value;
$obj2->{'new_'.$field} = $value;
}
$obj = $obj2;
echo '<pre>';
var_dump($obj);
your code is stuck in a infinite loop because if you have:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
In each iteration, you add a new position into the object, and this position must be iterated by the foreach.
You can clone the original object and iterate the clone, into the iteration you can add the new position to the original object.
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$objcopy = clone $obj;
foreach($objcopy as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
Is it possible to set property values of an object using a foreach loop?
I mean something equivalent to:
foreach($array as $key=>$value) {
$array[$key] = get_new_value();
}
EDIT: My example code did nothing, as #YonatanNir and #gandra404 pointed out, so I changed it a little bit so it reflects what I meant
You can loop on an array containing properties names and values to set.
For instance, an object which has properties "$var1", "$var2", and "$var3", you can set them this way :
$propertiesToSet = array("var1" => "test value 1",
"var2" => "test value 2",
"var3" => "test value 3");
$myObject = new MyClass();
foreach($propertiesToSet as $property => $value) {
// same as $myObject->var1 = "test value 1";
$myObject->$property = $value;
}
Would this example help at all?
$object = new stdClass;
$object->prop1 = 1;
$object->prop2 = 2;
foreach ($object as $prop=>$value) {
$object->$prop = $object->$prop +1;
}
print_r($object);
This should output:
stdClass Object
(
[prop1] => 2
[prop2] => 3
)
Also, you can do
$object = new stdClass;
$object->prop1 = 1;
$object->prop2 = 2;
foreach ($object as $prop=>&$value) {
$value = $value + 1;
}
print_r($object);
You can implement Iterator interface and loop through the array of objects:
foreach ($objects as $object) {
$object->your_property = get_new_value();
}
Hacked away at this for a few hours and this is what i finally used. Note the parameters passed by reference in two places. One when you enter the method and the other in the foreach loop.
private function encryptIdsFromData(&$data){
if($data == null)
return;
foreach($data as &$item){
if(isset($item["id"]))
$item["id"] = $this->encrypt($item["id"]);
if(is_array($item))
$this->encryptIdsFromData($item);
}
}
How can I rename an object property without changing the order?
Example object:
$obj = new stdClass();
$obj->k1 = 'k1';
$obj->k2 = 'k2';
$obj->k3 = 'k3';
$obj->k4 = 'k4';
Example rename by creating new property:
$obj->replace = $obj->k3;
unset($obj->k3);
Result:
( k1=>k1, k2=>k2, k4=>k4, replace=>k3 )
See the problem?
Simply recreating the object property causes the order to change.
I had a similar issue with arrays and came up with this solution:
Implemented solution for arrays
function replaceKey(&$array, $find, $replace)
{
if(array_key_exists($find, $array)){
$keys = array_keys($array);
$i = 0;
$index = false;
foreach($array as $k => $v){
if($find === $k){
$index = $i;
break;
}
$i++;
}
if ($index !== false) {
$keys[$i] = $replace;
$array = array_combine($keys, $array);
}
}
}
Looking for something similar to this but a function that will work on objects.
Can't seem to find any documentation on object property position indexes.
So, readd your properties
$obj = new YourClass();
$backup = [];
foreach ($obj as $key => $value)
{
$backup[$key] = $value;
unset($obj->$key);
}
replaceKey($backup, $find, $replace);
foreach ($backup as $key => $value)
{
$obj->$key = $value;
}
Since you have a function for your arrays, why dont you do something like :
$array = (array) $obj;
$replacedKeyArray = replaceKey($array);
$newObject = (object) $replacedKeyArray;
I've got this function:
$request = array("setNewDoc", "setNewFile");
foreach($request as $key => $val) {
$result = $controller->setNewDoc($key);
$smarty->assign('result', $result);
$index = TPL_DIR . 'docs.tpl';
}
Is it possible to make this loop dynamic with putting a variable in my pointer? The $keys in my array are also the name of the function.
Like $controller->$variable($key);
Like this(pseudo code)
$result = array("setNewDoc", "setNewFile");
foreach($request as $key => $val) {
$result = $controller->set$key($request);
$smarty->assign('result', $result);
// $key = setNewDoc or setNewFile
$index = TPL_DIR . $key . '.tpl';
}
Yes you can.
You can use it to cast a new object or to acces a property.
For exmaple
$classname = foo;
$prop=name;
$myObject = new $classname();
$myObject->{$prop} or a function: $myObject->{$prop}()
You can even foreach over an object's properties
foreach ($myObject as $key => $value) {
print $key // would be name
print $value // would be the value of the property
}
Yes that's possible and it is in fact pretty easy:
<?php
class MyClass {
function myMethod()
{
echo "Hello World";
}
}
$obj = new MyClass();
$dynamicVar = 'Method';
$obj->{'my' . $dynamicVar}();
enclose your method name with curly brackets and you can do some string concatenation inside. Once everything inside the the brackets is processed it will eventually used as your method name.
For your specific use case you would write something like
<?php
$result = array("setNewDoc", "setNewFile");
foreach($request as $key => $val) {
$result = $controller->{'set' . $key}($request);
$smarty->assign('result', $result);
// $key = setNewDoc or setNewFile
$index = TPL_DIR . $key . '.tpl';
}