16

Is it possible to set multiple properties at a time for an object in php? Instead of doing:

$object->prop1 = $something;
$object->prop2 = $otherthing;
$object->prop3 = $morethings;

do something like:

$object = (object) array(
    'prop1' => $something,
    'prop2' => $otherthing,
    'prop3' => $morethings
);

but without overwriting the object.

6
  • 3
    Why would you want to obfuscate what the code is doing in this way? At some point in the future someone (maybe you) will need to read this code and doing something like this will only make it more difficult to understand. Commented May 3, 2012 at 15:49
  • Why not just paste this into a php file and run it? Instead of asking here if it would work, just try it yourself. Commented May 3, 2012 at 15:50
  • 2
    Just create a helper function to do it for you. Pass in the object and array. Commented May 3, 2012 at 15:51
  • It looks awful and it's more code, why would you need that? Commented May 3, 2012 at 15:51
  • 1
    Take a look at this: bugs.php.net/bug.php?id=53266 Commented May 3, 2012 at 15:52

7 Answers 7

25

Not like the way you want. but this can be done by using a loop.

$map =  array(
    'prop1' => $something,
    'prop2' => $otherthing,
    'prop3' => $morethings
);

foreach($map as $k => $v)
    $object->$k = $v;

See only 2 extra lines.

Sign up to request clarification or add additional context in comments.

4 Comments

It's not 2 more lines, but 50% more lines; worse if there are only two properties to set. Actually it's 3 lines if we don't cheat and use the bug-preventors { and }.
@Pacerier I hope you're trolling. In a real use-case such arrays could hold hundreds of values. Of course if you hand only 2 values, it's extra work because it's three lines. But if you work with an array with 358 values, this solution stays at three lines.
@Holonaut, It's meant to be a serious comment not a troll comment. Sure, there are bound to be use cases where there are hundreds of values, but many use cases have just two, three, or four values.
@Pacerier You can't be the judge of which use case occurs more frequently. OP's question was about setting multiple properties and the answer was valid. The fact that his example array had 3 values is simply incidental and should be treated as anything ranging from 2 to *. The answer was correct in achieving this and you're just not seeing the big picture.
12

You should look at Object Oriented PHP Best Practices :

"since the setter functions return $this you can chain them like so:"

 $object->setName('Bob')
        ->setHairColor('green')
        ->setAddress('someplace');

This incidentally is known as a fluent interface.

3 Comments

This is a completely different thing. He is talking about shortcuts for creating variable properties and that has nothing to do with your answer.
If you had been talking about using public function __set($k, $v){ $this->$k=$v; return $this;}, then it still wouldn't work because (($obj->k="v")->k2)="v2"; is syntax error.
Why does this have 8 upvotes? It has nothing to do with the question that was asked... 🤔
5

I would recommend you don't do it. Seriously, don't.

Your code is much MUCH cleaner the first way, it's clearer of your intentions, and you aren't obfocusing your code to the extent where sometime in the future someone would look at your code and think "What the hell was the idiot thinking"?

If you insist on doing something which is clearly the wrong way to go, you can always create an array, iterate it and set all the properties in a loop. I won't give you code though. It's evil.

1 Comment

Not true. Other languages have this syntax and they are hailed as clean code. It depends on how you use it.
3

You could write some setters for the object that return the object:

public function setSomething($something)
{
 $this->something = $something;
 return $this; //this will return the current object
}

You could then do:

$object->setSomething("something")
       ->setSomethingelse("somethingelse")
       ->setMoreThings("some more things");

You would need to write a setter for each property as a __set function is not capable of returning a value.

Alternatively, set a single function to accept an array of property => values and set everything?

public function setProperties($array)
{
  foreach($array as $property => $value)
  {
    $this->{$property} = $value;
  }
  return $this;
}

and pass in the array:

$object->setProperties(array('something' => 'someText', 'somethingElse' => 'more text', 'moreThings'=>'a lot more text'));

1 Comment

"need to write a setter for each property as a __set function is not capable of returning a value". See my answer for a way around this.
1

I realise this is an old question but for the benefit of others that come across it, I solved this myself recently and wanted to share the result

<?php
    //Just some setup
    header('Content-Type: text/plain');
    $account = (object) array(
        'email' => 'foo',
        'dob'=>((object)array(
            'day'=>1,
            'month'=>1,
            'year'=>((object)array('century'=>1900,'decade'=>0))
        ))
    );
    var_dump($account);
    echo "\n\n==============\n\n";

    //The functions
    function &getObjRef(&$obj,$prop) {
        return $obj->{$prop};
    }

    function updateObjFromArray(&$obj,$array){
        foreach ($array as $key=>$value) {
            if(!is_array($value))
                $obj->{$key} = $value;
            else{
                $ref = getObjRef($obj,$key);
                updateObjFromArray($ref,$value);
            }
        }
    }

    //Test
    updateObjFromArray($account,array(
        'id' => '123',
        'email' => '[email protected]',
        'dob'=>array(
            'day'=>19,
            'month'=>11,
            'year'=>array('century'=>1900,'decade'=>80)
        )
    ));
    var_dump($account);

Obviously there are no safeguards built in. The main caveat is that the updateObjFromArray function assumes that for any nested arrays within $array, the corresponding key in $obj already exists and is an object, this must be true or treating it like an object will throw an error.

Hope this helps! :)

Comments

0

I wouldn't actually do this....but for fun I would

$object = (object) ($props + (array) $object);

you end up with an stdClass composed of $objects public properties, so it loses its type.

1 Comment

This overrides the object which fails to meet the requirement of the question. $object === $old_object is no longer true.
0

Method objectThis() to transtypage class array properties or array to stdClass. Using direct transtypage (object) would remove numeric index, but using this method it will keep the numeric index.

public function objectThis($array = null) {
    if (!$array) {
        foreach ($this as $property_name => $property_values) {
            if (is_array($property_values) && !empty($property_values)) {
                $this->{$property_name} = $this->objectThis($property_values);
            } else if (is_array($property_values) && empty($property_values)) {
                $this->{$property_name} = new stdClass();
            }
        }
    } else {
        $object = new stdClass();
        foreach ($array as $index => $values) {
            if (is_array($values) && empty($values)) {
                $object->{$index} = new stdClass();
            } else if (is_array($values)) {
                $object->{$index} = $this->objectThis($values);
            } else if (is_object($values)) {
                $object->{$index} = $this->objectThis($values);
            } else {
                $object->{$index} = $values;
            }
        }
        return $object;
    }
}

2 Comments

the explanation preceding the code sample could use some improvement
What on Earth is a transtypage?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.