So I have some code looking like this at the moment:
$filter = new \stdClass();
$queryObj = $this->getpost['filter'];
$filters = new \stdClass();
$filters->team = $queryObj['team'];
$filters->skill = $queryObj['skill'];
$filters->division = $queryObj['division'];
$filter->filters = $filters;
$users = $managerStatistics->getManagerDeliveryData($filter);
I fellt the need to do this because in the getManagerDeliveryData(§filter), there is a "foreach $filter->filters"..
Does anyone know how to do this in a better looking way? This looks messy to me but I'm not sure what to do here..
You could rewrite the way you build the data into a more compact format, casting each array definition to an object as needed...
$filter = (object) [
"filters" => (object) [ 'team' => $queryObj['team'],
'skill' => $queryObj['skill'],
'division' => $queryObj['division'] ]
];
If you cast an associative array to an object, it becomes a stdClass object with matching properties. Here's a generic example:
$arr = ['one' => 'foo', 'two' => 'bar', 'three' => 'meh'];
$obj = (object) $arr;
var_dump($obj);
This would give you:
object(stdClass)#2 (3) {
["one"] · string(3) "foo"
["two"] · string(3) "bar"
["three"] · string(3) "meh"
}
In your case, you could do the following, if you're hoping to not have to name your $queryObj keys/values one by one (which is necessary if e.g. the filter list isn't fixed, and therefore can't be hard-coded):
$filters = (object) $queryObj;
Obviously, every key/value pair in the source array then becomes a property/value pair in the object. If there are particular values you want to omit, either unset them or use array_intersect_key() etc. functions to only cast the desired keys. Suppose your $queryObject had a bunch of keys, but you only wanted the ones in your example, you could do this:
$keymap = ['team', 'skill', 'division'];
$filters = (object) array_intersect_key(array_flip($keymap), $queryObject);
Related
I need to extract values from a multidimensional array. The startpoint is however an stdClass object. The aim is to use the extracted values to create a graph. The graph is not part of this question.
Question:
Is there a shorter and more straightforward way, then below?
Note that the values can be 100 so I do not plan to extract the values, one by one.
// Create an stdClass.
$products = (object)[
'group' => [
['level' => "12"],
['level' => "30"],
['level' => "70"],
]
];
// Transform stdClass to array.
$products = json_decode(json_encode($products), true);
var_dump($products);
// Calc amount of subarrays.
$amount_of_subarrays = count($products['group']);
$amount_of_subarrays = $amount_of_subarrays - 1; // Adjust since objects start with [0].
// Extract data from [$products], populate new array [$array].
$array = [];
for ($i=0; $i <= $amount_of_subarrays; $i++) {
$tmp = $products['group'][$i]['level'];
array_push($array, $tmp);
}
var_dump($array);
Result (as expected):
array(3) {
[0] =>
string(2) "12"
[1] =>
string(2) "30"
[2] =>
string(2) "70"
}
Simplest way I know of is to use the array_column function which returns the values from a single column in the input array
E.g. array_column($products['group'], 'level') should return the expected result.
You not need the Transform with json_encode and json_decode from stdClass to array
if use this:
$result = array_column($products->group, 'level');
This is an array,
$array = array(
'one' => 1,
'two' => 2,
'three' $array['one'] + $array['two']
);
It's get an error,
why?
Because $array does not exist before the end of your declaration. You simply cannot define an array on such a recursive manner since you refer to a non-existing resource.
This is a working variant. Indeed, not very convenient, but working:
<?php
$array = [
'one' => 1,
'two' => 2
];
$array['three'] = $array['one'] + $array['two'];
var_dump($array);
The output obviously is:
array(3) {
'one' =>
int(1)
'two' =>
int(2)
'three' =>
int(3)
}
The only really elegant way around this requires quite some effort:
You can implement a class implementing the ArrayAccess interface. That allows you to implement how the properties should be defined internally (for example that sum), whilst still allowing to access these properties via an array notation. So no difference to an array at runtime, only when setting up the object. However this is such a huge effort that I doubt it is worth it in >99% of the cases.
You're using a variable which is being declared, its value value is not know yet. Here is how you should write it:
$array = array(
'one' => 1,
'two' => 2,
);
$array['tree'] = $array['one'] + $array['two'];
$array1 = array("$name1" => "$id1");
$array2 = array("$name2" => "$id2", "$name3" => "$id3");
I need a new array combining all together, i.e. it would be
$array3 = array("$name1" => "$id1", "$name2" => "$id2", "$name3" => "$id3");
What is the best way to do this?
Sorry, I forgot, the ids will never match each other, but technically the names could, yet would not be likely, and they all need to be listed in one array. I looked at array_merge but wasn't sure if that was best way to do this. Also, how would you unit test this?
array_merge() is more efficient but there are a couple of options:
$array1 = array("id1" => "value1");
$array2 = array("id2" => "value2", "id3" => "value3", "id4" => "value4");
$array3 = array_merge($array1, $array2/*, $arrayN, $arrayN*/);
$array4 = $array1 + $array2;
echo '<pre>';
var_dump($array3);
var_dump($array4);
echo '</pre>';
// Results:
array(4) {
["id1"]=>
string(6) "value1"
["id2"]=>
string(6) "value2"
["id3"]=>
string(6) "value3"
["id4"]=>
string(6) "value4"
}
array(4) {
["id1"]=>
string(6) "value1"
["id2"]=>
string(6) "value2"
["id3"]=>
string(6) "value3"
["id4"]=>
string(6) "value4"
}
Check out array_merge().
$array3 = array_merge($array1, $array2);
There is also array_replace, where an original array is modified by other arrays preserving the key => value association without creating duplicate keys.
Same keys on other arrays will cause values to overwrite the original array
New keys on other arrays will be created on the original array
I use a wrapper around array_merge to deal with SeanWM's comment about null arrays; I also sometimes want to get rid of duplicates. I'm also generally wanting to merge one array into another, as opposed to creating a new array. This ends up as:
/**
* Merge two arrays - but if one is blank or not an array, return the other.
* #param $a array First array, into which the second array will be merged
* #param $b array Second array, with the data to be merged
* #param $unique boolean If true, remove duplicate values before returning
*/
function arrayMerge(&$a, $b, $unique = false) {
if (empty($b)) {
return; // No changes to be made to $a
}
if (empty($a)) {
$a = $b;
return;
}
$a = array_merge($a, $b);
if ($unique) {
$a = array_unique($a);
}
}
$array = array(
22 => true,
25 => true,
34 => true,
35 => true,
);
print_r(
array_replace($array, [
22 => true,
42 => true,
])
);
print_r(
array_merge($array, [
22 => true,
42 => true,
])
);
If it is numeric but not sequential associative array, you need to use array_replace
UPDATE
Just a quick note, as I can see this looks really stupid, and it has no good use with pure PHP because the array_merge just works there. BUT try it with the PHP MongoDB driver before you rush to downvote. That dude WILL add indexes for whatever reason, and WILL ruin the merged object. With my naïve little function, the merge comes out exactly the way it was supposed to with a traditional array_merge.
I know it's an old question but I'd like to add one more case I had recently with MongoDB driver queries and none of array_merge, array_replace nor array_push worked. I had a bit complex structure of objects wrapped as arrays in array:
$a = [
["a" => [1, "a2"]],
["b" => ["b1", 2]]
];
$t = [
["c" => ["c1", "c2"]],
["b" => ["b1", 2]]
];
And I needed to merge them keeping the same structure like this:
$merged = [
["a" => [1, "a2"]],
["b" => ["b1", 2]],
["c" => ["c1", "c2"]],
["b" => ["b1", 2]]
];
The best solution I came up with was this:
public static function glueArrays($arr1, $arr2) {
// merges TWO (2) arrays without adding indexing.
$myArr = $arr1;
foreach ($arr2 as $arrayItem) {
$myArr[] = $arrayItem;
}
return $myArr;
}
I stumbled upon this question trying to identify a clean way to join two assoc arrays.
I was trying to join two different tables that didn't have relationships to each other.
This is what I came up with for PDO Query joining two Tables. Samuel Cook is what identified a solution for me with the array_merge() +1 to him.
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM ".databaseTbl_Residential_Prospects."";
$ResidentialData = $pdo->prepare($sql);
$ResidentialData->execute(array($lapi));
$ResidentialProspects = $ResidentialData->fetchAll(PDO::FETCH_ASSOC);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM ".databaseTbl_Commercial_Prospects."";
$CommercialData = $pdo->prepare($sql);
$CommercialData->execute(array($lapi));
$CommercialProspects = $CommercialData->fetchAll(PDO::FETCH_ASSOC);
$Prospects = array_merge($ResidentialProspects,$CommercialProspects);
echo '<pre>';
var_dump($Prospects);
echo '</pre>';
Maybe this will help someone else out.
For me, this small snippet worked.
I have similar structures for both my arrays except the keys are a little different.
e.g
JSON 1 : {"sketchCount":{"2":{"A":50477}},"raw":{"2":{"A":70477}}}
JSON 2 : {"sketchCount":{"2":{"B":50477}},"raw":{"2":{"B":50477}}}
Desired Output JSON : {"sketchCount":{"2":{"A":70477,"B":50477}},"raw":{"2":{"A":70477,"B":50477}}}
Code
foreach($existingArray as $key => $possibleArray){
if(is_array($possibleArray)){
foreach($possibleArray as $index=> $value){
$combinedArray[$key][$index] = $value;
if(array_key_exists($key,$newArray) && array_key_exists($index,$newArray[$key])){
foreach($newArray[$key][$index] as $newKey=> $associatedValue){
$combinedArray[$key][$index][$newKey] = $associatedValue;
}
}
}
}
}
My array
$arr = array(
"name" => "Prakash",
"tall" => "maybe",
"nick_names" => array ("p", "b", "bee", "prak", "new_names" => array("short_name" => "sn", "long_name" => "ln"))
);
I want to be able to create an object from which the values can be accessed via attributes.
e.g.
$obj->name // "PRAKASH"
$obj->nick_names // array("p", "b", "bee", "prak", "new_names" => (object))
How could I get this ?
I seem to able to accomplish exactly what I need through
$obj = json_decode(json_encode($arr));
But obviously that is not the right thing to do.
Thanks.
You can cast it into an stdClass:
$obj = (stdClass) $arr;
Take note that in PHP an array is far superior to an stdClass in any thinkable way.
Better performance
Better traversing abilities
Better readability (IMO)
For example:
$names = {[bob:27, billy:43, sam:76]};
and then be able to reference it like this:
$names[bob]
http://php.net/manual/en/language.types.array.php
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>
Standard arrays can be used that way.
There are no dictionaries in php, but PHP array's can behave similarly to dictionaries in other languages because they have both an index and a key (in contrast to Dictionaries in other languages, which only have keys and no index).
What do I mean by that?
$array = array(
"foo" => "bar",
"bar" => "foo"
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
The following line is allowed with the above array in PHP, but there is no way to do an equivalent operation using a dictionary in a language like Python(which has both arrays and dictionaries).
print $array[0]
PHP arrays also give you the ability to print a value by providing the value to the array
print $array["foo"]
Normal array can serve as a dictionary data structure. In general it has multipurpose usage: array, list (vector), hash table, dictionary, collection, stack, queue etc.
$names = [
'bob' => 27,
'billy' => 43,
'sam' => 76,
];
$names['bob'];
And because of wide design it gains no full benefits of specific data structure. You can implement your own dictionary by extending an ArrayObject or you can use SplObjectStorage class which is map (dictionary) implementation allowing objects to be assigned as keys.
Use arrays:
<?php
$arr = [
"key" => "value",
"key2" => "value2"
];
If you intend to use arbitrary objects as keys, you may run into "Illegal offset type". To resolve this you can wrap the key with the call of spl_object_hash function, which takes any object, and returns its unique hash.
One thing to keep in mind, however, is that then the key itself will be the hash, and thus you will not be able to get a list of the objects used to generate those hashes from your dictionary. This may or may not be what you want in the particular implementation.
A quick example:
<?php
class Foo
{
}
$dic = [];
$a = new Foo();
$b = new Foo();
$c = $a;
$dic[spl_object_hash($a)] = 'a';
$dic[spl_object_hash($b)] = 'b';
$dic[spl_object_hash($c)] = 'c';
foreach($dic as $key => $val)
{
echo "{$key} -> {$val}\n";
}
The output i get is:
0000000024e27223000000005bf76e8a -> c
0000000024e27220000000005bf76e8a -> b
Your hashes, and hashes at different executions may be different.