I'm kinda stuck here while querying multiple relationships in laravel eloquent I had the raw query like
SELECT * FROM tblSchedules,tblUserHomeCourts,tblHomeCourts
where tblHomeCourts.userId=6
and tblHomeCourts.homeCourtId=5
and (tblSchedules.timeFrom <= 1495617580
and tblSchedules.timeTo >= 1495617580)
and tblUserHomeCourts.userHomeCourtStatus=1
and tblSchedules.scheduleStatus=0
now I need to query this raw query into laravel eloquent. I've tried to to do so like this
$getSchedule= Schedule::with(['userSchedule' => function($query) use ($userId,$homeCourtId,$timeFrom, $timeTo) {
$query->where(['userId'=> $userId,'homeCourtId'=>$homeCourtId,'userHomeCourtStatus' => Constant::STATUS_1]);
}]) ->where('timeFrom','<=',$timeFrom)
->where('timeTo','>=',$timeTo)
->where(['scheduleStatus'=>Constant::STATUS_0])
->get();
but I'm not getting the result instead of this I'm getting blank message array where I'm supposed to get the records.
Question:
what I have done wrong?
suggest me the correct way of query this query.
Schedule Model
public function friendsFeed(){
return $this->hasOne(UserHomeCourt::class,'userHomeCourtId','userHomeCourtId')->with('user')->with('homeCourt');
}
public function userSchedule(){
return $this->hasOne(UserHomeCourt::class,'userHomeCourtId','userHomeCourtId')->with('homeCourt');
}
UserHomeCourt Model
public function homeCourt(){
return $this->belongsTo(HomeCourt::class,'homeCourtId','homeCourtId');
}
public function user(){
return $this->belongsTo(User::class,'userId','userId');
}
}
HomeCourt Model
public function friendsFeed()
{
return $this->hasOne(UserHomeCourt::class, 'homeCourtId', 'homeCourtId');
}
public function userSchedule()
{
return $this->hasOne(UserHomeCourt::class, 'homeCourtId', 'homeCourtId');
}
Response I have got from SQL Query
The time check from your sql to eloquent was wrong and when you pass multiple conditions to where, you need to set the conditions as an array.
$getSchedule= Schedule::with(['userSchedule' => function($query) use ($userId, $homeCourtId) {
$query->whereHas('homeCourt', function ($query) use ($userId, $homeCourtId) {
$query->where('userId', $userId)
->where('homeCourtId', $homeCourtId);
})->where('userHomeCourtStatus', 1);
}])
->where('timeFrom', '<=', $timeFrom)
->where('timeTo', '>=', $timeTo)
->where('scheduleStatus', 0)
->get();
try to use whereHas function:
Schedule::whereHas('userSchedule', function ($query)
{
$query->where('userId', $userId)
->where('homeCourtId', $homeCourtId)
->where('userHomeCourtStatus', Constant::STATUS_1);
})
->where('timeFrom', '<=', $timeFrom)
->where('timeTo', '>=', $timeTo)
->where('scheduleStatus', Constant::STATUS_0)
->get();
Related
i have this index function that will show data from two different tables:
public function index()
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->get();
return view('admin.complaints',compact('complaints'));
}
and in the next function i want to show a single row using the same thing above by 'id'
i tired this:
public function show($id)
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->where('id', $id)->first()
->get();
return $complaints;
}
but i'm getting this error
Call to undefined method stdClass::get()
For creating where statements, you can use get() and first() methods. The first() method will return only one record, while the get() method will return an array of records , so you should delete first() , so the code should be like that .
public function show($id)
{
$complaints = DB::table('complaint')
->select(['complaint.id','complaint.createdDate','complaint.user_id','complaint.createdDate','complaint.complaint_title','tbl_users.phone','tbl_users.email'])
->join('tbl_users', 'complaint.user_id', '=', 'tbl_users.id')
->where('id', $id)
->get();
return $complaints;
}
I have two models which have a many-to-many relationship.
class User extends Model
{
function cars()
{
return $this->belongsToMany(Car::class);
}
}
class Car extends Model
{
function users()
{
return $this->belongsToMany(User::class);
}
}
I want to get users who used a specific set of cars:
$car_selected = [1, 3, 6];
$users = User::when(count($car_selected) > 0, function ($q) use ($car_selected) {
$q->whereIn('cars.id', $car_selected);
})
->get();
This gives too many results because of the 'whereIn' condition; what I want is 'whereAnd' something.
I tried this, but no luck.
$users = User::when(count($car_selected) > 0, function ($q) use ($car_selected) {
foreach($car_selected as $xx) {
$q->where( 'cars.id', $xx);
}
})
->get();
How can I get all users which have a relationship to cars 1, 3, and 6?
Your code provided doesn't make a lot of sense, but based on your explanation, you want to find a user who has a relationship with cars 1 and 3 and 6. Using whereIn() gets you users with relationships with cars 1 or 3 or 6.
Your attempt with multiple where() filters wouldn't work, as this would be looking for a single row in the pivot table with multiple cars, which obviously wouldn't be possible. Instead, you need to nest multiple whereHas() relationship filters into a single where() group like this:
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})
->with(['cars' => function ($q) use ($car_selected) {
$q->whereIn('car_id', $car_selected);
}])
->get();
This is all assuming you've correctly set up your relationships and tables per Laravel standards.
Demo code is here: https://implode.io/anjLGG
You can use the whereHas method to query relationship:
use Illuminate\Database\Eloquent\Builder;
User::whereHas('cars', function (Builder $builder) use($car_selected)
{
$builder->whereIn( 'cars.id', $car_selected);
})->get();
For more infos, check the doc
as #miken32 explained, I need to nest multiple whereHas() relationship filters into a single where() group.
#miken32 proposed following..
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})
->with(['cars' => function ($q) use ($car_selected) {
$q->whereIn('car_id', $car_selected);
}])
->get();
And I guess following is enough .
$users = User::where(function ($q) use ($car_selected) {
foreach ($car_selected as $car) {
$q->whereHas('cars', function ($query) use ($car) {
$query->where('car_id', $car);
});
}
})->get();
Thanks.
I need to query and check if the relationship column is the same in my main table column.
example codes:
not working
User::with('product', => function($q) {
$q->whereRaw('users.company_id',' product.company_id');
})->get();
not working
User::with('product', => function($q) {
$q->whereRaw('users.company_id = product.company_id');
})->get();
not working
User::with('product')->whereColumn('users.company_id', 'product.company_id')->get();
but it's not working..
any idea how to do it?
My Models
User Model
public function product()
{
return $this->belongsTo(Product::class, 'product_id');
}
Product Model
public function users()
{
return $this->hasMany(User::class, 'product_id');
}
Please try again:
User->with(['product' => function ($query) {
$query->join('users', 'users.company_id', '=', 'product.company_id');
}])->get();
Try to use DB:raw() then show the table info? like this
I have a model customer and it has many projects. I want to find projects count without including its object.
Customer model includes:
public function numberOfProjects()
{
return $this->hasMany(Project::class)->count();
}
Query in my controller:
$customers = Customer::where(['is_active'=>1])
->with(['customerContactInformation'=> function ($query) {
$query->where('is_active',1);
}, 'numberOfProjects'])
->skip($skip)->take(10)
->get();
Its giving me error:Call to a member function addEagerConstraints() on integer
Try this
Customer Model
public function numberOfProjects()
{
return $this->hasMany(Project::class);
}
Controller
$customers = Customer::where(['is_active'=>1])
->with(['customerContactInformation'=> function ($query) {
$query->where('is_active',1);
}])
->withCount('numberOfProjects') //you can get count using this
->skip($skip)
->take(10)
->get();
That should be work
$customers = Customer::withCount('numberOfProjects')->get();
WithCount on the particular status
$customers = Customer::withCount([
'numberOfProjects',
'numberOfProjects as approved_count' => function ($query) {
$query->where('approved', true);
}
])
->get();
class Tutorial extends Model
{
function chapters()
{
return $this->hasMany('App\Chapter');
}
function videos()
{
return $this->hasManyThrough('App\Video', 'App\Chapter');
}
}
And then you can do:
Tutorial::withCount(['chapters', 'videos'])
Counting Related Models
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models. For example:
$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
You may add the "counts" for multiple relations as well as add constraints to the queries:
$posts = App\Post::withCount(['votes', 'comments' => function ($query) {
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;
echo $posts[0]->comments_count;
You may also alias the relationship count result, allowing multiple counts on the same relationship:
$posts = App\Post::withCount([
'comments',
'comments as pending_comments_count' => function ($query) {
$query->where('approved', false);
}
])->get();
echo $posts[0]->comments_count;
echo $posts[0]->pending_comments_count;
If you're combining withCount with a select statement, ensure that you call withCount after the select method:
$posts = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;
I have the following set for relations in my eloquent models/db:
Student has many PhdReport
PhdReport has one Link
I need to get Students where the (single) most recent PhdReport (by the attribute date_to) is more than 6 months and the Link connected to the PhdReport has a status of 'complete'.
I am trying to do this using eloquent relationships and I'm pretty new to the concept of querying relationships so I would like to know if there's a better approach to the one I'm taking.
Here's the relevant code so far:
PhdReport.php
public function link()
{
return $this->belongsTo(\App\Models\Link::class);
}
Student.php
public function phdReport()
{
return $this->hasMany(\App\Models\PhdReport::class);
}
public function latestPhdReport()
{
return $this->hasOne(\App\Models\PhdReport::class)->latest('date_to');
}
/* this doesn't work! */
public function lastPhdReportSixMonthsAgo()
{
$sixMonthsAgo = \Carbon\Carbon::now()->subMonth(6);
return $this->whereHas('latestPhdReport', function ($query) use ($sixMonthsAgo) {
$query->where('date_to', '<=', $sixMonthsAgo);
});
}
This is my best shot at it so far but I am unsure if the first whereHas applies to the second whereHas also?
$sixMonthsAgo = \Carbon\Carbon::now()->subMonth(6);
$students = $this->student
->whereHas('phdReport.link', function ($query) {
$query->where('status', 'complete');
})
->whereHas('latestPhdReport', function ($query) use ($sixMonthsAgo) {
$query->where('date_to', '<=', $sixMonthsAgo);
})
->get();
If I run:
$students = $this->student
->has('lastPhdReportSixMonthsAgo')
->get();
I get:
BadMethodCallException in Builder.php line 1994:
Call to undefined method Illuminate\Database\Query\Builder::getRelated()
Any advice would be much appreciated!
This is my current solution, I haven't had time to refactor yet but I'm sure it can be improved by doing only a query and no filter. Will edit when I get time but thought I'd put it up as it might help someone else. Much credit to #JarekTkaczyk
$monthsAgo = \Carbon\Carbon::now()->subMonth($months);
// Query 1: students with a completed report
$studentsWithCompletedLink = $studentsWithCompletedLink
->whereHas('phdReport.link', function ($query) {
$query->where('status', 'complete');
})
->get();
if ($months != 0) {
// filter through to get students where the report date_to is more than $months months ago
$studentsWithReport = $studentsWithCompletedLink->filter(function ($student) use ($monthsAgo) {
return $student->latestReport->date_to <= $monthsAgo;
});
}
Student.php
public function latestPhdReport()
{
return $this->hasOne(\App\Models\PhdReport::class)->latest('date_to');
}