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());
Related
am trying to filter courses by single category or multi categories but it's not working.
$courses = Course::when($r->catId, function ($query, $catId) {
$category = CourseCategory::find($catId);
$catChildrenIdsArray = $category->children()->pluck('id')->toArray();
$catParentIdsArray = CourseCategory::whereIn('parent_id', $catChildrenIdsArray)->pluck('id')->toArray();
return $query->whereIn('course_category_id', $catParentIdsArray);
})
->when($r->level, function ($query, $level) {
return $query->where('level', 'like', "%{$level}%");
})
// PROBLEM NOT WORKING
->when($r->category, function ($query, $category) {
$query->when(is_array($category) && count($category) > 1, function ($query) use ($category) {
$query->where(function ($q) use ($category) {
foreach ($category as $cat) {
return $q->orWhere('course_category_id', 'like', "%{$cat}%");
}
});
}, function ($query, $category) {
return $query->where('course_category_id', 'like', "%{$category}%");
});
})
// END OF PROBLEM
->when($r->discount, function ($query, $discount) {
if ($discount == 1) {
return $query->where('discount', '!=', null);
}
})
->when($r->rate, function ($query, $rate) {
if ($rate == 1) {
$itemsRated = DB::table('ratings')->select('course_id', DB::raw('AVG(stars_rated) as count'))
->groupBy('course_id')->orderBy("count", 'desc')->get();
$courseIds = [];
foreach ($itemsRated as $item) {
array_push($courseIds, $item->course_id);
}
$fieldOrder = join(", ", $courseIds);
return $query->whereIn('id', $courseIds)->orderByRaw("FIELD(id, $fieldOrder)");
}
})
->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()->orderBy('id');
})->paginate(18)->appends($r->query());
Everything else is working discount filter or rating or level but i can't search single or multi categories its always search all categories in the blade am getting like this
<input name="category[]" type="checkbox" value="{{ $c->id }}">
Please can someone help me with this i'm trying to fix this two days... (
I believe you need to use an orWhere clause
instead of a where clause at the beginning of your when method's closure section.
Secondly, you're returning way too soon in your foreach loop. The return statement should be outside the loop.
$query->where(function ($q) use ($category) {
foreach ($category as $cat) {
return $q->orWhere('course_category_id', 'like', "%{$cat}%");
}
});
Thirdly, it doesn't make sense to pass the whole category[] request parameter array in the LIKE condition of the query.
}, function ($query, $category) {
return $query->where('course_category_id', 'like', "%{$category}%");
});
Solution
Hence the query for the category section could be:
// ... PROBLEM NOT WORKING
->when($r->has('category[]') && count($r->input('category[]')), function ($query) use ($r) {
return $query->orWhere(function ($q) use ($r) {
foreach ($r->input('category[]') as $cat) {
$q->orWhere('course_category_id', 'like', "%{$cat}%");
}
return $q;
});
})
// .... END OF PROBLEM
Have a query, how I can filter results by translation relation (by name column)
$item = Cart::select('product_id','quantity')
->with(['product.translation:product_id,name','product.manufacturer:id,name'])
->where($cartWhere)
->get();
my model
Cart.php
public function product($language = null)
{
return $this->hasOne('App\Models\Product','id','product_id');
}
Product.php
public function translations()
{
return $this->hasMany('App\Models\ProductTranslation','product_id','id');
}
Update v1.0
do like this, but query takes too long time
$item = Cart::select('product_id','quantity')
->with(['product.translation', 'product.manufacturer:id,name'])
->where($cartWhere)
->when($search,function ($q) use ($search) {
$q->whereHas('product.translation', function (Builder $query) use ($search) {
$query->where('name', 'like', '%'.$search.'%');
$query->select('name');
});
}
)
->get() ;
Inside the array within your with() method, you can pass a function as a value.
Cart::select('product_id','quantity')
->with([
'product', function($query) {
$query->where($filteringAndConditionsHere);
}
]);
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading
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();
based on the example from here https://scotch.io/tutorials/simple-and-easy-laravel-routing#blog-pages-with-categories-route-parameters
I want to show entries for specific categories.
By calling this Route:
Route::get('menues/{city?}', 'PagesController#menue');
I want to show all entries for a specific city.
This is my Controller:
public function menue($city = null) {
if ($city) {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}])->where('city', '=', $city)->get();
} else {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}])->where('city', '!=', $city)->get();
}
return view('pages.menues')
->withRestaurants($restaurants)
->withCity($city);
}
The only thing that doesn't work is, by calling a url with a {city} that doesn't exist in the DB I want to display all entries.
With the code above this doesn't happen. I get a blank page.
How can I fix this? My guess was that the code inside my else statement displays all entries, but this isn't the case.
Do the following:
public function menue($city = null) {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}]);
if(if(!is_null($city) && !is_null(City::where('name', $city)->first())) {
$restaurants->where('city', '=', $city);
}
$restaurants = $restaurants->get();
return view('pages.menues')
->withRestaurants($restaurants)
->withCity($city);
}
->where('city', '!=', $city) is the problem. If you want to get all articles, remove the condition.
Change the condition to:
if(!is_null($city) && !is_null(City::where('name', $city)->first())
Use Requests $request
public function menue(Request $request) {
if ($request->has('city')) {
I would do something like:
public function menue($city = null) {
if ($city) {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}])->where('city', '=', $city)->get();
if (restaurants->count() == 0) {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}])->get();
}
} else {
$restaurants = User::with(['articles' => function ($q){
$q->nowpublished();
}])->where('city', '!=', $city)->get();
}
return view('pages.menues')
->withRestaurants($restaurants)
->withCity($city);
}
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.