how to compare two collection and get match records - php

I am using Laravel and I have two different collections that contain ID of products
First one is colorProduct and second is tagProduct
so I want to compare these two and get only same ID of products so how can I do this?
$colorProducts = Color::where('code', $request->color)->get()->first()->products;
$tagProducts = $tag->products->where('shop_id', $shop->id);
$colorAndTagProducts = collect();
foreach ($colorProducts->toBase()->merge($tagProducts)->unique('id')->groupBy('id') as $allProducts) {
if ($allProducts->count() >= 1) {
$colorAndTagProducts[] = $allProducts->first();
}
}
here
$colorAndTagProducts
gives me all records form both collection but I only want same record

I dont know, if I understand correctly, but maybe like this?
I suppose Color and Product are in many to many relationship. And Product and Shop/tag in one to many.
$colorId = Color::where('code', $request->color)->get()->first()->id;
$shopId = $shop->id;
$products = Product::whereHas('colors', function ($query) use ($colorId) {
$query->where('id', $colorId); //id or color_id
})->where('shop_id', $shopId)->get();

intersect()
The intersect method removes any values from the original collection
that are not present in the given array or collection. The resulting
collection will preserve the original collection's keys:
I did it with this method

Related

Laravel pagination with specific foreign key

I need to make pagination in Laravel, and as I read laravel documentation here is a several way to do it. but in my cases it is a little bit complexity. So let say I've two table in my DB, table1 and table2(many to many relationship), I want to paginate table1 with specific ids. So I mean if table1 contains ids 1,2,3,4,5 ... n, I want to paginate only rows which id is 2 and 3
I have tried :
private function check_wear($type){
$products_id = array(); //here is ids which $type is set as 'ON'
$wears = DB::select("SELECT prod_id FROM wears WHERE ".$type." = 'on' "); //Select specific products ids. (in our case it is **table1**)
foreach ($wears as $wr){
array_push($products_id,$wr->prod_id);
}
return $products_id; //return array with ids which should be paginate
}
public function hat($locale){
$hat_prod_ids = $this->check_wear('coat');
$p=12;
$products = DB::table('products')->paginate($p); // 12 per page
dd($products);
my code only paginate one table with all data, is there any built-in function to somehow write a logic condition? for pagination
If you need to filter your pagination with elements which you've in $hat_prod_ids, you're able to use WhereIn() method, that one checks if your elements (in our case ids) exist in your $hat_prod_ids and returns true or false
$products = DB::table('products')
->whereIn('id',$hat_prod_ids)
->paginate($p);
add that code and now you will be able to paginate only that ids which is matched in your array

Laravel: sorting collection by last name in single string

i'm trying to sort a collection, which consists of ids and full names, alphabetically by the last name.
the id comes from a parent class and the full name from the child.
I tried exploding the string and ordering according to the last name, but couldn't really get it to also reorder th IDs properly.
I tried both with sortBy while getting the collection and with usort after retrieving it
$testExaminers=TestExaminer::where('test_id',$request->testid)
->with('examiner')
->get()
->sortBy('examiner.name');
$result = array();
$num=0;
foreach($testExaminers as $testExaminer) {
$result[$num]['id'] = (int) $testExaminer->examiner_id;
$result[$num]['text'] = $testExaminer->examiner->name;
$num++;
}
echo json_encode(['examiners'=>$result]);
The code above works fine for sorting it by first name, but I need it to sort by last name.
user inputs test_id, which gives a list of "TestExaminers", each has a property "examiner_id" associated with a unique "examiner", which in turn has a name "firstname middlename lastname".
so it should look something like this
before sort
$result = [[1,'Alpha Z. Goodman'],[2,'Joe Bman'],[3,'ZZ Top'],[4,'Joe Aman']]
after sort
$result = [[4,'Joe Aman'],[2,'Joe Bman'],[1,'Alpha Z. Goodman'],[3,'ZZ Top']]
Thanks!
How about trying something like this?
$testExaminers = TestExaminer::where('test_id', $request->testid)
->with('examiner')
->get()
->map(function ($item, $key) {
$item->examiner->last_name = array_slice(explode(' ', $item->examiner->name), -1)[0];
return $item;
})
->sortBy('examiner.last_name');

Retrieving items Based on multiple IDS in Laravel

I have a relationship between employees and items. It's a one-to-many relationship (i.e employee can have many items).
For instance, there are two employees Mark and Bill.
Mark bought items with item_no 1-0234, 1-0235 respectively.
Bill bought items with item_no 1-0236, 1-0237 respectively.
Item numbers are unique and therefore can be used to find the customer who is in possession.
This is my code to find customers items belong to. I select ids of all items using a checkbox.
What I am looking to achieve is, I want to find all employees based on the item selected, retrieve the phone numbers and item_nos using explode and process a message to them.
Controller
<?php
public function processMessage(Request $request)
{
$ids = $request->ids; // i am able to get the item_nos selected, eg. 1 - 0234, 1 - 0236
$split = explode(",", $ids);
if (request()->ajax()) {
$employees = Employee::whereHas('items', function ($emp) use ($split) {
$emp->where('id', $split);
})->get();
$get_name = [];
$get_phone = [];
foreach ($emps as $key => $emps) {
$get_name[] = $emps->name;
$get_phone [] = $emps->phone;
}
}
return ['success' => $get_phone];
}
PS: in the code, imagine i have selected two items with item_nos 1-0234, 1-0236. That is, my code should return two phone numbers, i.e for Mark and Bill but it returns just one of them, which is Mark's. Why is this happening
If i correct, following should help inside your query function-
$emp->whereIn('id',$split);

Issue with Laravel Eloquent Filters while trying to assign a field

I need to use filters to generate a collection with Laravel. I have a Project model which has many Investments. I make a query and retrieve a collection at the $projects variable. Then, there is a collection inside each one of the $projects collection called investments. I need to retrieve only the projects which have investments such that:
$investments->status = 'paid' && $investments->user_id is contained in $users_list
I used two nested filters, one for the projects collection and another one for the investments collection. I use the inner investments collection to filter by status and user_id and assign the filtered collection to $filtered_investments. Then I try to modify the unfiltered investments collection inside each project collection and replace it by $filtered_investments, however that does not happen. The investments filter works well but $filtered_projects contains its original investments collection instead the one I calculated.
Is there a way to do this? Thanks!
$projects = Project::has('investments')
->with('investments')
->get();
$users_list = [54];
$investment_status = 'paid';
$filtered_projects = $projects->filter(function($proj_value,$proj_key) use ($users_list,$investment_status){
// Calculate the filtered_investments collection checking the status and user_id fields
$filtered_investments = $proj_value->investments->filter(function($inv_value,$inv_key) use ($users_list,$investment_status){
$return = $inv_value->status == $investment_status && in_array($inv_value->user_id,$users_list);
return $return;
});
// Here I have a new filtered_investments collection which I want to assign to
// the current project investments field.
$proj_value->investments = $filtered_investments;
// This is only to return the current project if there is at least one
// element inside $filtered_investments
return $filtered_investments->count() > 0;
});

Laravel relations, select next raleted row from database.

I have related items in my database. I selected all of items from database by related id:
$next_stock = $this->model->get()->where('part_id', $in_data['part_id'])->all();
and I collection of rows grouped by one specific id, like on the picture. All of them selected by "part_id":
Selection Of Items
Grouped By Same Id
Also with this line of code i can select one of the items from this collection:
$next_stock = $this->model->get()->where('id', $old_stock['id'])->where('part_id', $in_data['part_id'])->first();
But how can I select the following items after this one?
Or, how can I select second or third item from this collect?
I cannot just increase id number by one from first, because sometimes this item ids not following each other.
Having a collection, you can take a specific element in the position with a combination of take() and last().
$collection = $this->model->get()->where('part_id', $in_data['part_id'])->all();
$second = $collection->take(2)->last(); //if this doesnt work, do it in 2 steps
$third = $collection->take(3)->last(); //if this doesnt work, do it in 2 steps
If you don't have a collection, take directly from database like this
$second = $this->model
->where('part_id', $in_data['part_id'])
->skip(1)
->first();
If it doesn't work with first()
$collect = $this->model
->where('part_id', $in_data['part_id'])
->skip(1)
->take(1)
->get();
$second = $collect->first();
Edit
skip() and take() are actually part of the query builder, not eloquent model. So it won't work with Eloquent in Laravel 5.4
Try with
$collect = $this->model
->where('part_id', $in_data['part_id'])
->get(1); //For the second record, 0 being the first
If you aren't doing it yet, you should set your model's relationships.
E.g. If you use "one-to-many", Eloquent will automatically determine the proper foreign key column on the model for you.
$parts = App\Stock::find(1)->partId;
foreach ($parts as $part) {
//
}

Categories