How to use custom model function in eloquent - laravel

I want to get all user's online friends, how can I call a custom model function inside the eloquent condition?
this is my code
$friends = $user->friends()->where(function (Builder $query){
$query->where('friend', 'yes');
})
->get();
and this is my function in model
public function getIsOnlineAttribute(): bool
{
// check if the user is online or not
return $this->is_online;
}
I can access is_online after eloquent by foreach, but in my case, I want to check everything in one step ( inside where condition in eloquent). how can I do that???

You can't use conditions for eloquent accessors, in this case you can use (assume 1 is database column value):
$friends = $user->friends()->where('is_online', 1)->get();
or
$friends = $user->friends()->whereIsOnline(1)->get();
or you can create eloquent scope on your model:
public function scopeIsOnline($query) {
$query->where('is_online',1);
}
and you can use this eloquent scope on your controller in this way:
$friends = $user->friends()->isOnline()->get();

this worked for me :)
$friends = $user->friends()
->simplePaginate()
->reject(function ($friend) {
return $friend->is_online === false;
});

Related

How can I get a query with a conditional in a third relation?

Im using Laravel 7 and to get an array like this Array image spect result
And im working with Eloquent. This is my code for that array
**return EvaluateTeacherQuestion::with('evaluate_teacher_possibles_answers')->get();**
And this is my function evaluate_teacher_possibles_answers to make the relationship
public function evaluate_teacher_possibles_answers()
{
return $this->hasMany(EvaluateTeacherPossibilites::class)->withCount('evaluate_teacher_answers')->with('evaluate_teacher_answers');
}
And to get the third condition use this
public function evaluate_teacher_answers()
{
return $this->hasMany(EvaluateTeacherAnswer::class, 'evaluate_teacher_possible_id');
}
The problem is in the table evaluate_teacher_answers, I need get only this that if a condition (teacher_id = $teacher) is right.
When you add the whereHas condition a subquery is added.
Eg:
EvaluateTeacherQuestion::with('evaluate_teacher_possibles_answers')->whereHas('evaluate_teacher_possibles_answers',function($query){
$query->where('column','operation','value');
})->get();
With this way, will included relation in model and will execute conditions on closure from related model
Try this way:
remove with('evaluate_teacher_answers') from evaluate_teacher_possibles_answers relation:
public function evaluate_teacher_possibles_answers()
{
return $this->hasMany(EvaluateTeacherPossibilities::class)->withCount('evaluate_teacher_answers')->;
}
then load that relation with your condition:
$value = EvaluateTeacherQuestion::with(['evaluate_teacher_possibles_answers'=>function($query)use($teacher_id)
{
$query->with(['evaluate_teacher_answers'=>function($query)use($teacher_id){
$query = $query->where('evaluate_teacher_answers.teacher_id',$teacher_id);
}]);
}])->get();

Laravel Eloquent get all categories of restaurants?

I'm trying to get all categories of restaurants.
My models:
Restaurant
public function categories()
{
return $this->belongsToMany(Category::class,'restaurant_categories_relation','restaurant_id');
}
Category
public function restaurants()
{
return $this->belongsToMany(Restaurant::class,'restaurant_categories_relation', 'category_id');
}
In my controller:
$restaurants = Restaurant::where('district_id', $request->district)->paginate(8);
$categories = $restaurants-> ????;
Please help me do this, thanks!
You could use has() like :
Category::has('restaurants')->get();
That will return the categories who are related with the restaurants.
Try also the use of whereHas like :
$users = Category::whereHas('restaurants', function($q){
$q->->where('district_id', $request->district)->paginate(8);
})->get();
Since you've already a Collection we can't query the categories so I suggest adding a function to scope that inside the Restaurant model like :
public static function getCategoriesOfRestaurants($restaurants)
$categories = [];
foreach($restaurants as $restaurant){
array_push( $categories, $restaurant->categories->pluck('id')->toArray());
}
return Category::WhereIn('id', array_unique($categories))->get();
}
Then just call it when you get the $restaurants collection :
$restaurants = Restaurant::with("categories")->where('district_id', $request->district)->paginate(8);
$categories = Restaurant::getCategoriesOfRestaurants($restaurants);
Note: The use of with("categories") when getting the collection will query All the related categories in the first query so the foreach loop will not generate any extra query just looping through the already fetched data, and finally we will get the collection of categories in the return statement.
use with() method for eagerloading, that provides you get all categories in a single query
$restaurants = Restaurant::with("categories")->where('district_id', $request->district)->paginate(8);
foreach($restaurants as $restaurant){
foreach($restaurant->categories as $category)
{{$category}}
}
}
if you want to use categories outside of the loop, then assign these categories to a variable
foreach($restaurants as $restaurant){
$categories = $restaurant->categories;
}
// do something with $categories
Your relation should be
Restruant.php
public function categories() {
return $this->belongsToMany(Category::class,'restaurant_categories_relation','restaurant_id','category_id');
}
then in you controller method just wirte
$restruants = Restruant::with('categories')->get();
It should return you collection of all restruants with all related categories.

how to send variable from controller to model function in laravel

I want to send variable $typeid to function categories to use it in query is there a way Knowing that when I try to use new instance of class in my controller like that:
$cat= new Main_category();
$categories = $cat->categories()->get();
it returns empty array
the following code is working well when I manually add the typeid inside the model function I want to have it as a variable sent from controller
controller:
$categories = Main_category::with('categories')->get();
Model
public function categories()//($typeid)
{
$query = $this->hasMany(Category::class, 'main_cat_id')
->join('category_type','category_type.cat_id','=', 'categories.cat_id')
->join('main_categories','main_categories.main_cat_id','=', 'categories.main_cat_id')
->where('category_type.type_id', '1'); // I want to use $typeid here
return $query;
}
I am not sure whether you can pass your variable in eloquent relationship methods by using with method or not. But you can add a where clause in controller.
Main_category::with(['categories' => function($query) use($typeid) {
$query->where('category_type.type_id', $typeid);
}])->get();
Or you can create a query scope for model too.
in Model
public function scopeWithCategories($query, $typeid) {
return $query->with(['categories' => function($query) use($typeid) {
$query->where('category_type.type_id', $typeid);
}]);
}
and finally in Controller
Main_category::withCategories($typeid)->get();

How to add condition in connection tables?

I have two tables: Users and Images.
So, a user can have some images.
For this relationship I have additional function in model User:
public function images()
{
return $this->hasMany('App\Images', 'idElement', 'id');
}
And in controller I have:
$users = Users::where('id', $id)->with("images")->get();
How can I add additional condition in controller for images table that will be "where images.type = 1"?
Now this tables are connected only by primary keys, but I need to set a new condition yet.
You can filter your images with callback function, try this:
$users = Users::where('id', $id)->with(["images" => function ($query){
$query->where('type', 1);
}])->get();
For something like this, where you want to scope down a subset of images based on their type, you can add another method called something like public function scopedImages() and define it as such:
public function scopedImages() {
return $this->hasMany('App\Images', 'idElement', 'id')->where("images.type", "=", 1);
}
In your controller, you would access this function the same as you would the images() function on User:
$users = Users::where('id', $id)->with(["scopedImages"])->get();
Keep the function images() as well, so if you need to find all images attached to a User, but adding additional functions like this gives you flexibility on what you want to return and when.

Eloquent where condition based on a "belongs to" relationship

Let's say I have the following model:
class Movie extends Eloquent
{
public function director()
{
return $this->belongsTo('Director');
}
}
Now I'd like fetch movies using a where condition that's based on a column from the directors table.
Is there a way to achieve this? Couldn't find any documentation on conditions based on a belongs to relationship.
You may try this (Check Querying Relations on Laravel website):
$movies = Movie::whereHas('director', function($q) {
$q->where('name', 'great');
})->get();
Also if you reverse the query like:
$directorsWithMovies = Director::with('movies')->where('name', 'great')->get();
// Access the movies collection
$movies = $directorsWithMovies->movies;
For this you need to declare a hasmany relationship in your Director model:
public function movies()
{
return $this->hasMany('Movie');
}
If you want to pass a variable into function($q) { //$variable } then
function($q) use ($variable) { //$variable }
whereBelongsTo()
For new versions of Laravel you can use whereBelongsTo().
It will look something like this:
$director = Director::find(1);
$movies = Movie::whereBelongsTo($director);
More in the docs.
is()
For one-to-one relations is() can be used.
$director = Director::find(1);
$movie = Movie::find(1);
$movie->director()->is($director);

Resources