How to make associative array in Yii2? - php

I would like to make associative array using foreach to use in Yii 2 dropdownlist.
My goal is to make array like following using foreach-
$array= [
['id' => '123', 'name' => 'abc'],
['id' => '124', 'name' => 'def'],
];
And then I want to use them using Yii 2 ArrayHelper::map().
$result = ArrayHelper::map($array, 'id', 'name');
How do I make the array using foreach?

Yii way to build items for drop-down list is exactly as you described, using ArrayHelper::map():
$items = ArrayHelper::map($array, 'id', 'name');
You don't need to use foreach here, just pass results of ActiveQuery as array:
$array = YourModel::find()->all();
Update:
Thanks. But here, I am actually calculating custom value for 'name'
and for that reason I want to use foreach to generate the array after
the calculation
You definetely need to add this information to the question, but anyway, you can use the ArrayHelper for that too. Take a look at toArray method. It can be used for both object / array of objects. After processing with this method you can use map.
Official docs:
ArrayHelper::map()
ArrayHelper::toArray()

Related

How to get the values of a multi-dimensional array by key in Laravel?

Let's say for example you have a constant multi-dimensional array with multiple keys (and values), but you want to filter out specific keys with it's values. See a example array below:
const defaultInvestmentFields = [
[
'type' => 'system',
'investment_name' => 'Ballast'
],
[
'type' => 'system',
'investment_name' => 'Inverters'
],
[
'type' => 'system',
'investment_name' => 'Extra garantie inverters'
]
];
The output I want is an array with only the values of investment_name. Like ['Ballast', 'Inverters', 'Extra garantie inverters'].
Additionally to #Levi's answer, you can use an array helper to avoid having to transform the array into a collection and back: Arr::pluck()
Arr::pluck(Project::defaultInvestmentFields, 'investment_name');
A quick and neat solution would be to use the collect wrapper function which is provided by Laravel. After that we can use the pluck function in order to specify which values by their key(s) we want to get. For example:
collect(Project::defaultInvestmentFields)->pluck('investment_name');
Now we have a Collection of the following values: Ballast, Inverters and Extra garantie inverters.
In order to use it as an array, simply call toArray() on it.

Check if values in array are in another array using Laravel Validation

I want to check if all the values of my input, an array, are in another array. For example:
$my_arr = ['item1', 'item2', 'item3', 'item4'];
Validator::make($request, [
'item' => [ /* what do i put here??? */ ],
]);
I don't think the rule in works, because that expects a single value as input, not an array. in_array doesn't work either. I've tried creating a custom rule or closure, but neither of those allow me to pass in a parameter (the array I want to check against). Especially since I want this same functionality for multiple arrays, for different inputs, it would be nice to have a generic rule that works for any array I give it.
If that's not possible, I suppose I need to create a rule for each specific array and use !array_diff($search_this, $all) as this answer says. Is there an alternative to this?
True that in doesn't accept an array but a string. So you can just convert the array into a string.
$my_arr = ['item1', 'item2', 'item3', 'item4'];
Validator::make($request, [
'item' => [ 'in:' . implode(',', $my_arr) ],
]);
implode
Another better solution might be to use Illuminate\Validation\Rule's in method that accepts an array:
'item' => [ Rule::in($my_arr) ],
Laravel Validation - Rule::in

Given array keys that correspond to another array, how can I merge them?

I have the following array that is supposed to only be keys:
$keys = ['mod_4_key'];
and the bigger array which contains a lot of information:
$big_array = [ 'mod_4_key' => ['old' => '', 'info' => ''], 'mod_5_key' => ..]
I would like to, based on what is inside $keys generate a new array with the information from $big_array, as such, if we are to compute the "non-difference" between the arrays, the output should be:
$final_array = [ 'mod_4_key' => ['old' => '', 'info' => '']]
I achieved this using a classic foreach but I was wondering if there was no in-built way to achieve this.
You may be better off with a simple foreach() loop, but there are probably several ways of achieving this.
This uses array_flip() on the $keys, so that you end up with another associative array, then use array_intersect_key() with the big array first.
$final_array = array_intersect_key($big_array, array_flip($keys));

Laravel - How to makeHidden multidimensional?

There is a multidimensional array. I want to makeHidden the children of the array:
Model::with('someRelation')->get()->toArray();
what I get is:
array [
'something',
'something_else',
'something2' => [
'something_inside_something2_to_be_visible' => 'someValue',
'something_inside_something2_to_be_hidden' => 'someValue2',
]
]
what I want to get is the array without something_inside_something2 inside something2. Something like this:
Model::with('someRelation')->get()->makeHidden(['something.something_inside_something2'])->toArray();
How can I do that?
If i understood what you mean, you need keys only.
you can do something like this:
$user = User::first();
dd(array_keys($user->toArray()));
Well I think you want to load just some columns from the relationship. In that case tell explicitly what you need from the relationship in with method.
Model::with('someRelation:primary_key,another_column,more_column')->get()->toArray();

how to process my array to be associative on first two levels and on third to have simple value

I'm trying to construct an array where there only strings and the array would look like this
key->key->value
To explain it I attached two screenshots below.
I start with this:
After my code below I'm 90% there, yet there is an array in value on the third level instead of simple value.
Here is some code:
$theme = ThemeHandler::with('sections.settings')->find($activeTheme);
$themeSettings = $theme->sections;
$themeSettings = collect($themeSettings->toArray());
// dd($themeSettings);
$themeSections = [];
foreach ($themeSettings as $key => $value) {
$settings = collect($value['settings']);
$settings = $settings->mapToGroups(function ($item) {
return [$item['key'] => $item['value']];
});
$themeSections[$value['key']] = $settings->toArray();
}
dd($themeSections);
I would like to end up with this structure
key->key->value
and not
key->key->single_element_array->value
I'm not sure how I end up with an array at the bottom level when I do this
return [$item['key'] => $item['value']];
inside the mapToGroups, which is a function found here: https://laravel.com/docs/5.8/collections#method-maptogroups
Maybe I misunderstand how mapToGroups work. Anybody has an idea how to get key->key->value structure output?
Use mapWithKeys() instead of mapToGroups().
You're getting an array instead of the simple value you expect because the value is a group, albeit a group with only one member.
mapToGroups() groups all the values with the same key, but mapWithKeys() will assign a single value to each key.
You can see in the examples in the collection documentation, mapToGroups() produces a result like this:
[
'Sales' => ['John Doe', 'Jane Doe'],
'Marketing' => ['Johnny Doe'],
]
And mapWithKeys() result is like this:
[
'john#example.com' => 'John',
'jane#example.com' => 'Jane',
]

Categories