How to use orderBy and with in laravel? [duplicate] - laravel

This question already has an answer here:
How to use orderby on element that was joined with Laravel Eloquent method WITH
(1 answer)
Closed 4 years ago.
How to use orderBy() with with() relationship where orderBy needs column which is being brought in by using with().
UPDATED
return $rank = BusinessDetails::with(['rar' => function ($query) {
$query->orderBy('int_total_ratings_value', 'DESC');
}])
->select('pk_int_business_id', 'vchr_business_name',
'vchr_business_description', 'fk_int_category_id', 'fk_int_location_id')
->get();
Business Model
<?php
namespace App\BackendModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\User;
use App\BackendModel\BusinessImages;
use App\BackendModel\Categories;
class BusinessDetails extends Model
{
use SoftDeletes;
const ACTIVATE = 1;
const DEACTIVATE = 0;
public static $days=[
['name'=>'Monday','id'=>1],
['name'=>'Tuesday','id'=>2],
['name'=>'Wednesday','id'=>3],
['name'=>'Thursady','id'=>4],
['name'=>'Friday','id'=>5],
['name'=>'Saturday','id'=>6],
['name'=>'Sunday','id'=>7]
];
protected $dates = ['deleted_at'];
protected $primaryKey = 'pk_int_business_id';
protected $table = 'tbl_business_details';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'vchr_business_name', 'vchr_business_description', 'vchr_telephone_number', 'vchr_company_mobile_number', 'vchr_company_email', 'vchr_contact_person', 'vchr_logo_path', 'fk_int_category_id', 'date_date_of_establishment', 'vchr_website', 'time_open_hours', 'time_close_hours', 'time_lunch_hours','int_closed_on','int_status', 'int_review_status','fk_int_user_id','fk_int_location_id','vchr_map','vchr_holiday'
];
public function rar()
{
return $this->hasOne('App\BackendModel\OverallRating', 'fk_int_business_id', 'pk_int_business_id')
->select('fk_int_business_id', 'float_overall_ratings' , 'int_no_of_ratings', 'int_total_ratings_value', 'int_no_of_reviews', 'int_no_of_like');
}
}

You can pass a closure to the with() and apply order by there.
Here is an example
Model::with(['relation' => function($query){
$query->orderBy('column', 'ASC');
}]);
Updated
return $rank = BusinessDetails::with(['rar' => function ($query) {
$query->orderBy('rar.int_total_ratings_value', 'DESC');
}])
->select('pk_int_business_id', 'vchr_business_name',
'vchr_business_description', 'fk_int_category_id', 'fk_int_location_id')
->get();
Hope this helps.

Related

Recursive relationship and nested eager loading with constraints

I'm tryng to create nested eager loading with a where constraint on a recursive relationship
Models and query simulation:
Model Hierarchy
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Hierarchy extends Model
{
protected $table = 'hierarchy';
protected $primaryKey = 'id_hierarchy';
protected $fillable = [
'name',
'parent_id'
];
/**
* #return HasMany
*
* This method implement recursive relationship
*/
public function children()
{
return $this->hasMany(Hierarchy::class, 'parent_id')->with('children');
}
/**
* #return HasMany
*/
public function grandchildren()
{
return $this->hasMany(Grandchild::class, 'id_hierarchy');
}
}
Model Grandchild
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Grandchild extends Model
{
protected $table = 'grandchildren';
protected $primaryKey = 'id';
protected $fillable = [
'id_hierarchy',
'id_something'
'name'
];
/**
* #return BelongsTo
*/
public function hierarchy()
{
return $this->belongsTo(Hierarchy::class, 'id_hierarchy');
}
}
The following query does not return the grandchildren as it was supposed to;
public function read($id)
{
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children.grandchildren' => function ($query) use($id) {
$query->where('id_something', $id);
}])
->get();
}
The problem is in the constrain, because with the following query it returns the grandchildrren (although not filtered because it doesn't have the where condition)
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children.grandchildren'])
->get();
Thanks in advance for suggestions to resolve this issue.
Edited:
As the code is a simulation of the real case, I added 'id_something' to be clearer what is involved.
'id_something' is related to another model that is not represented here
Assuming that HomeCity is one of the related models for GrandChild and the relationship is defined as
//GrandChild.php
public function home_city()
{
return $this->hasMany(HomeCity::class);
}
Then the query to return GrandChild records who live in HomeCity (id_something is a column on home_city table) identified by $id may written as:
public function read($id)
{
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children' => function ($query) use($id) {
$query->with(['grandchildren' => function($query) use($id) {
$query->whereHas('home_city', fn($query) => $query->where('id_something', $id);
}]);
}])
->get();
}

Run an extra where clause in the model

Is it possible to specify a where clause for the model to run with each select?
Example:
I have a query $var = TestModal::where('date', '2021-06-08')->get(); and I want my TestModal to run ->where('type', 'r') for every query so I don't have to write it multiple times
You could use an Anonymous Global Scope to define the query for each Query running on the Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class TestModal extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope('type', function (Builder $builder) {
$builder->where('type', 'r');
});
}
}
yes you can use multiple where like this
var = TestModal->where(['date' => '2021-06-08', 'type' => '' ])->get();
or
var = TestModal->where('date' , '2021-06-08' )->where('type' , '')->get();
or can your addGlobalScope
protected static function booted()
{
static::addGlobalScope('table_name', function (Builder $builder) {
$builder->where('type', ');
});
}

Laravel relationship many to many filtering on pivot field

I have a relationship between Invoice and Shift.
Invoice model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'user_id',
'date_ins',
'closeco',
'closedrh',
'lvl',
'new',
];
public function user()
{
return $this->hasOne(User::class,'id','user_id');
}
/**
* The roles that belong to the invoice.
*/
public function shifts()
{
return $this->belongsToMany(Shift::class, 'invoice_shift')
->withPivot([
'invoice_id', 'shift_id', 'shift_taken_id', 'shift_swapped_date', 'shift_taken_date', 'tas',
'status_tas', 'status_co', 'status_drh', 'back_co',
'msg', 'msg_co', 'msg_drh'
])
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
Shift model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shift extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'code',
'description',
];
/**
* The users that belong to the role.
*/
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_shift')
->orderBy('status_drh', 'ASC')
->orderBy('status_co', 'ASC');
}
}
So I have a pivot table called Invoice_shift.
I cannot extract, starting from invoices table, just invoices that have tas (in invoice_shift table) = current logged user.
I cannot filter as a static value in Invoice model definition with wherepivot because it is dynamic value, every time logged user id is different.
I tried to do this in controller
$invoices = Invoice::with('shifts.invoices')
->orderBy('date_ins', 'DESC')->get();
$filter = $invoices->shifts()
->wherePivot('tas', '=', $user_id)
->get();
but I get an error because I think invoices are a collection ... I tried to insert a foreach...but it doesn't work.
The error message:
Method Illuminate\Database\Eloquent\Collection::shifts does not exist
How can I do this?
Thanks
$invoices is an instance of Illuminate\Database\Eloquent\Collection and therefore relationship shifts() cannot be used..
Maybe you need the correct Eloquent builder to filter invoices using whereHas("relationship", fn)
$filteredInvoices = Invoice::with('shifts.invoices')
->whereHas("shifts", function($query) use ($user_id) {
$query->wherePivot('tas', $user_id)
})
->orderBy('date_ins', 'DESC')
->get();

How to use relationship inside another relationship of other model?

I want to use public function scheduleTime() to check sechudle_time inside newsLetterSentOn() of News Model.
If this can be done,please help me regarding this.Thank you.
This is News Model
<?php
namespace Modules\Newsletter\Entities;
use Brexis\LaravelWorkflow\Traits\WorkflowTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
/**
* This is for storing news
* Class News
* #package Modules\Newsletter\Entities
*/
class News extends Model {
use WorkflowTrait;
protected $table = 'news_info';
protected $fillable = [
'title', 'header', 'description', 'status', 'created_by', 'media_url', 'media_thumbnail', 'media_type'
];
public function newsLetterSentOn() {
return $this->belongsToMany(Newsletter::class,'news_newsletters','news_id','newsletter_id')
->whereHas('scheduleTime', function($q){
$q->where('schedule_time', '<', date("Y-m-d h:i:s", time()));
});
}
}
This is Newsletter Model
<?php
namespace Modules\Newsletter\Entities;
use Illuminate\Database\Eloquent\Model;
class Newsletter extends Model
{
protected $table = 'newsletters';
protected $hidden = ['pivot'];
protected $fillable = [];
public function scheduleTime()
{
return $this->belongsTo(ScheduleTime::class,'id','newsletter_id');
}
}
You can get nested relationship with dot notation like so:
$news = News::with(['newsLetterSentOn.scheduleTime' => function($q)
$q->where('schedule_time', '<', date("Y-m-d h:i:s", time()));
])->find($id);
Then you can access it through $news like normal.
$news->newsLetterSenton->scheduleTime;

How to make dynamic query in laravel 5 with model and controller

i have Add query in codeigniter like this:
in controller:
$data=array(
'table'=>'tbl_activity_log',
'val'=>array(
'x'=>$x,
'y'=>$y,
'z'=>$z,
));
$log=$this->model->add_data($data);
And in model add_data function like this:
function add_data($data)
{
return $this->db->insert($data['table'],$this->security->xss_clean($data['val']));
}
But In Laravel 5 I have:
$name=$Request->input('name');
$lname=$Request->input('lname');
$myItems = array(
'first_name'=>$name,
'last_name'=>$lname
);
DB::table("tbl_user")->insert($myItems);
My question is, how can we make table field dynamic in Laravel and call that function through model.
Also, how can I call that function from model? Any help please. I want a dynamic query
You can write a helper function
//create a helper function
function addModelData($arrayData = [])
{
return \DB::table($arrayData['table'])->insert($arrayData['val']));
}
//in your controller or any place you like
$data=array(
'table'=>'tbl_activity_log',
'val'=>array(
'x'=>$x,
'y'=>$y,
'z'=>$z,
));
$log = addModelData($data);
You could create a model as described in official documentation:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'tbl_user';
// If your primary key is not 'id'
protected $primaryKey = 'model_id';
}
Now in your controller you can use this model:
namespace App\Http\Controller;
use App\User;
use Illuminate\Http\Request;
class MyController extends Controller {
public function myAction(Request $request){
$user = new User();
$user->last_name = $request->input('lname');
$user->first_name = $request->input('name');
$user->save();
}
}
You also could use mass assignment. But before you have to set the $fillable attribute in your model:
protected $fillable = ['first_name', 'last_name'];
Now you can use mass assignment in your controller:
$user = User::create([
'first_name' => $request->input('name'),
'last_name' => $request->input('lname')
]);
// alternatively:
$user = User::create($request->only(['name', 'lname']));

Resources