tags:

views:

194

answers:

6

Hi All

What is the best way of creating and populating an Object from values passed in from a form?

If for example, i have a class Car with properties Colour, Model, Make, Year and a method Save, which will either insert or update the record.

I then have a form that has fields for all these values and it is submitted. I want to create an instance of class Car with the posted values and then call the Save method. All good and well.

But what is the best way of assigning the posted values to the objects internal properties. Assuming this is a simplified scenario and the actual situation would have many more properties, making individual Set calls long-winded.

Is it best to simply call the Set method for each one? Or pass in an array to a method (or the constructor) which then calls the Set methods? Or some other way?

Any advice on best practices is appreciated

Cheers Stuart

+2  A: 
soulmerge
Am i right in thinking that the implementation of this method is going to be (near enough) identical to Chaos' suggestion above?
Stuart
Yes, the implementation would be the same. Expanded answer to explain why I suggested this approach.
soulmerge
Are you sure you can access private members? __set_state is supposed to be static function, $this is not defined in there, you are instead creating a new object instance and then assigning variables to it. So, please explain how can you access private variables from within the function?
Anti Veeranna
`private` members are accessible from everywhere within the class in which they are defined, you can write a little test code if you want. The only private members that you cannot access are inherited ones.
soulmerge
private members are NOT accessible from your static __set_state function, because $this does not exist inside a static method.I dare you to write some test code to prove me wrong.
Anti Veeranna
@Anti Veeranna: Updated answer. `private` means "this member is only visible from within the class", not "from within the object". And you should NOT post such claims before verifying them. http://php.net/manual/en/language.oop5.visibility.php
soulmerge
Is it possible to put this method into a base class for all other classes to extend to stop duplicating the set_state method for every class?
Stuart
Ok, soulmerge, I was wrong, you were right, it really does work like this. I learned something new today :)
Anti Veeranna
@Anti Veeranna: It's not that you were wrong or I was right. It was about your way of arguing. We are engineers, unlike politicians, we do not need to argue by repeating our statements over and over again, and unlike many others we (as *software* engineers) can verify some claims quickly and easily (using less than 1000 key strokes in this case.)
soulmerge
+1  A: 

If the properties are public:

foreach($_POST as $key => $value)
    $obj->$key = $value;

If they require setters:

foreach($_POST as $key => $value) {
    $set = 'Set' . $key;
    $obj->$set($value);
}
chaos
+1  A: 

Well, you can convert the post array to an object in one step...

$mypostobject = (object) $_POST;
echo $mypostobject->Colour;

EDIT: added link to PHP docs. http://uk.php.net/manual/en/language.types.object.php

If you want to do this with your own class of object, then some kind of constructor or function that takes the post array and set up your class would be in order.

class MyCar {
  public function __construct($postdata) 
  {
    $this->Colour = $postdata['Colour'];
    // etc
  }
};

$car = new MyCar($_POST);
rikh
A: 

create a constructor which will take all the attributes

class Car {
  // private members …
  public function __construct($color, $type, $model, $make) {
    // assign your values here
  }
  // other methods
};

if you are dealing with associative arrays, you can also use a constructor with an array as argument:

public function __construct($car_properties) {}

and then loop your properties with

foreach($car_properties as $property => $value) {
  if(isset($value)) $this->property = $value
}

be sure to sanitize/validate your input beforehand! (can’t stress this often enough)

knittl
I have thought about this approach but when you are (potentially) dealing with a lot of properties this gets very messy.
Stuart
+2  A: 

You can use a bit of Reflection magic:

public function loadFromArray($array) {
    $class = new ReflectionClass(get_class($this));
    $props = $class->getProperties();
    foreach($props as $p) {
         if (isset($array[$p->getName()])
              $p->setValue($this, $array[$p->getName]);
    }
}

You can implement this method in a base class and make all yout object inherit from that, so you have this functionality in every object without repeating yourself in any class.

Davide Gualano
A: 

In case the object that you're posting may become more complex than a flat list of properties in the future (think nesting, arrays as values etc.), you could first create a JavaScript object on the client side and post it as JSON inside a single parameter. Then you can simply deserialize the JSON string into a PHP object. PHP 5+ has built-in support for JSON deserialization. Using JSON would allow you to be flexible in how complex your object can be.

Ates Goral