Left Join with Multiple on clause Eloquent Laravel - php

I have the following mysql query
select * from operatories o
left join apts ap on o.location = ap.Location and o.operatory = ap.Operatory;
I also have two models
class Operatories extends Model
{
public function operatories()
{
return $this->hasMany('App\Models\Appointment', 'Location', 'location');
}
}
Appointments:
class Appointment extends Model
{
public function operatories()
{
return $this->belongsTo('App\Models\Operatories', 'operatory', 'Operatory');
}
}
In my controller I am trying to write the mysql query,
this is what I have so far
$arrOperators = Operatories::leftJoin('appointment', function ($join) {
$join->on('appointments.location','=','operatories.location');
})
does anyone know how to write multiple on clause?

Related

How to limit query after with() method in laravel

i have 2 models. PostModel and CategoriesModel.
class PostModel extends Model
{
protected $table='posts';
protected $primaryKey = 'id';
protected $guarded=['id'];
public function categories()
{
return $this->belongsTo(CategoriesModel::class);
}
}
class CategoriesModelextends Model
{
protected $table='categories';
protected $primaryKey = 'id';
protected $guarded=['id'];
public function posts()
{
return $this->hasMany(PostModel::class);
}
}
I want to get 6 categories with 10 posts.
I used this code in my controller
$categories = CategoriesModel::with(['pages' => function($query) {
$query->limit('10');
}])->take("6")->get();
but this code is wrong. it applies to all records. But the truth is that this query applies per one categories. please help me.thanks
there is a laravel package specialized in this called Eloquent Eager Limit:
after installing it:
composer require staudenmeir/eloquent-eager-limit:"^1.0"
you should use it inside the models that would apply limited eager loading:
class PostModel extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ........
}
class CategoriesModel
extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ........
}
now this query will get the result you want:
$categories = CategoriesModel::with(['pages' => function($query) {
$query->limit('10');
}])->take("6")->get();
For eager loading you can do like this with map operation :
$categories = CategoriesModel::with('pages')->take(6)->get()
->map(function($q)
{ $q->pages = $q->pages->take(10); // take only 10 query
return $q;
}
);
The reason the above approach is necessary is because the constrained eager loading query roughly translates to SQL like:
Query to select Categories:
select * from `categories`
limit 6;
Query to fetch relation
select * from `categories`
inner join `posts` on `categories`.`id` = `posts`.`category_id`
where `posts`.`category_id` in (id's from categories query)
limit 10;
First of all your relation name is wrong in your controller. Update your category model by the following code:
public function ten_posts()
{
return $this->hasMany(PostModel::class)->take(10);
}
then update your controller with the following code:
$categories = CategoriesModel::with('ten_posts')->take(6)->get();
Try like this -
$categories = CategoriesModel::with(['pages' => function($query) {
$query->take('10');
}])->take("6")->get();

Eloquent - using a closure with a relationship

I have this problem with Laravel Eloquent.
I have two models - for simplicity's sake named:
A (id, name)
B (id, a_id, created_at)
relationship: A hasMany B
I need to return all B records filtered by these conditions:
A.name = given_name
B.created_at >= given_date
I want to do this by passing in a closure.
I searched through the laravel documentation on models:
https://laravel.com/docs/7.x/eloquent
https://laravel.com/docs/7.x/eloquent-relationships
and found these examples, but how do I put this together?
public function user()
{
return $this->belongsTo('App\User')->withDefault(function ($user, $post) {
$user->name = 'Guest Author';
});
}
function (Builder $builder) {
$builder->where('age', '>', 200);
}
You can do it using whereHas but first you need to define the relationship in your models like so:
A Model
class A extends Model
{
/**
* Get all B for the A.
*/
public function b()
{
return $this->hasMany(B::class);
}
}
B Model
class B extends Model
{
/**
* Get the B's A.
*/
public function a()
{
return $this->belongsTo(A::class);
}
}
Now after we defined the relationships just use whereHas with a Closure to check for extra conditions:
$allB = B::whereHas('a', function (Builder $query) {
$query->where('A.name', $givenName);
})->where('created_at','>=',$givenDate)->get();
You need to write this on A model
class A extends Model
{
public function aToB()
{
return $this->hasMany('App\B', 'a_id', 'id');
}
}
Then you need to write the query
$userData = A::where('name', $givenName)->with('aToB');
$userData = $userData->whereHas('aToB', function($query) use($givenDate){
$query->whereDate('created_at', date('Y-m-d', strtotime($givenDate)));
});
$userData = $userData->get();
dd($userData->aToB);

Laravel Eloquent model JOIN a MAX record

I'm new to Laravel and I'd like to know how to use eloquent model to join a max(date) record...
App\SchemasGroup::find(7)->schemas()->get()->max('schemasVersion')->get();
I find a group of schemas (schemas_groups table) based on ID, then get the schemas from that group (schemas table), and I want to join the 'date' and 'version' field from schemas_versions table with the last version (so, max date or version field) ...
Relations are defined as:
class SchemasGroup extends Model
{
public function schemas() { return $this->hasMany('App\Schema'); }
}
class Schema extends Model
{
public function group() { return $this->belongsTo('App\SchemasGroup'); }
public function versions() { return $this->hasMany('App\SchemasVersion'); }
}
class SchemasVersion extends Model
{
public function schema() { return $this->belongsTo('App\Schema'); }
public function updatedBy() { return $this->belongsTo('App\User','updated_by'); }
}
Getting the user name who updated that last version would also be lovely...
Apparently it was easy with defining chaining models.
class Schema extends Model
{
public function group() { return $this->belongsTo('App\SchemasGroup'); }
public function versions() { return $this->hasMany('App\SchemasVersion'); }
public function latestVersion() { return $this->hasOne('App\SchemasVersion')->latest(); }
}
and then fetching the data with:
App\SchemasGroup::with('schemas.latestVersion.updatedBy')->find($schemaGroupId);

Laravel: how I can write my onw function with own query on my model?

Example:
I wanna create my own function for laravel model like:
(original query)
SELECT
AVG(persons_positions.points)
FROM
positions
INNER JOIN persons_positions ON (
positions.id = persons_positions.position_id
)
WHERE positions.country = 1
AND persons_positions.person_id = 2
(model class)
class Menedzher extends Model {
function oh ($x) {
return DB::table('positions')
->join('persons_positions', 'positions.id', '=', 'persons_positions.position_id')
->where('positions.country', $x) // see here
->where('persons_positions.person_id', '=', $this->id ) // see it!!
->select(DB::raw('AVG(persons_positions.hits)'));
}
}
and to use it:
Menedzher::get(1)->oh(3)
Thanks!
Make one relationship in your Position Model like below
public function oh() {
return $this->hasOne('persons_positions')
->selectRaw('avg(hits) as hits, person_id')
->groupBy('person_id');
}
Then do this in controller
$user = Position::with('oh')->get();

How to get a specific column from the joined table in HasMany relationship in Laravel Eloquent

My Model looks like this
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class appraisaltask extends Model
{
//
protected $table = 'empappraisaltask';
/*
* An invoice can has many payments
*
*/
public function ratings(){
return $this->hasMany('App\appraisalrating','empappraisaltask_id')->select(array('comment', 'rating'));
}
}
and I am doing a query in my function like this
public function getUserbasictask(){
$taskwithcomments = appraisaltask::select(array('id','taskname','description','status'))->with( array('ratings' => function($query)
{
// the condition that will be apply on the with relation
$query->where('emp_id','=',Auth::user()->empid);
}))->where('type','=','basic')->get();
return json_encode($taskwithcomments);
}
But I am getting Empty Rating object . ANy suggestion how to do that
If I remove the select() from the rating function in the model I get all the details
Any help would be appreciated
i got your issue,update your ratings function in appraisaltask model
public function ratings()
{
return $this->hasMany('App\appraisalrating','empappraisaltask_id')->select(array('emp_id','comment', 'rating'));
}
and also update query
public function getUserbasictask(){
$taskwithcomments = appraisaltask::select(array('id','taskname','description','status'))
->with(['ratings' => function($query)
{
// the condition that will be apply on the with relation
$query->where('emp_id','=',Auth::user()->empid);
}])->where('type','=','basic')->get();
return json_encode($taskwithcomments);
}
hope it will work.

Categories