Consider following code:
$ob=new MyObject();
$ob->name=$_GET['name'];
$ob->email=$_GET['email'];
...
$ob->foo=$_GET['foo'];
Is there any cleaner way (language mechanism) to populating an object's property with an associative array. (without using foreach or similar constructs)?
As this answer states, you can do:
$ob = (Object) $a;
Only foreach? You can other loop: while, for. What about goto?
Also you can use some functions without obvious loop.
$object = new MyObject();
$array = array('foo' => 1, 'baz' => 2);
array_walk($array, function ($value, $field)use($object){
$object->$field = $value;
});
Related
My question is what is a neat way to obtain an array of objects from an array of classes.
The array of classes I get by using array_filter() on get_declared_classes().
EDIT:
My own attempts were pretty correct, the thing was I forgot to return value of in_array() in callback function :
$classes_array = array_filter(
get_declared_classes(),
function($class_name){
return in_array('IItem', class_implements($class_name));
}
$objects_array;
foreach($classes_array as $class){
$objects_array[] = new $class();
}
You can use array_map(), and refer to Creating PHP class instance with a string
$objects = array_map(function($v){
return new $v();
}, get_declared_classes());
In JS you could have something like this:
var a = [1, 2, 3];
a.myProp = false;
This is possible because in js array are actually objects.
What I'm trying to do is to implement the same, but in PHP.
The closest solution I've found is to use the ArrayObject class, but the main problem of this "solution" is that it is object and when you check with is_array or try to use other specific array method it will return false or throw error.
Is there any magic php method like __construct or sth similar for arrays?
In general - I want to add some kind of a flag separated from the array values. For example:
$a = [1, 2, 3];
$a.alreadyIterated = false;
foreach ($a as $item) {
...
}
$a.alreadyIterated = true;
...
if (!$a.alreadyIterated) {
foreach($a as $item) {...}
}
This is somewhat possible via creating your own class:
class PropArray implements ArrayAccess, Iterator {
public $alreadyIterated = false;
protected $a = []; # internal array for iterable values
# add required methods from the interfaces, pretty easy
}
Instances will still be objects, but can be iterated like arrays and tested via is_array($obj) || $obj instanceof Traversable.
I've been trying to write a recursive function that would reorder an array of objects based on the order provided by another array (simple, numeric array).
I want to use this sorting function to sort an array of objects by a 'template' array that would hold only one property of each object present in the array to sort, e.g.
$template = ['A', 'B', 'C']
Array to sort:
$myArray = [
new Element('B'),
new Element('C'),
new Element('A'),
]
class Element
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
I was not successful. Perhaps you might have an idea about how to apprach this task?
I don't see how recursion would help you with that task. This is how you can use the built in sort functions:
usort($myArray, function(Element $a, Element $b) use ($template) {
return array_search($a->name, $template) - array_search($b->name, $template);
});
usort sorts by given comparison callback
I added the Element type hint to the callback because the sort function will only work with arrays of Element objects
array_search returns the key for the given name property value within the $template array. If the value does not exist in the array, it will be placed at the beginning, because the result false is coerced to 0.
I also managed to do the sorting using recursion - here it is:
function orderRecursively($template, $myArray, &$ordered)
{
foreach($myArray as $k => $v) {
if ($myArray[$k]->name == $template[0]) {
$ordered[] = $myArray[$k];
array_splice($template, 0, 1);
}
}
if (!empty($template)) orderRecursively($template, $myArray, $ordered);
}
$ordered = [];
order($template, $myArray, $ordered);
$ordered would then hold the sorted array of objects.
Still, I find #fschmengler's answer more elegant.
I have an array that I access like this:
$item['id'];
What can I do to the array to access it like this instead?
$item->id
Use this code:
$item = (object) $item;
echo $item->property;
The -> syntax is for objects, not associative arrays. You can use the (object) cast operator to cast an array into an object of the class stdClass though.
Cast it to (a stdClass) object:
$item = (object) $item;
If that array is coming from a database, such as mysql you can fetch objects instead of arrays with mysql_fetch_object() or set the flag PDO::FETCH_OBJ if you are using PDO.
Maybe it is not relevant to you however ...
You need to convert it into an object
$item = (object) $item;
echo $item->id;
As stated in the title, How do you perform an array_unshift() on a arrayObject, array_push() is obtained by doing an arrayObject->append() but what about unshift ?
Edit: What I've forgot to mention is that i also need in this particular case to preserve existing keys.
The API of ArrayObject does not have any function to accomplish this directly. You have several other options:
Manually move each element by 1, and set your new value at index 0 (only if you have a numerically index ArrayObject).
$tmp = NULL;
for ($i = 0; $arrayObject->offsetExists($i + 1); $i++) {
$tmp = $arrayObject->offsetGet($i + 1);
$arrayObject->offsetSet($i + 1, $arrayObject->offsetGet($i));
}
$arrayObject->offsetSet($i, $tmp);
$arrayObject->offsetSet(0, $new_value);
Write a class deriving from ArrayObject and add a function prepend (implementation could be the one below).
Extract an array, call array_unshift() and create a new ArrayObject with the modified array:
$array = $arrayObject->getArrayCopy();
array_unshift($array, $new_value);
$arrayObject->exchangeArray($array);
There is no such functionality in ArrayObject, but you can subclass it to add whatever you need. Try this:
class ExtendedArrayObject extends ArrayObject {
public function prepend($value) {
$array = (array)$this;
array_unshift($array, $value);
$this->exchangeArray($array);
}
}
function prefix($value) {
return $this->exchangeArray(array_merge([$value], $this->getArrayCopy()));
}
#Dmitry, #soulmerge your answers was good regarding the initial question but was missing the requirement in my edit, but they point me in the right direction to achieve what i was expected here's the solution we came with here at work: (work for php>=5.1)
public function unshift($value){
$tmp = $this->getArrayCopy();
$tmp = array($value) + $tmp;
$this->exchangeArray($tmp);
return $this;
}
these exemple is not exactly the same as the final solution we needed as for our particular arrayObject. We use a given key in array values as key for the values (think of using database rowId as index for each value in the collection). let's call this value "key" here's what the actual array struct looks like:
array(
key1 => array(key=>key1,val1=>val1,val2=>val2...),
key2 => array(key=>key2,val1=>val1_2,val2=>val2_2...),
...
);
so our solution looks more something like this:
public function unshift($value){
$tmp = $this->getArrayCopy();
$tmp = array($value['key'],$value) + $tmp;
$this->exchangeArray($tmp);
return $this;
}
thank's for your answers, if you find a way that work in php5.0 too i'm still interested.
this works for me. with array_merge()
$old_arr[]=array(
'val1'=>'sample1',
'val2'=>'1'
);
$new_arr[] = array(
'val1'=>'sample2',
'val2'=>'2'
);
array_merge($new_arr,$old_arr);