I want to take an array and use that array's values to populate an object's properties using the array's keynames. Like so:
$a=array('property1' => 1, 'property2' => 2);
$o=new Obj();
$o->populate($a);
class Obj
{
function Populate($array)
{
//??
}
}
After this, I now have:
$o->property1==1
$o->property2==2
How would I go about doing this?
foreach ($a as $key => $value) {
$o->$key = $value;
}
However, the syntax you are using to declare your array is not valid. You need to do something like this:
$a = array('property1' => 1, 'property2' => 2);
If you don't care about the class of the object, you could just do this (giving you an instance of stdClass):
$o = (Object) $a;
Hm. What about having something like
class Obj
{
var properties = array();
function Populate($array)
{
this->properties = $array;
}
}
Then you can say:
$o->properties['property1'] == 1
...
Related
I want to make a foreach loop like this one
foreach ($this->data['array'] as $this->data['key'] => $this->data['value'])
{
echo $this->data['value'];
}
Yet the $this->data['value'] is never created. Why is this and what am I doing wrong?
In my understanding, you have a class in which there is a variable or array name $data.
Now, you added an array in $data with an index named 'array', right?
If so, this code will work properly -
class myClass{
public $data = array(); //$data is an array
function print_array(){
foreach ($this->data['array'] as $this->data['key'] => $this->data['value'])
{
echo $this->data['value'];
}
}
}
$ob = new myClass(); // object declaration for your class
array_push($ob->data,'array'); // added a value to the $data array.
$ob->data['array'] = array(); // the newly added value is declared as an index of an array
// Now simply push values to the array named $data['array']
array_push($ob->data['array'],1);
array_push($ob->data['array'],2);
array_push($ob->data['array'],3);
$ob->print_array(); // call the print_array() function. $this will be passed to that function
Hope this will help to understand.
If you still have problem, please comment.
To have a clear understanding, you can visit this link. There are lots of simple and interesting examples explained!
Happy Coding!
I think $this is for current class object reference not for an array
foreach ($this->data['array'] as $k => $v)
{
echo $v;
$this->data['key'][] = $k;
$this->data['value'][] = $v;
}
print_r($this->data['key']);
print_r($this->data['value']);
If:
class YourClass {
private data = array(
'array' => array(
'key1' => 'val1',
'key2' => 'val2', etc.
)
);
then it should be:
foreach ($this->data['array'] as $key => $val)
{
echo $val;
// if you want to add keys and vals to data array:
$this->data[$key] = $val;
}
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.
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.
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.
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.
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'));
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' => 'user#domain.com',
'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! :)
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.
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;
}
}
How would something like this be possible:
I have an object called Player:
class Player
{
public $name;
public $lvl;
}
and I have an array of these players in: $array.
For example $array[4]->name = 'Bob';
I want to search $array for a player named "Bob".
Without knowing the array key, how would I search $array for a Player named "Bob" so that it returns the key #? For example it should return 4.
Would array_search() work in this case? How would it be formatted?
Using array_filter will return you a new array with only the matching keys.
$playerName = 'bob';
$bobs = array_filter($players, function($player) use ($playerName) {
return $player->name === $playerName;
});
According to php docs, array_search would indeed work:
$players = array(
'Mike',
'Chris',
'Steve',
'Bob'
);
var_dump(array_search('Bob', $players)); // Outputs 3 (0-index array)
-- Edit --
Sorry, read post to quick, didn't see you had an array of objects, you could do something like:
$playersScalar = array(
'Mike',
'Chris',
'Steve',
'Bob'
);
class Player
{
public $name;
public $lvl;
}
foreach ($playersScalar as $playerScaler) {
$playerObject = new Player;
$playerObject->name = $playerScaler;
$playerObjects[] = $playerObject;
}
function getPlayerKey(array $players, $playerName)
{
foreach ($players as $key => $player) {
if ($player->name === $playerName) {
return $key;
}
}
}
var_dump(getPlayerKey($playerObjects, 'Steve'));
I am trying to recurse through a multidimensional Object/Array structure to create JSON, but the following isn't working. $data is reset, but I'm not sure how to prevent this.
public function encodeJSON($data) {
foreach ($data as $key => $value) {
if (is_array($value) || is_object($value)) {
$json->$key = $this->encodeJSON($value);
} else {
$json->$key = $value;
}
}
return json_encode($json);
}
If you're trying to learn recursion that's one thing, but at least for me json_encode automatically encodes objects and arrays recursively so it's not really necessary to write the extra function.
Tested with this code:
class TestClass {
var $c1;
var $c2;
function __construct() {
$this->c1 = 'member variable 1';
$this->c2 = 8080;
}
}
$test = array('hello' => 'world', 'age' => 30,
'arr' => array('a' => 'b', 'c' => 'd'), 'obj' => new TestClass());
echo(json_encode($test));
// I get the following JSON object:
// {"hello":"world","age":30,"arr":{"a":"b","c":"d"},"obj":{"c1":"member variable 1","c2":8080}}
Is there a way to instantiate a new PHP object in a similar manner to those in jQuery? I'm talking about assigning a variable number of arguments when creating the object. For example, I know I could do something like:
...
//in my Class
__contruct($name, $height, $eye_colour, $car, $password) {
...
}
$p1 = new person("bob", "5'9", "Blue", "toyota", "password");
But I'd like to set only some of them maybe. So something like:
$p1 = new person({
name: "bob",
eyes: "blue"});
Which is more along the lines of how it is done in jQuery and other frameworks. Is this built in to PHP? Is there a way to do it? Or a reason I should avoid it?
the best method to do this is using an array:
class Sample
{
private $first = "default";
private $second = "default";
private $third = "default";
function __construct($params = array())
{
foreach($params as $key => $value)
{
if(isset($this->$key))
{
$this->$key = $value; //Update
}
}
}
}
And then construct with an array
$data = array(
'first' => "hello"
//Etc
);
$Object = new Sample($data);
class foo {
function __construct($args) {
foreach($args as $k => $v) $this->$k = $v;
echo $this->name;
}
}
new foo(array(
'name' => 'John'
));
The closest I could think of.
If you want to be more fancy and just want to allow certain keys, you can use __set() (only on php 5)
var $allowedKeys = array('name', 'age', 'hobby');
public function __set($k, $v) {
if(in_array($k, $this->allowedKeys)) {
$this->$k = $v;
}
}
get args won't work as PHP will see only one argument being passed.
public __contruct($options) {
$options = json_decode( $options );
....
// list of properties with ternary operator to set default values if not in $options
....
}
have a looksee at json_decode()
The closest I can think of is to use array() and extract().
...
//in your Class
__contruct($options = array()) {
// default values
$password = 'password';
$name = 'Untitled 1';
$eyes = '#353433';
// extract the options
extract ($options);
// stuff
...
}
And when creating it.
$p1 = new person(array(
'name' => "bob",
'eyes' => "blue"
));