Creating arrays within arrays without creating keys first - php

This is how I used to create keys that didn't exist inside an array when looping through data:
$array = [];
foreach ($results as $result) {
if (!isset($array[$result->id])) {
$array[$result->id] = [];
}
$array[$result->id][] = $result->value;
}
A colleague at work does the following. PHP doesn't error but I am not sure if it's a feature of PHP or if it's incorrect:
$array = [];
foreach ($results as $result) {
$array[$result->id][] = $result->value;
}
Is it incorrect for me to do the above?

if condition you put in your code is unnecessary. Let me explain.
if (!isset($array[$result->id])) {
$array[$result->id] = [];
}
This mean if $array[$result->id] is not exist than you are define it as an array, however $array[$result->id][] it self create new array if not existing without throwing any error. So no need to use if condition error. In conclusion, both code are correct, just you are using unnecessary if condition.

Related

How to dynamically set a parent table when accessing a collection?

I'm trying to fetch data from dynamically different tables depending on which user is logged on and if he is allowed to edit said table, what I thought was going to work was this:
$colaboradores = Colaboradore::where('email', '=', Auth::user()->email)->first();
$tables = DB::connection('mysql2')->select("SHOW TABLES LIKE 'intervencoes\_%'");
foreach ($tables as $object) {
$arrays[] = (array)$object;
}
foreach ($arrays as $array) {
$string = implode('', $array);
$test = $colaboradores->Niveis->$string->id;
}
And it outputs an error on the last bit of code saying
"Trying to get property 'id' of non-object"
I have been looking around for hours but couldn't find anything related.
This is all inside a livewire component by the way.
Thanks in advance.
Edit:
dd($colaboradores->Niveis)
dd($colaboradores->Niveis->$string)
Since $colaboradores->Niveis->$string returns a Collection, you need to iterate over it to get results.
$test = [];
foreach ($colaboradores->Niveis->$string as $obj) {
$test[] = $obj->id;
}
Then you can check the IDs in $test with dd($test); for example.
This can cause a problem if $obj is not a real object, so you could check it with:
if (!is_object($obj)) {
//Do something - Not an object!
}

Bug when trying to update an array

I have a two questions with a symfony's project.
My first one :
I am trying to modify some data in an array.
I have this code
var_dump($results); // FIRST ONE
foreach ($results as $result) {
foreach ($result as $res) {
foreach ($dates as $date) {
if(!array_key_exists($date,$res)) {
$res = array_merge($res,[$date => '0']);
}
}
var_dump($res); // THIS ONE IS MODIFIED
}
}
var_dump($results); // LAST ONE... SAME AS THE FIRST ONE
I don't understand why my array ' $results ' is no updated... am i missing something ?
And my second question : is there any way to simplify this code ? I don't like the 3 foreach.
Thanks you guys :)
PHP foreach copy each item when iterate so $result array will not update when you change $res item.
1) You can use array keys to change main array
foreach($arrr as $k => $item) {arrr[$k]['key'] = 'changed'}
2) Or you can get link to the $res item and change it dirrectly
foreach($arrr as &$item) {$item['key'] = 'changed'}
Note that second case can cause different issues
Unless you're passing an object in PHP, PHP does not pass values by reference. $res is a copy of the value, not a link to the original value. If you know what you're doing, you can pass by reference. When passing by reference, altering $res would alter the original data. You pass by reference by prefixing a & to the variable or argument.
Since this is a nested foreach, you'll also have to pass $result by reference to avoid that being a copy of the item of $results.
foreach ($results as &$result) {
foreach ($result as &$res) {
foreach ($dates as $date) {
if(!array_key_exists($date,$res)) {
$res = array_merge($res,[$date => '0']);
}
}
}
}

PHP: String in json parse

I am trying to parse a json. I am running this in a foreach loop and if I do the following it works:
$places = array('restaurant', 'store', 'etc')
foreach ($this->placesCachingTypes as $places) {
$places_location_lat = $json_decoded->json[0]->restaurant[0]->geometry->location->lat;
$places_location_lng = $json_decoded->json[0]->restaurant[0]->geometry->location->lng;
}
However, when I do the following, i.e. I change restaurant to $places (I need to do this since I have an array of different places and I want to parse all of them in a foreach loop) it doesn't work.
foreach ($this->placesCachingTypes as $places) {
$places_location_lat = $json_decoded->json[0]->$places[0]->geometry->location->lat;
$places_location_lng = $json_decoded->json[0]->$places[0]->geometry->location->lng;
}
Solution is changing $places to {$places}[0]
The $places array contains keywords, such as restaurant or store. So the [0] is referring to the first one in the json which is why it's needed.
Why do you have this in the first loop:
json[0]->restaurant[0]
json[0]->$restaurant[0]
But then in the next you have:
json[0]->$places[0]
json[0]->$places[0]
Perhaps you are parsing the JSON incorrectly and it should be:
foreach ($this->placesCachingTypes as $places) {
$places_location_lat = $json_decoded->json[0]->places[0]->geometry->location->lat;
$places_location_lng = $json_decoded->json[0]->places[0]->geometry->location->lng;
}
And then in the first loop, you should do a similar edit to get rid of $restaurant[0]:
foreach ($this->placesCachingTypes as $places) {
$places_location_lat = $json_decoded->json[0]->restaurant[0]->geometry->location->lat;
$places_location_lng = $json_decoded->json[0]->restaurant[0]->geometry->location->lng;
}
Then again, unclear on what value $places has when you loop via foreach ($this->placesCachingTypes as $places) {. It does’t make sense what you would be looping through with the value of $places. And perhaps assigning that $places in the loop object of $json_decoded->json[0]-> is the source of your issues? Need more info from you to confirm this.

Filter an array in PHP

I'm trying to write a sort/filter script using an array filter function in PHP using the lambda syntax.
This achieves what I want to do, but it looks like it can be optimised:
$offersReceivedProcessedByItem = array();
foreach ($this->currentSessionUser->items as $item) {
$receivedOffersOnItem = array();
foreach ($offersReceived as $offerReceived) {
if ($offerReceived->item->id === $item->id) {
$receivedOffersOnItem[$offerReceived->id] = $offerReceived;
}
}
offersReceivedProcessedByItem[$item->id] = $receivedOffersOnItem;
}
(for each item a user has, filter through the offersReceived array and add the offer to a new array if it has an equal id, if that makes sense?!).
Here's what I'm trying:
$offersReceivedProcessedByItem = array();
foreach ($this->currentSessionUser->items as $item) {
$receivedOffersOnItem = array_filter($item->offers, function($offer){
return $offer->item->id === $item->id;
});
$offersReceivedProcessedByItem[$item->id] = $receivedOffersOnItem;
}
But i'm getting that $item is undefined, I expect it's closed scope so I tried passing $item as another argument but then i'm getting 'missing argument 2'.
I tried this using the relational approach built into Fuel but PHP eats too much memory and fails.
Any help? What am I getting wrong?
A closure doesn't know anything about the environment it is created it unless you tell it
$receivedOffersOnItem = array_filter($item->offers, function($offer) use($item){
return $offer->item->id === $item->id;
});
Notice the use-statement
A link to the manual http://php.net/functions.anonymous#example-119

Patterns for building multidimensional array with unique key

Problem:
Extract data from an object/array and represent this data using a multidimensional array with a unique key generated from the inner loop.
I always find myself building multidimensional arrays like this:
$final_array = array();
foreach ($table as $row) {
$key = null;
$data = array();
foreach ($row as $col => $val) {
/* Usually some logic goes here that does
some data transformation / concatenation stuff */
if ($col=='my_unique_key_name') {
$key = $val;
}
$data[$col] = $val;
}
if (!is_null($key) {
if (!isset($final_array[$key]) {
$final_array[$key] = array();
}
$final_array[$key][] = $data;
}
}
I can't help but wonder if I'm constantly doing this out of habit, but it feels kind of verbose with all the key-checking and whatnot. Is there a native function I am not utilizing? Can this be refactored into something more simple or am I overthinking this?
Why are you always doing that? Doesn't seem the common kind of stuff one works with on a day to day basis... Anyway, that's kinda cryptic (an example would be nice) but have you though of using an MD5 hash of the serialized dump of the array to uniquely define a key?
$key = md5(serialize($value));

Categories