Laravel Eloquent querying pivot table not unique - laravel

For some reason I don't get the expected result when doing the following:
$cars = Car::query();
$cars->whereIsVisible(true);
# output: $list
// [2016-01-16 09:30:04] local.INFO: array (
// 0 => 5,
// 1 => 7,
// 2 => 9,
// 3 => 3,
// )
$cars->whereHas('specifications', function($query) use ($list) {
$query->whereIn('id', ($list));
});
$cars->get();
What I expect is that I get only cars that have all the specifications that are inside that $list, but that's not correct. Even when I fill in more specifications, I get a bigger result. So there goes something wrong.
I'm used to Eloquent, so I suck in queries. But this is the Query:
select * from "cars" where "cars"."deleted_at" is null
and "is_visible" = true
and (select count(*)
from "specs" inner join "car_specs"
on "specs"."id" = "car_specs"."facility_id"
where "car_specs"."car_id" = "cars"."id"
and "id" in (5, 7, 9 ,3)) >= 1
Anyone see where it goes wrong? And how to fix it?

According to https://laravel.com/docs/5.1/eloquent-relationships#querying-relations
whereHas just checks that you have cars with the provided specifications, not that it returns those cars that match your specifications.
I think you should use where directly.

Related

Laravel/Eloquent whereIn/where with a pair of sets

I have 3 tables in my database.
The first two tables are just normal tables with an ID and some other columns like:
Table 1
ID
col01
1
...
2
...
Table 2
ID
col01
1
...
2
...
The third table is some kind of a relation/assignment table:
Table 3
ID
table1_id
table2_id
text
1
1
1
..
2
1
2
..
3
1
3
..
4
2
1
..
5
3
3
..
Now I do have a SQL statement which does exactly what I want:
SELECT * FROM table_3 where (table1_id, table2_id) in ( (1, 1), (2, 1), (3, 3));
So Im sending following Request Body to the API:
{
"assignments": [
{
"table1_id": 1,
"table2_id": 1
},
{
"table1_id": 2,
"table2_id": 1
},
{
"table1_id": 3,
"table2_id": 3
}
]
}
I do validate my the request with
->validate($request,
[
'assignments' => 'required|array',
'assignments.*.table1_id' => 'required|integer|min:1|max:20',
'assignments.*.table2_id' => 'required|integer|min:1|max:20'
]
Now Im kinda stuck how to use the eloquent commands (e.g. whereIn) to get my desired output.
Thanks in advance!
EDIT
So I took the workaround of arcanedev-maroc mentioned here: https://github.com/laravel/ideas/issues/1021
and edited it to fit my Request.
Works like a charm.
Laravel does not provide any functions by default. The core team said that they would not maintain this feature. You can read the post here.
But you can create your own query to accomplish this. I am providing a function that you can use as per your specification:
public function test(Request $request)
{
$body=$request->input('data');
$data=json_decode($body)->assignments;
$query='(table1_id, table2_id) in (';
$param=array();
foreach($data as $datum)
{
$query=$query."(".$datum->table1_id.",".$datum->table2_id."), ";
}
$query = rtrim($query, ", ");
$query = $query.")";
$result=DB::table('table3')->whereRaw($query)->get();
return $result;
}
So I took the workaround of arcanedev-maroc mentioned here: https://github.com/laravel/ideas/issues/1021
and edited it to fit my Request.
Works like a charm.

Laravel whereHas not filtering as expected

The 2 models involved are JobRequest and StationJob. Really their relationship is oneToMany. I have a relationship set up for this $jobRequest->stationJobs().
Further to this I need a hasOne relationship latestStation, based on the same model. I need this relationship to filter my collection of JobRequests based on whether the JobRequest has a latestStation equal to a specified station.
I am expecting to get an empty list of JobRequests because I know the latestStation is equal to id 3 and I am filtering for id 2. Instead I get the jobRequest, with latestStation id 3 even though I am filtering for 2.
Relationship
public function latestStationTest()
{
return $this->hasOne(StationJob::class)->whereNotNull('finished')->latest();
}
Controller
$stationId = $request->station_id;
$jobRequests = JobRequest::with(['latestStationTest'])->whereHas('latestStationTest', function($query) use ($stationId) {
$query->where('station_id', $stationId);
})->get();
Query Result
[2020-10-17 07:39:07] local.INFO: array (
0 =>
array (
'query' => 'select * from `job_requests` where exists (select * from `station_jobs` where `job_requests`.`id` = `station_jobs`.`job_request_id` and `station_id` = ? and `finished` is not null)',
'bindings' =>
array (
0 => 2,
),
'time' => 1.0,
),
1 =>
array (
'query' => 'select * from `station_jobs` where `finished` is not null and `station_jobs`.`job_request_id` in (1) order by `created_at` desc',
'bindings' =>
array (
),
'time' => 0.5,
),
)
I've tried...
Switching with() before or after whereHas makes no difference.
adding ->where() to with() selects the StationJob with the specified id, instead of checking if the latestStation id is equal to the specified id.

Laravel Eloquent - where with and

Pic for table in blade:
and
See this pic for table in database:
In my advanced search I have 2 input box which is round 1 and round 2.
If I search for 1 in round 1 and also 1 in round 2 it should display only the data of id 1.
It's like:
$query->where(['column.round' => 1, 'column.score' => $request->score1] and ['column.round' => 2, 'column.score' => $request->score2]);
My question is how to have and operator with this to show only the data of id 1.
This is like multiple rows with the same id in 1 column.
if i get you right u only want one RAW back instead of a collection
if that is the case then:
$query->where(['round1' => 1, 'round2' => 1])->first();
Can you try this code. Refer here
$query->where(function ($roundQuery) {
$roundQuery->where('round', '=', 1)
->orWhere('round', '=', 2);
})
->where(function ($scoreQuery) use($request) {
$scoreQuery->where('score', '=', $request->score1)
->orWhere('score', '=',$request->score2);
})
->get();

Laravel WhereIn or Wheren with where

Im trying to design a query, but I have no idea where to start.
I'll type it out how I want it to function.
Items::whereIn('id',$ids)->orWhereIn('id_2',$ids)->where('type','!=',$type)->get();
Thats how I want it to work, but I know that wont work, because it will just ignore the WHERE type=$type query, because the whereIN's would have already pulled records, that dont adhere to the Where query.
Basically I want the eloquent version of this...
"SELECT * FROM items WHERE type!=$type AND (id IN (1,2,3) OR id_2 IN(1,2,3))"
What you are attempting to do is to group statements: https://laravel.com/docs/5.3/queries#parameter-grouping
What you need to do is to make the code something like this:
Items::where('type', '!=', $type)
->where(function ($query) use ($ids) {
$query->whereIn('id',$ids)
->orWhereIn('id_2',$ids);
})
->get();
That way you are grouping the where in clauses.
$user_id = 2 ;
$user_ids = [2,3,4,5,6,7,78,87,88,90] ;
where('id',$user_id) vs whereIn('id',$user_ids)
Note: where will compare with just first value of array or just one single value. and whereIn will compare evey index of array.
You're gonna want to do something like this:
Item::where('type','!=','ATypeTest')->where(function ($query) {
$query->whereIn('id',[1, 2, 3])->orWhereIn('id_2',[1, 2, 3]);
})->get();
Check the Laravel documentation on more regarding grouping: https://laravel.com/docs/5.3/queries#parameter-grouping
This will by the way generate the following SQL query:
SELECT * FROM "items" WHERE "type" != `ATypeTest` AND ("id" in (1, 2, 3) OR "id_2" in (1, 2, 3))

Laravel - Eloquent group by

When I use group by, the results get grouped but not all of them are returned. Here I have six results but I only get five results. So basically room_id = 17 gets the entry 103 and entry 106 is not returned.
Here is what I am doing:
$prices = $hotel->prices()->groupBy('room_id')->get();
There is a way of grouping the like you desire. You can use groupBy() on the collection eloquent returns when it executes the query. The trick is to groupBy() after the database retrieving. Check this for more info.
An example would look like this:
$prices = $hotel->prices()->get(); // Returns a Collection of results
$prices = $prices->groupBy('room_id'); // Grouped by room_id
This will result in a collection that looks like:
[
'39' => [
// 1 row
],
'40' => [
// 1 row
],
'17' => [
// 2 rows
],
.....
]
The keys of this array will represent the room_id. On every key is this array will be another array containing the rows with the specified room_id.
Hope this helps :)

Resources