Laravel Eloquent unique() - Seems to not work - php

I'm using Laravel Eloquent to pick out unique answers.
So in my Database I have 3 answers, But they are under two different questions.
So all I would need returning back is the number 2, Not the number 3.
My code so far is :
$foundation_scores = Foundation::where('user_id', $this->user_id)
->where('foundation_section', 'theory')
->get();
$foundation_scores->unique('foundation_question');
$foundation_scores = count($foundation_scores);
The unique('foundation_question') is returning 3. It should return 2
Any ideas why this would be?
My collection looks as follows (NOTE) I've outputted it as an array to avoide all the code Laravel Returns :
array:3 [
0 => array:12 [
"foundation_id" => 3
"user_id" => 17019
"foundation_section" => "theory"
"unit_id" => 0
"foundation_sub_section" => "Unit 1"
"foundation_question" => 0
"foundation_reference" => "Ref one way st"
"foundation_answer" => "Ref answer st"
"created_at" => "2017-10-25 11:57:05"
"updated_at" => "2017-10-25 11:57:05"
"deleted_at" => null
"friendly_date" => "25th October 2017"
]
1 => array:12 [
"foundation_id" => 4
"user_id" => 17019
"foundation_section" => "theory"
"unit_id" => 0
"foundation_sub_section" => "Unit 1"
"foundation_question" => 0
"foundation_reference" => "Red"
"foundation_answer" => "Ans"
"created_at" => "2017-10-25 12:02:01"
"updated_at" => "2017-10-25 12:02:01"
"deleted_at" => null
"friendly_date" => "25th October 2017"
]
2 => array:12 [
"foundation_id" => 5
"user_id" => 17019
"foundation_section" => "theory"
"unit_id" => 0
"foundation_sub_section" => "Unit 1"
"foundation_question" => 1
"foundation_reference" => "XY"
"foundation_answer" => "Z"
"created_at" => "2017-10-25 12:02:19"
"updated_at" => "2017-10-25 12:02:19"
"deleted_at" => null
"friendly_date" => "25th October 2017"
]
]
Is their a bug with unique. Or is it something I'm doing wrong?

$foundation_scores->unique('foundation_question'); is not assigning unique values to any new variable. Also unique() does not change original collection.
So:
$unique_collection = $foundation_scores->unique('foundation_question');
echo count($unique_collection);

Related

Convert Collection to Array with I=ID in Laravel

I am beginner php developer.
I have small problem with my array. I use in my project Laravel 7
I have this code:
$items = collect($discount->products->toArray());
It's result me:
Illuminate\Support\Collection {#1783 ▼
#items: array:2 [▼
0 => array:17 [▼
"id" => 1
"product_category_id" => 5
"image_id" => null
"vat_type_id" => 1
"name" => "Produkt 1"
"slug" => "produkt-1"
"lead" => "<p>fewferfer</p>"
"description" => "<p> </p>"
"price" => "123.00"
"loyalty_program_points_price" => 2
"min_student_level" => null
"marked_as_available_at" => "2020-09-30T11:45:51.000000Z"
"deactivated_at" => null
"created_at" => "2020-09-30T11:45:23.000000Z"
"updated_at" => "2020-09-30T11:45:51.000000Z"
"deleted_at" => null
"pivot" => array:3 [▶]
]
1 => array:17 [▼
"id" => 2
"product_category_id" => 5
"image_id" => null
"vat_type_id" => 1
"name" => "Produkt 2"
"slug" => "produkt-2"
"lead" => "<p> </p>"
"description" => "<p>fergfer</p>"
"price" => "21.00"
"loyalty_program_points_price" => 3
"min_student_level" => null
"marked_as_available_at" => "2020-09-30T11:45:38.000000Z"
"deactivated_at" => null
"created_at" => "2020-09-30T11:45:38.000000Z"
"updated_at" => "2020-09-30T11:45:38.000000Z"
"deleted_at" => null
"pivot" => array:3 [▶]
]
]
}
I need convert it to this result:
Array{
1 => 1 (id)
2 => (id)
}
How can I make it?
I need array with only id values
Collections have the pluck method, which allows you to grab all the values of a specific key. To get all of the ids, you'd just need to do
$ids = $items->pluck('id')->all();
If you want them to have the same key as the id as well, pass that as the second parameter
$ids = $items->pluck('id', 'id')->all();
As a note, if products is a relation, then it's already a collection. You do not need to convert it to an array, then back to a collection:
$product_ids = $discount->products->pluck('id')->all();

Itterate to a multidimensional array

I am trying to iterate over this array in order to take all league values (league_id,name,type etc)
array:1 [▼
"api" => array:2 [▼
"results" => 970
"leagues" => array:970 [▼
0 => array:13 [▼
"league_id" => 1
"name" => "World Cup"
"type" => "Cup"
"country" => "World"
"country_code" => null
"season" => 2018
"season_start" => "2018-06-14"
"season_end" => "2018-07-15"
"logo" => "https://media.api-football.com/leagues/1.png"
"flag" => null
"standings" => 1
"is_current" => 1
]
1 => array:13 [▼
"league_id" => 2
"name" => "Premier League"
"type" => "League"
"country" => "England"
"country_code" => "GB"
"season" => 2018
"season_start" => "2018-08-10"
"season_end" => "2019-05-12"
"logo" => "https://media.api-football.com/leagues/2.png"
"flag" => "https://media.api-football.com/flags/gb.svg"
"standings" => 1
"is_current" => 0
]
.......
but until now,with the following code:
$request = json_decode($request->getBody()->getContents(), true);
foreach ($request as $array=>$val) {
foreach ($val['leagues'] as $id) {
dd($id);
}
}
the only thing that i can get is the first array only and not the rest:
array:13 [▼
"league_id" => 1
"name" => "World Cup"
"type" => "Cup"
"country" => "World"
"country_code" => null
"season" => 2018
"season_start" => "2018-06-14"
"season_end" => "2018-07-15"
"logo" => "https://media.api-football.com/leagues/1.png"
"flag" => null
"standings" => 1
"is_current" => 1
]
any help?
The dd() function you are calling is killing the execution of your script on your first iteration.
From the Laravel Docs:
The dd function dumps the given variables and ends execution of the script.
If you do not want to halt the execution of your script, use the dump function instead.
Just iterate over it like so:
$request = json_decode($request->getBody()->getContents(), true);
foreach ($request['leagues'] as $id=>$league) {
print_r(compact('id', 'league')); // To see the id and value array
}
Hope this helps,

return redis values in the middle of a foreach loop?

Wondering if it is even possible to return values from my redis cache while i am performing a PHP foreach loop?
I might be over thinking this...
essentially i have a MySql instance and a redis instance.
my MySql instance returns the following:
array:5 [▼
0 => array:6 [▼
"user_id" => 2
"short_url_key" => "aQpjoM"
"original_url" => "www.domain.com/"
"deleted_at" => null
"created_at" => "2017-03-11 08:19:02"
"updated_at" => "2017-03-11 08:19:02"
]
1 => array:6 [▼
"user_id" => 2
"short_url_key" => "olW7uN"
"original_url" => "www.domain.com/products/"
"deleted_at" => null
"created_at" => "2017-03-11 09:05:23"
"updated_at" => "2017-03-11 09:05:23"
]
2 => array:6 [▼
"user_id" => 2
"short_url_key" => "u4rjLA"
"original_url" => "www.domain.com/products/asdf"
"deleted_at" => null
"created_at" => "2017-03-11 09:05:56"
"updated_at" => "2017-03-11 09:05:56"
]
3 => array:6 [▼
"user_id" => 2
"short_url_key" => "fOuOju"
"original_url" => "www.domain.com/"
"deleted_at" => null
"created_at" => "2017-03-11 09:06:30"
"updated_at" => "2017-03-11 09:06:30"
]
4 => array:6 [▼
"user_id" => 2
"short_url_key" => "XmSBTK"
"original_url" => "www.domain.com/xyz"
"deleted_at" => null
"created_at" => "2017-03-11 09:18:54"
"updated_at" => "2017-03-11 09:18:54"
]
]
Now My Redis instance stores the short_url_key, the original_url & I store the visits their as well (which is what i am trying to return along with this data)
The visits just incriments on my redis key but would love to return this data along as well... Trying to think of how i can do that as part of my PHP loop? Or is their something I am not thinking of?
ideally I would like to append each of these arrays with the visits count from my redis instance.
"visits" => 22
update: I am able to loop through and return all the values... but now i am not sure how to merge that into the other array..
foreach ($datas as $data)
{
echo Cache::get('short:' . $data['short_url_key'] . ':visits');
}
exit();
Cheers
Citti
ok I was clearly overthinking this - I ended up appending to the array like below. Worked like a charm. cheers.
foreach ($data as $key => $value)
{
// will switch short_url_key to visits when i know they line up correctly
$data[$key][$value['short_url_key']] = Cache::get('short:' . $value['short_url_key'] . ':visits');
}

laravel whereNotIn not working

I have two different laravel query and i want to use second query with whereNotIn based on first query. but whereNotIn seems not working because the data still shown.
this the first query
$detailservice = DetailServiceOrder::leftJoin('services', 'detail_service_orders.service_id', '=', 'services.id')
->select('detail_service_orders.*',
'services.service_name')
->where('sales_order_id', $id)
->get();
this the second query
foreach ($detailservice as $data) {
$service[] = Service::whereNotIn('id', [$data->service_id])->get();
}
dd($service);
and here my dd($service) result sample
#attributes: array:4 [▼
"id" => 2
"service_name" => "Mail Service"
"created_at" => "2016-11-26 02:15:24"
"updated_at" => "2016-11-26 02:15:24"
]
#attributes: array:4 [▼
"id" => 1
"service_name" => "Network Maintenance"
"created_at" => "2016-11-15 07:00:45"
"updated_at" => "2016-11-15 07:00:45"
]
and here my dd($detailservice) result sample
#attributes: array:10 [▼
"sales_order_id" => 6
"service_id" => 1
"order_type" => "add"
"select_plan" => "test 1"
"qty" => 2
"unit_price" => 200.0
"note" => "testing 1"
"updated_at" => "2016-12-22 01:34:00"
"created_at" => "2016-12-22 01:34:00"
"service_name" => "Network Maintenance"
]
#attributes: array:10 [▼
"sales_order_id" => 6
"service_id" => 2
"order_type" => "change"
"select_plan" => "test 2"
"qty" => 3
"unit_price" => 400.0
"note" => "testing 2"
"updated_at" => "2016-12-22 01:34:00"
"created_at" => "2016-12-22 01:34:00"
"service_name" => "Mail Service"
]
the above dd($service) result should not shown because it was filtered on second query.
Your code works just fine. First, it gets results where ID is not 1 (so, it gets 2) and then it returns results where ID is not 2 (returns object where ID is 1).
If you want to get results where ID is not 1 or 2, use this instead of foreach():
$services = Service::whereNotIn('id', $data->pluck('service_id'))->get();

Push a set of values to an array based on another unique value in the same array

Question background
Hello, I have the following array of movie crew members:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ed7"
"department" => "Writing"
"id" => 139098
"job" => "Story"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story"
"name" => "Ben Coccio"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee3"
"department" => "Writing"
"id" => 139098
"job" => "Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
4 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5ee9"
"department" => "Writing"
"id" => 132973
"job" => "Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
5 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
11 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
As you can see this is a list of credits I'm getting via the TMDb API. The first step of building the above array was to filter out all jobs that I don't want to display, here's how I did that:
$jobs = [ 'Director', 'Director of Photography', 'Cinematography', 'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer' ];
$crew = array_filter($tmdbApi, function ($crew) use ($jobs) {
return array_intersect($jobs, $crew);
});
My question
I'd like to figure out how to take the above result one step further and combine jobs where the id is the same, so as to end up with something like this, for example:
array:7 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
I have also considered ditching doing this in my logic and instead doing it in my blade template, but I'm not sure how to achieve that.
How would you accomplish this?
You could nicely use Laravel's Collection in such a situation, which has a great number of methods which will help you in this case.
First, turn this array (the one you already filtered on jobs) to a Collection:
$collection = collect($crew);
Second, group this Collection by it's ids:
$collectionById = $collection->groupBy('id');
Now, the results are grouped by the id and transformed to a Collection in which the keys correspond to the id, and the value an array of 'matching' results. More info about it here.
Finally, just a easy script that iterates through all the results for each id and combines the job field:
$combinedJobCollection = $collectionById->map(function($item) {
// get the default object, in which all fields match
// all the other fields with same ID, except for 'job'
$transformedItem = $item->first();
// set the 'job' field according all the (unique) job
// values of this item, and implode with ', '
$transformedItem['job'] = $item->unique('job')->implode('job', ', ');
/* or, keep the jobs as an array, so blade can figure out how to output these
$transformedItem['job'] = $item->unique('job')->pluck('job');
*/
return $transformedItem;
})->values();
// values() makes sure keys are reordered (as groupBy sets the id
// as the key)
At this point, this Collection is returned:
Collection {#151 ▼
#items: array:4 [▼
0 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5e9d"
"department" => "Directing"
"id" => 139098
"job" => "Director, Story, Screenplay"
"name" => "Derek Cianfrance"
"profile_path" => "/zGhozVaRDCU5Tpu026X0al2lQN3.jpg"
]
1 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5edd"
"department" => "Writing"
"id" => 132973
"job" => "Story, Screenplay"
"name" => "Ben Coccio"
"profile_path" => null
]
2 => array:6 [▼
"credit_id" => "52fe49dd9251416c750d5eef"
"department" => "Writing"
"id" => 1076793
"job" => "Screenplay"
"name" => "Darius Marder"
"profile_path" => null
]
3 => array:6 [▼
"credit_id" => "52fe49de9251416c750d5f13"
"department" => "Camera"
"id" => 54926
"job" => "Director of Photography"
"name" => "Sean Bobbitt"
"profile_path" => null
]
]
}
Note: to use this Collection as an array, use:
$crew = $combinedJobCollection->toArray();
There are multiple ways to achieve this, for example: search the array for overlapping id's, but I think this is the easiest way to achieve this.
Goodluck!
Since you are trying to edit the array elements and its size, I believe array_map() or array_filter() won't be a solution to this.
This is what I could come up with...
$jobs = [
'Director', 'Director of Photography', 'Cinematography',
'Cinematographer', 'Story', 'Short Story', 'Screenplay', 'Writer'
];
$crew = [];
foreach($tmdbApi as $key => $member) {
if($member['id'] == $id && in_array($member['job'], $jobs)) {
if(!isset($crew[$key])) {
$crew[$key] = $member;
} else {
$crew_jobs = explode(', ', $crew[$key]['job']);
if(!in_array($member['job'], $crew_jobs)) {
$crew_jobs[] = $member['job'];
}
$crew[$key]['job'] = implode(', ', $crew_jobs);
}
}
}
Hope this answers your question :)

Categories