How to get the common values from 2 Laravel collections - laravel

I have 2 Collections in Laravel, and I want only common values in my $result object. I see that $collection->intersect() works only for 1D array.
Below are the collections
Collection {#1086 ▼
#items: array:5 [▼
0 => {#1115 ▼
+"name": "Light"
+"class": "ABC"
+"id": 4
}
1 => {#1113 ▼
+"name": "Milo"
+"class": "XYZ"
+"id": 10
}
2 => {#1120 ▼
+"name": "Milo Test"
+"class": "ABC"
+"id": 12
}
3 => {#1102 ▼
+"name": "KMSMiloCow"
+"class": "ABC"
+"id": 16
}
4 => {#1106 ▼
+"name": "MiloCows"
+"class": "XYZ"
+"id": 18
}
]
}
Collection {#1086 ▼
#items: array:5 [▼
0 => {#1115 ▼
+"name": "Light"
+"class_name": "ABC"
+"id": 4
}
]
}
Now in my result, I just need this
Collection {#1086 ▼
#items: array:5 [▼
0 => {#1115 ▼
+"name": "Light"
+"class": "ABC"
+"id": 4
}
]
}

I have no idea this would help you or not but these will be useful
$common_collection = $collection_1->whereIn('id', $collection_2->pluck('id')->toArray())
->unique('id')
->sortBy('id');

To get a collection with common elements, you can use filter():
The filter method filters the collection using the given callback, keeping only those items that pass a given truth test
$commonCollection = $collection1->filter(function ($value, $key) use ($collection2){
return $collection2->contains($value);
});

I think using collection method each and contains, it can be done like this
$collection1->each(function ($value, $key) use ($collection2){
return $collection2->contains($value);
});
dd($collection1);
I test it in routes file web.php like
use Illuminate\Support\Collection;
Route::get('test', function(){
$collection1 = new Collection([
'bear',
'whale',
'chicken',
'tardigrade'
], [[
'bear8',
'whale44',
'chicken45',
'tardigrade445'
]]);
$collection2 = new Collection([
'bear1',
'whale2',
'chicken3',
'tardigrade4'
], [[
'bear',
'whale',
'chicken',
'tardigrade'
]]);
$collection1->each(function ($value, $key) use ($collection2){
return $collection2->contains($value);
});
dd($collection1);
});

use intersect https://laravel.com/docs/9.x/collections#method-intersect
for example:
$commonValues = $collection1->pluck("id")->intersect($collection2->pluck("id"));
dd($commonValues);
Then get common collections
dd($collection1->whereIn("id", $commonValues));

try this
$a1 = array(
array('name' => 'asdfjkl;', 'class' => 'foo'),
array('name' => 'qwerty', 'class' => 'bar'),
array('name' => 'uiop', 'class' => 'baz'),
);
$a2 = array(
array('name' => 'asdfjklk;', 'class' => 'foo'),
array('name' => 'qwertyxs', 'class' => 'bar'),
array('name' => 'uiop', 'class' => 'baz'),
);
$cc = array_uintersect($a1, $a2, 'cmp');
print_r($cc);
function cmp($a1, $a2){
return strcasecmp($a1['name'] , $a2['name']);
}

Related

Retrieving data from a countries API

I'm using an API to get a list of countries in Laravel. I have been able to isolate the countries list only but the countries now have an inner array with details of the country. I only need the name. I've tried using foreach but it didn't work.
This below is the result from the api
#items: array:2 [▼
"countries" => array:198 [▼
0 => array:4 [▼
"code" => "BT"
"name" => "Bhutan"
"geonameid" => 1252634
"depends_on" => null
]
1 => array:4 [▶]
This below is the code fetching it
$response = Http::withHeaders([
'x-rapidapi-host' => 'world-geo-data.p.rapidapi.com',
'x-rapidapi-key' => '1fa601995fmshcc1d2fcc97ee24cp1ac29djsn9b9b11cc10ec',
//'x-rapidapi-key' => config('app.rapid_api_key'),
])->get('https://world-geo-data.p.rapidapi.com/countries');
//dd($response->collect());
return $response->collect()->pluck('name')
->all();
I'm trying to get only the name value. the return is returning null
I think this is what you want:
return collect($response->collect()["countries"])->pluck('name');
The result will be like:

Laravel parameterBag as array issues when inserting

I am trying to insert mass data but i get this error when i iterate through the request:
Symfony\Component\Debug\Exception\FatalThrowableError Cannot use
object of type Symfony\Component\HttpFoundation\ParameterBag as array
Request example:
request: Symfony\Component\HttpFoundation\ParameterBag {#52 ▼
#parameters: array:4 [▼
"_token" => "Z1sF2K5LHU1bsQ4l3JRaOLCTQDmJ47qakigmrfI5"
"name" => "Rousaddasd 1"
"secsaddsans" => array:1 [▼
"secsdfs1" => array:2 [▼
"name" => "Sectdfs 1"
]
]
"submit" => "Submit"
]
}
Loop to go through the request and insert:
$abc = new abc;
$abc->create(['user_id' => 1, 'name' => $request->name, 'description' => 'test description']);
foreach($request as $item){
$asd = new asd;
$asd->name = $item['name'];
$asd->description = 'test description';
$abc->asds()->create([$asd]);
}
Im adding some data "inline" because i didnt handle them in the form yet, thats why the added duration and duration_unit for example.
You can use $request as array like this:
$request = $request->all();
And loop like:
foreach($request['sections'] as $item) {
....
foreach($item['exercises'] as $item2) {
....
}
}

Laravel resource ignoring given fields

I'm trying to convert a given API response in something easy to work with.
This is what I have so far:
Controller:
public function drive()
{
$optParams = [
'corpora' => 'drive',
'driveId' => env('GOOGLE_DRIVE_ID'),
'includeItemsFromAllDrives' => true,
'supportsAllDrives' => true,
'fields' => 'files(*)'
];
$results = $this->googleDrive->files->listFiles($optParams);
$data = collect($results);
$collection = new FileCollection($data);
dd($collection);
return 'Hi!';
}
FileCollection resource:
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => ['files_count' => $this->collection->count()],
];
}
File resource:
public function toArray($request)
{
return [
'name' => $this->resource['name'],
'mime' => $this->resource['mimeType'],
'parents' => $this->resource['parents'],
'version' => $this->resource['version'],
'webDownloadLink' => $this->resource['webContentLink'],
'webLink' => $this->resource['webViewLink'],
'modified_at' => $this->resource['modifiedTime'],
'size' => $this->resource['size']
];
}
This is the result I'm getting:
FileCollection {#223 ▼
+collects: null
+collection: Collection {#243 ▶}
+resource: Collection {#243 ▼
#items: array:2 [▼
0 => File {#224 ▼
+resource: Google_Service_Drive_DriveFile {#279 ▶}
+with: []
+additional: []
}
1 => File {#263 ▼
+resource: Google_Service_Drive_DriveFile {#269 ▶}
+with: []
+additional: []
}
]
}
+with: []
+additional: []
}
So as you can see the types of resources are correct, but for some reason the 'meta' in the FileCollection isn't there, nor are the fields in the File resource. All fields are still shown, like 30+ (instead of the 8 requested in the FileResource).
Am I missing something here?
EDIT:
When accessing the collection with the toArray() method ($collection->toArray(null)), I do indeed get the appropriate result:
array:2 [▼
"data" => Collection {#243 ▼
#items: array:2 [▼
0 => File {#224 ▶}
1 => File {#263 ▶}
]
}
"meta" => array:1 [▼
"files_count" => 2
]
]
So how do I make sure now that this collection uses the toArray() of the FileResources? (I'm still getting over 30 fields, instead of 8).
PS: I don't really get why I need to call the toArray(), nowhere in their documentation is it written : https://laravel.com/docs/5.8/eloquent-resources .

How to transpose this into an array?

I am trying to transpose a Collection into an array. I'm not sure what's the method to do this. I think it's due to my lack of understanding in the eloquent operators/commands. I've been trying with map but had not made any headway.
Data
Collection {#911 ▼
#items: array:4 [▼
"HIGH" => Collection {#902 ▼
#items: array:2 [▼
0 => Finding {#680 ▶}
1 => Finding {#681 ▶}
]
}
"MEDIUM" => Collection {#903 ▶}
"LOW" => Collection {#904 ▶}
"INFO" => Collection {#905 ▶}
]
}
I would like to transpose this into an array ['HIGH' => 2, 'MEDIUM' => 1, 'LOW' => 13 ...]
I tried to apply a map but it's not giving me what i want. (tried applying the below)
... ->map (function ($risk) { return $risk[0]; });
Looking for tips on learning about these map operators and also how to transpose the Collection result above. Any help will be the most welcome!
Use toArray function to convert the collection to the array
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
Hope this link helps you.
https://laravel.com/docs/5.7/collections#method-toarray

Laravel - Sortby date after GroupBy callback

I'm creating a collection and using a groupBy to group items together depending on the month, however after this I then want to it to go back to ascending date order (Jan/Feb/Mar). Here is my function that I'm using below;
private function monthByMonthAgentReferrals() {
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->where('source', 'AGENT')->get()
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
});
return $case;
}
At the moment when I display the results I get a return of the months in a random order;
Collection {#1982 ▼
#items: array:12 [▼
12 => Collection {#1321 ▶}
"07" => Collection {#1322 ▶}
10 => Collection {#1320 ▶}
"05" => Collection {#1991 ▶}
"06" => Collection {#1990 ▶}
"08" => Collection {#1989 ▶}
"01" => Collection {#1988 ▶}
11 => Collection {#1987 ▶}
"09" => Collection {#1986 ▶}
"02" => Collection {#1985 ▶}
"03" => Collection {#1984 ▶}
"04" => Collection {#1983 ▶}
]
}
How would I go about sorting by 'start_date' again? or would it be better to sort by the array key? Thanks.
You can use it like this:
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->selectRaw('table_name.*')
->where('source', 'AGENT')
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
})->orderBy('start_date')->get();
private function monthByMonthAgentReferrals() {
$case = Case::where('start_date', '>', Carbon::now()->subDays(360))
->where('source', 'AGENT')->get()
->groupBy(function($key) {
return Carbon::parse($key->start_date)->format('m');
})->toArray();
ksort($case);
return collect($case);
}
Converts the collection to an array, use the function ksort on the array and then recollect the array.

Resources