I want to order a query in laravel ways depending on certain factors. One of which would be a related table.
So right now my query goes like this:
$products = Product::where("price", "<=", $maxBudget)
and I know that I can add a function to my where clause like so
->where(function ($q) use($mature) {
if ($mature == "1") {
$q->where('mature', 1)->orWhere('mature', 0);
} else {
$q->where('mature', 0);
}
})
however I want to make a function for my order as well. Something like this (I know this is wrong, this is just an example):
->orderBy(function ($q) use($orderBy) {
if ($orderBy == "price_low") {
$q->orderBy('price', 'desc');
} elseif ($orderBy == "price_high") {
$q->orderBy('price', 'asc');
} elseif ($orderBy == "rating") {
$q->orderBy( $product->user->getAvgStarRating(), 'desc')
} else {
$q->orderBy('created_at', 'desc');
}
})
The $q->orderBy( $product->user->getAvgStarRating(), 'desc') is obviously wrong, $product isn't even defined, but you get the idea. In this scenario, I'd like to order my query based off the average rating of the creator of the product.
So my questions are: How do I make it so that I can add a function of some kind to my ordering, and how can I order a query based off related tables?
Define a user relationship (if haven't already):
public function user() {
return $this->belongsTo(User::class);
}
Then you can use a modified withCount():
Product::withCount(['user' => function($query) {
$query->select('avgStarRating');
}])->orderBy('user_count', 'desc');
You can also use a simple JOIN:
Product::select('products.*')
->join('users', 'users.id', 'products.user_id')
->orderBy('users.avgStarRating', 'desc');
can you try this
$products = Product::where("price", "<=", $maxBudget)
->where(function ($q) use($mature) {
if ($mature == "1") {
$q->where('mature', 1)->orWhere('mature', 0);
} else {
$q->where('mature', 0);
}
})
->orderBy(function ($q) use($orderBy) {
if ($orderBy == "price_low") {
$q->orderBy('price', 'desc');
} elseif ($orderBy == "price_high") {
$q->orderBy('price', 'asc');
} elseif ($orderBy == "rating") {
$q->join('users', 'users.id', '=','products.user_id')->orderBy('users.avgStarRating', 'desc')
} else {
$q->orderBy('created_at', 'desc');
}
})->get();
Related
I have course search everything works except, when $r->price it's returns all courses not last searched ones. I need to catch last "when" and then filter price by it.
How can i do that?
$courses = Course::when($r->mainCat, function ($query) use ($mainCat) {
$courseIdsArray = Direction::whereIn('course_category_id', $mainCat)->pluck('course_id')->toArray();
return $query->whereIn('id', $courseIdsArray);
})->when($r->level, function ($query, $level) {
return $query->where('level', 'like', "%{$level}%");
})->when($categories && count($categories) > 0, function ($query) use ($categories) {
return $query->whereIn('course_category_id', $categories);
})->when($r->price && in_array($r->price, ['more-expensive', 'less-expensive']), function ($query) use ($r) {
return $query->orderBy('price', $r->price == 'less-expensive' ? 'asc' : 'desc');
}, function ($query) {
return $query->statusOn()->order();
})->paginate(18)->appends($r->query());
I need to remove the pagination and leave everything on one page, but this way I'm doing it only generates BUG.
I wonder why the snippet of the commented code doesn't work to remove the pagination.
if ($minParam || $maxParam) {
$products = Product::whereHas('sizes', function ($query) use ($minParam, $maxParam) {
if ($minParam && $maxParam) {
$query->whereBetween('max_capacity', [$minParam, $maxParam]);
} elseif ($minParam) {
$query->where('max_capacity', '>=', $minParam);
} else {
$query->where('max_capacity', '<=', $maxParam);
}
})
->whereHas('solutions', function ($query) use ($solution_id) {
$query->whereIn('solution_id', $solution_id);
})
->where('active', 1)
->orderBy('position', 'ASC')
->get();
//->paginate(16);
} else {
$products = Product::whereHas('solutions', function ($query) use ($solution_id) {
$query->whereIn('solution_id', $solution_id);
})
->where('active', 1)
->orderBy('position', 'ASC')
->get();
//->paginate(16);
}
return view('solutions.show')->with(compact('solutions', 'solution', 'products', 'ranges'));
}
}
The bug after replacing with get ()
ErrorException (E_ERROR)
Method Illuminate\Database\Eloquent\Collection::links does not exist. (View: /app/server/resources/views/solutions/show.blade.php)
Previous exceptions
Method Illuminate\Database\Eloquent\Collection::links does not exist.
try changing ->paginate(16) to ->get() in all of the code like this:
whereHas('sizes', function($query) use($minParam, $maxParam) {
if($minParam && $maxParam) {
$query->whereBetween('max_capacity', [$minParam, $maxParam]);
} elseif($minParam) {
$query->where('max_capacity', '>=', $minParam);
} else {
$query->where('max_capacity', '<=', $maxParam);
}
})->
if ($minParam || $maxParam) {
$products = Product::whereHas('sizes', function ($query) use ($minParam, $maxParam) {
if ($minParam && $maxParam) {
$query->whereBetween('max_capacity', [$minParam, $maxParam]);
} elseif ($minParam) {
$query->where('max_capacity', '>=', $minParam);
} else {
$query->where('max_capacity', '<=', $maxParam);
}
})
->whereHas('solutions', function ($query) use ($solution_id) {
$query->whereIn('solution_id', $solution_id);
})
->where('active', 1)
->orderBy('position', 'ASC')
->get();
} else {
$products = Product::whereHas('solutions', function ($query) use ($solution_id) {
$query->whereIn('solution_id', $solution_id);
})
->where('active', 1)
->orderBy('position', 'ASC')
->get();
/*$products = Product::whereHas('solutions', function ($query) use ($solution_id) {
$query->whereIn('solution_id', $solution_id);
})
->where('active', 1)
->orderBy('position', 'ASC');*/
return view('solutions.show')->with(compact('solutions', 'solution', 'products', 'ranges'));
}
CODES IN CONTROLLER
public function getAthleteProperties(Request $request)
{
$getAthlete = DB::table('students')
->join('sports', 'students.id', '=', 'sports.athlete');
->select('students.*', 'sports.*')
->get();
if($request->input('gender') == 1)
{
//add this line of queries to $getAthlete queries
->where('gender', "m");
}
else
->where('gender', "f");
if($request->input('active') == 1)
{
//add this line of queries to $getAthlete queries
->where('active', "y");
}
else
->where('active', "n");
return view('admin', compact('getAthlete'));
}
Is it possible to append queries in laravel? For example I have codes as shown on above codes, if the condition for gender is 1 and active is 1 then in the end of the $getAthlete queries will become like this. Is it possible? How?
$getAthlete = DB::table('students')
->join('sports', 'students.id', '=', 'sports.athlete');
->select('students.*', 'sports.*')
->where('gender', "m") //added because condition is true
->where('active', "y") //added because condition is true
->get();
You don't have to use the "get" method at first, since it executes the select statement.
public function getAthleteProperties(Request $request)
{
$getAthlete = DB::table('students')
->join('sports', 'students.id', '=', 'sports.athlete')
->select('students.*', 'sports.*');
if($request->input('gender') == 1) {
//add this line of queries to $getAthlete queries
$getAthlete->where('gender', 'm');
} else {
$getAthlete->where('gender', 'f');
}
if($request->input('active') == 1) {
//add this line of queries to $getAthlete queries
$getAthlete->where('active', 'y');
} else {
$getAthlete->where('active', 'n');
}
$getAthlete = $getAthlete->get();
return view('admin', compact('getAthlete'));
}
UPDATE:
With the latest versions of laravel a conditional clause method was introduced. So we can do it this way:
$getAthlete = DB::table('students')
->join('sports', 'students.id', '=', 'sports.athlete')
->select('students.*', 'sports.*')
->when($request->input('gender') == 1, function ($query) {
return $query->where('gender', 'm');
}, function ($query) {
return $query->where('gender', 'f');
})
->when($request->input('active') == 1, function ($query) {
return $query->where('active', 'y');
}, function ($query) {
return $query->where('active', 'n');
})
->get();
How do I create brackets around my orWhere:
public function categories()
{
return $this->belongsToMany('App\Category', 'user_category')->orWhere('default', 1);
}
So it is converted to this:
where (`user_category`.`user_id` = ? or `default` = 1)
Currently the brackets here are missing and mess up the whole query. I tried for example:
public function categories()
{
$join = $this->belongsToMany('App\Category', 'user_category')
->orWhere('default', 1);
return $this->where(function ($query) use ($join) {
return $join;
});
}
But here I am loosing my model and getting Call to undefined method Illuminate\Database\Query\Builder::...
You can use advanced where clause like:
Model::where(function ($query) {
$query->where('a', '=', 1)
->orWhere('b', '=', 1);
})->where(function ($query) {
$query->where('c', '=', 1)
->orWhere('d', '=', 1);
});
Or nested clause like:
Model::where(function($query)
{
$query->where('a', 'like', 'keyword');
$query->or_where('b', 'like', 'keyword');
})
->where('c', '=', '1');
Are you trying to get all the categories related to an user and the categories where the default field is 1?
If that is the case:
public function categories()
{
return $this->belongsToMany('App\Category');
}
public function relatedCategories()
{
return App\Category::all()->where('default',1)->merge($this->categories);
}
The relatedCategories() method should return a collection with the desired categories. Take in care that the non-related categories but with default=1 will not have the pivot object, because these categories doesn't exist in your pivot table.
Can I use this code with if condition like this?
$testq= DB::table('attendances')
if($flag==1)
->where('type', '=', $userinput)
else
->where('type', '=', $newdate)
->get();
You can. This will work for you:
$query = DB::table('attendances');
if($flag == 1) {
$query->where('type', '=', $userinput)
} else {
$query->where('type', '=', $newdate)
}
$result = $query->get();