search in values in array and get another value - php

I have an array like this:
//the result of `dd()` function in laravel
Collection {#401 ▼
#items: array:2 [▼
0 => {#400 ▼
+"tutorial_package_count": 2
+"tutorial_package_id": 1
+"tutorial_id": 1
}
1 => {#402 ▼
+"tutorial_package_count": 1
+"tutorial_package_id": 2
+"tutorial_id": 2
}
]
}
suppose I have a variable as $tutorial_id = 1,
now I want to get value of tutorial_package_count. at this here I want 2.
I dont want to use a loop.

In this case you can use filter method available for collections:
$filtered = $collection->filter(function ($value, $key) use($tutorial_id) {
return $value['tutorial_id'] == $tutorial_id;
});
$firstMatch = $filtered->first();

Related

How can I sort chosen collection in multidimensional array in laravel php

i want to sort by cu_customer_shortname in nested array collection but seems i cant see any ways do it . here is my example of my array list
{#1811 ▼
+"co_group_id": "ADUKO"
+"co_description": "ADUKO"
+"co_customer_id": "038"
+"co_active_sts": "1"
+"irel__h_d_rel_group_customer": array:3 [▼
0 => {#1812 ▼
+"ID": "5"
+"gc_group_id": "ADUKO"
+"gc_customer_id": "038"
+"irel__h_d_customer_master": {#1813 ▶}
}
1 => {#1814 ▼
+"ID": "6"
+"gc_group_id": "ADUKO"
+"gc_customer_id": "044"
+"irel__h_d_customer_master": {#1815 ▼
+"cu_customer_ID": "044"
+"cu_customer_Shortname": "JPEN" <------ Sort this shortname
}
}
]
Here is my code that i already tried
$groupList = $contents->data->groupList;
$order = $groupList->irel__h_d_rel_group_customer; //arrayList
$collection = new \Illuminate\Support\Collection($groupList); //collection
$sorted = $collection->SortByDesc('irel__h_d_customer_master.cu_customer_Shortname'); // sorted by cu_customer_shortname
My code not return any error but my list remain and not sorted by cu_customer_Shortname

Get value by column name value

Ny array looks something like this:
Illuminate\Database\Eloquent\Collection {#2052 ▼
#items: array:3 [▼
0 => App\Models\NewsMeta {#2089 ▶}
1 => App\Models\NewsMeta {#2090 ▶}
2 => App\Models\NewsMeta {#2091 ▶}
]
}
If I open up the array 2:
#original: array:7 [▼
"id" => 17
"post_id" => 240231
"news_tag_id" => 5
"meta_name" => "_thumbnail_id"
"meta_value" => "240232"
"created_at" => "2020-08-06 22:34:06"
"updated_at" => "2020-08-06 22:34:06"
]
Now, I looking to get value "240232" given that I've 240231.
How do I search inside array of the object?
Something like: where post_id is 240231 get ts meta_value.
FYI: It's not eloquent or DB query.
Something like this should work:
$postId = 240231;
$metaValue = null;
foreach ($collection as $model) {
if ($model->post_id == $postId) {
$metaValue = $model->meta_value;
break;
}
}
echo $metaValue;
You could also use the collection's seach method:
$postId = 240231;
$metaValue = $collection->search(static function($model, $key) use($postId) {
if ($model->post_id == $postId) {
return $model->meta_value;
}
});
echo $metaValue;
You can use the collection firstWhere() method
$collection->firstWhere('post_id', '240231')['meta_value'] ?? null;
With the data you provided this should return 240232. In a dataset where there is no post_id = 240231 it would return null.

how to sum a collection after groupBy laravel

i have a collection named detailed as below :
Collection {#1421 ▼
#items: array:2 [▼
3943 => Collection {#1419 ▼
#items: array:2 [▼
0 => RoomPricingHistory {#923 ▶}
1 => RoomPricingHistory {#1042 ▶}
]
}
3944 => Collection {#1420 ▼
#items: array:2 [▼
0 => RoomPricingHistory {#1153 ▶}
1 => RoomPricingHistory {#1264 ▶}
]
}
]
}
now i want to get the sum of RoomPricingHistory for 3943 item and 3944 ofc it can be more of 2 item so i want to get the sum of each collection how can i achieve that ??
The Collection sum method can take a callback so you can define what is going to be calculated. In this case you can call sum on the main collection and in the callback which will give you access to the internal collections, also call sum.
$detailed->sum(function ($group) {
return $group->sum('sales_price');
});
Laravel 6.x Docs - Collections - Available Methods - sum
Since that isn't what you are looking for, you can use something like mapWithKeys to go through the collection and call sum for the groups to get the sum for each group:
$sums = $detailed->mapWithKeys(function ($group, $key) {
return [$key => $group->sum('sales_price')];
});
Laravel 6.x Docs - Collections - Available Methods - mapWithKeys

Merge 2 Collections or Arrays by Key

I'm trying my best to prevent from looping over a collection to get more data that I need for a data table. I need a way to combine these 2 collections or arrays.
I have 2 functions inside a model that calls an API that gives me an array of data that I convert into a collection.
Orders()
public function orders(){
$orders_array = $this->api()->request('orders.json');
return collect($orders_array);
}
Returns:
Collection {#274 ▼
#items: array:2 [▼
0 => {#282 ▼
+"id": 628602961977
}
1 => {#270 ▶}
order_meta()
public function order_meta($order_id){
$order_metafields_array = $this->api()->request('meta.json');
return collect($order_metafields_array);
}
Returns:
Collection
#items: [
+"name": "meta_data"
]
What I am wanting to do is inject the order_meta() into each order using the order ID.
I guess I am wanting to do something like this:
public function orders_detailed(){
$orders = $this->orders();
$keyed = $orders->mapWithKeys(function ($item) {
return [$item['meta'] => $this->order_metafields($item['id'])];
});
}
In hopes it will return:
Collection {#274 ▼
#items: array:2 [▼
0 => {#282 ▼
+"id": 628602961977
+meta => {
+"name":"meta_data"
}
}
1 => {#270 ▶}
Is something like this possible? I'm also open to merging it in as an array first, then creating a collection.

Eloquent request with subitems count

I have 2 tables :
Valuechains : id, created_at, updated_at, deleted_at
Segments : id, valuechain_id (Foreign key), created_at, updated_at, deleted_at
And pivot tables (not really important here).
I have a method with sql requests ...
$valuechains list gives me a list of all the value chains which are not (soft) deleted
$valuechainCount counts the number of valuechains which are published
$segmentCount counts the number of segments for each value chains
I try to use the map function in order to add a column which contains the number of segments for each value chains ...
public function vcListAndSegmentCount() {
$valuechainLists = Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get();
$valuechainCount = Valuechain::whereNull('valuechains.deleted_at')->count();
for ($i=0; $i < $valuechainCount; $i++) {
$segmentCount[$i] = Segment::whereNull('segments.deleted_at')
->where('valuechain_id', '=', $valuechainLists[$i]->id)->count();
}
$valuechainLists = $valuechainLists->map(function ($record) use ($segmentCount) {
$vclists = array_first($segmentCount, function ($value, $key) use ($record) {
return $value['id'] === $record['valuechain_id'];
});
$record['count'] = $vclists;
return $record;
});
dd($valuechainLists);
}
The map methods adds a column my output collection. Unfortunatelly, the new collection is not giving me the right numbers of segments for each value chain... it only adds one value ...
Here is what I obtain :
Collection {#380 ▼
#items: array:4 [▼
0 => Valuechain {#450 ▼
...
#attributes: array:4 [▼
"id" => 1
"vcname" => "Génétique"
"vcshortname" => "Génétique"
"count" => 6
]
#original: array:3 [▶]
...
}
1 => Valuechain {#451 ▼
...
#attributes: array:4 [▼
"id" => 2
"vcname" => "Biotruc"
"vcshortname" => "Biotruc"
"count" => 6
]
...
}
2 => Valuechain {#452 ▼
...
#attributes: array:4 [▼
"id" => 3
"vcname" => "VC3"
"vcshortname" => "VC3"
"count" => 6
]
...
}
3 => Valuechain {#453 ▼
...
#attributes: array:4 [▼
"id" => 4
"vcname" => "VC4"
"vcshortname" => "VC4"
"count" => 6
]
#original: array:3 [▶]
...
}
]
}
I obtain 6, 6, 6 and 6 whereas the count should be 6, 5, 4, 4...
If you are using Laravel >= 5.2 and if you have defined the relationships on the models, you can use the withCount() method.
It would go something like this:
Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->withCount(['segments' => function ($query) {
$query->whereNull('deleted_at);
}])
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get()
or if your Segment model uses the SoftDeletes trait, then it's a bit simpler:
Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->withCount('segments')
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get()
add count value as a property instead of array element.
$valuechainLists = $valuechainLists->map(function ($record) use ($segmentCount) {
$vclists = array_first($segmentCount, function ($value, $key) use ($record) {
return $value['id'] === $record['valuechain_id'];
});
$record->count = $vclists;
return $record;
});
I changed
$record['count'] = $vclists;
to
$record->count = $vclists;
Add a reference: &$segmentCount
$valuechainLists = $valuechainLists->map(function ($record) use (&$segmentCount) {....
Also I'm not sure what your array_first function is doing.

Categories