Laravel 5.4 eloquent relationship and local scope - laravel-5

I use laravel 5.4 and have 2 models, User and Provinces.
In model User:
public function scopeWithSort($query, $sorting, $by)
{
return $query->orderBy($sorting, $by);
}
public function province()
{
return $this->belongsTo('App\Province', 'loction_id');
}
In controller User:
$query = User::with('province')->select('*');
if ($request->sorting == 'location_id') {
$query->withSort('provinces.name', $request->by); // ** error line
}
How can I sorting by using this relation. Thanks advances!

You have to use a different approach.
You can order the query with a modified withCount():
if ($request->sorting == 'location_id') {
$query->withCount(['province' => function($query) {
$query->select('name');
}])->orderBy('province_count', $request->by);
}
Or you sort the query result:
$users = $query->get();
if ($request->sorting == 'location_id') {
$users = $users->sortBy('province.name', $request->by);
}

Related

Laravel Using nested with

I couldn't do what I wanted to do with Laravel, actually what I want to do is as follows,
I send getTruck id and list truckHistory with witdh, and I want to pull trukInvoice information with truckHistory invoice_id. But i am getting error where am i doing wrong?
Mysql Connection is as follows.
http://localhost:3000/truck/1
"trucks" table column "plate"
"invoice_details" column "plate_no"
"invoice_details" column "invoice_id"
"invoice" column "id"
Truck Controller
public function getTruck($id)
{
$truck = Truck::find($id)->with([
'truckHistory' => function($query){
// return $query->with(['trukInvoice']);
}
])->first();
return $truck;
}
Truck Model
public function companys()
{
return $this->belongsTo(Contact::class, 'company_id', 'id');
}
public function getCompanyNameAttribute()
{
return $this->companys()->first()->name;
}
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate');
}
public function trukInvoice(){
return $this->belongsTo(Invoice::class,'invoice_id','id');
}
Try this:
$truck = Truck::leftJoin('invoices', 'trucks.invoice_id', 'invoices.id')
->leftJoin('invoice_details', 'trucks.plate_no', 'invoice_details.plate')
->select('*')
->first();
or
$truck = Truck::with(['invoices' => function ($query) {
$query->whereHas('invoice_details', function ($q){
$q->whereNotNull('invoice_details.plate');
});
}])->first();
Check the documentation on restraining eager loads.

Laravel : Call to a member function with() on string

I'm struggling with Laravel since I'm still a beginner.
In my web.php I have the following route
Route::get('/customize/{id}', function ($id) {
if (User::where('id','=','4')->has('profile'->with('id',$id))->exists() && Profile::where('user_id', $id)->exists()) {
return true;
}
return false;
});
I know something isn't right.
Basically what I want to do is, return true ONLY IF The user with id 4 has a profile with the same id as the one in the url.
In my user modal I have the following relationship :
public function profile()
{
return $this->hasMany(Profile::class);
}
Example of the profiles table:
You've got a typo.
if (User::where('id','=','4')->has('profile'->with('id',$id))->exists() && Profile::where('user_id', $id)->exists()) {
Should be
if (User::where('id','=','4')->has('profile')->with('id',$id)->exists() && Profile::where('user_id', $id)->exists()) {
By doing 'profile'->with(...) you were calling a member function (with(...)) on a string ('profile').
To return true only if the User with id 4 has a profile with id = $id, you want to use whereHas.
if (
User::where('id', 4)->whereHas('profile', function ($query) use ($id) {
return $query->where('id', $id);
})
->exists()
) { ... }
Using PHP ^7.4, this can be written a bit more compactly with shorthand Closures.
if ( User::where('id', 4)->whereHas('profile', fn($query) => $query->where('id', $id))->exists() ) { ... }
By the way, when using where()/orWhere(), if you don't use an operator, it's implied to be '=' so where('id', '=', 4) can be written as just where('id', 4).

Laravel, sort result on field from relation table?

I have a list with gamers and another table with game stats.
My list code is:
$gamers = Gamer::with(['lastGameStat' => function($query) {
$query->orderBy('total_points', 'DESC');
}])->paginate(20);
relation:
public function lastGameStat() {
return $this->hasOne(GameStat::class, 'gamer_id', 'id')->orderBy('created_at', 'DESC');
}
in relation table I have field: total_points and with this code I thought it's possible to sort list of gamers by total_points $query->orderBy('total_points', 'DESC');
It doesn't work, can somebody give me an advice here how can I sort the result on a field from relation table?
I guess you'll need either another relation or custom scopes to fetch various game stats of a gamer.
Second relation
Gamer.php (your model)
class Gamer
{
public function bestGameStat()
{
return $this
->hasOne(GameStat::class)
->orderBy('total_points', 'DESC');
}
}
Custom scopes
Gamer.php
class Gamer
{
public function gameStat()
{
return $this->hasOne(GameStat::class);
}
}
GameStat.php
use Illuminate\Database\Eloquent\Builder;
class GameStat
{
public function scopeBest(Builder $query)
{
return $query->orderBy('total_points', 'DESC');
}
}
In your controller:
$gamersWithTheirLatestGameStatistic = Gamer::with(['gameStat' => function($query) {
$query->latest();
}])->paginate(20);
$gamersWithTheirBestGameStatistic = Gamer::with(['gameStat' => function($query) {
$query->best();
}])->paginate(20);
Be aware as this is untested code and might not work.

Custom attribute containing whether or not there's a relation between models

I have two models: User and Event.
Both have a polymorphic many to many relationship to each other.
Is there any way when I do Event::all()
to $appends a getJoinedAttribute() that returns true if the Auth::user() has a relation to each Event in the list?
public function getJoinedAttribute() {
return $this->whereHas('users', function($query) {
$query->where('users.id', Auth::user()->id);
})->count() > 0 ? true : false;
I guess I need something similar to this.
Here I try with my system:
In my Order Modal:
public function scopeOrderStatus($query, $status, $newOrder = null)
{
if ($newOrder !== null) {
return $query->where(function($filter) use ($status, $newOrder){
$filter->where('status', $status)->whereDate('created_at', $newOrder);
})->count();
}
return $query->where('status', $status)->count();
}
in Your Controller to access :
$pendingConfirmOrders = Order::orderStatus(1);

Laravel filter relation with where returns all

I try to filter my users by role in a subquery but returns all records
here I have a normal Model query which I extend with a subquery if the request contains the position parameter
$query = User::select()-> ....
and here comes the extension on $request->has('position')
if ($request->has('position')) {
$role = $request->get('position');
if ($role == 'all') {
$query->with('roles');
} else {
$query->with(['roles' => function($query) use($role) {
$query->where('id', $role);
}]);
}
} else {
$query->with('roles');
}
but this one returns the filtered and plus other users
I got it working using whereHas model method, here is the hole refactoring
if ($request->has('position')) {
$role = $request->get('position');
if ($role !== 'all' && $role !== 0 ) {
$query->whereHas('roles', function($query) use($role) {
return $query->where('id', $role);
});
}
}

Resources