Relationship with user condition - laravel

I have a follow system that works like Twitter's follow (you follow other people and get updates from them).
I have this relationship set in my User.php model:
public function follows()
{
return $this->hasMany('App\Follow');
}
This obviously gets all records of users who follow this person.
However, when displaying the person's profile page, I want to get a relationship that checks if a follow record exists given the user ID.
Something like:
public function userFollow()
{
return $this->hasOne('App\Follow')->where('user_id', Auth::user()->id);
}
So now my profile page query looks like this:
$user = User::where('username', $username)
->with('userFollow')
->first();
This works as long as the user is logged in. If the user isn't logged in, the page gives me this error:
ErrorException in User.php line 28: Trying to get property of
non-object
How do I fix this? What is the proper way of using conditions in relationships?

This is because if user is logged out then Auth::user() is null, because user session has ended. Auth::user() is no more object, so you can't get the id from a null object.
Here you can do something like that
public function userFollow()
{
$userId = Auth::user() ? Auth::user()->id : $this->id;
return $this->hasOne('App\Follow')->where('user_id', $userId);
}
then it will not look for authenticated user, it will just get the particular user table's id.

The proper way of using conditions in relationships is using Constraining eager loads
public function userFollow()
{
return $this->hasOne('App\Follow');
}
And,
if(Auth::check())
{
$user = User::where('username', $username)
->with(['userFollow'=>function($query)
{
$query->where('user_id', Auth::user()->id);
}]);
->first();
}

Related

How to find user by user name in laravel?

I am trying to find user by user name while building a laravel API. This is what I'm trying
api.php
Route::get('user-profile/user/{user}', 'UserProfileController#getUserProfile');
Controller
public function getUserProfile(User $user)
{
$userId = User::where('userName', $user->userName)->first()->id; // I am expecting user id here like "1"
}
This causing 404 not found error.
By default route model binding will search for id.
You should customise the column name in your route if you want Laravel to select the user using the column userName.
In you api.php:
Route::get('user-profile/user/{user:userName}', 'UserProfileController#getUserProfile');
Assuming that your userName is unique in the table, then in your controller you should use:
public function getUserProfile(User $user)
{
$userId = user->id;
...
}
This will automatically handle 404 errors for you as opposed to this answer.
by default route model binding search for id and in your case you want search by username so all you need is to remove dependency injection from your controller parameters like this
public function getUserPortfolio($user) // fix it as $user only
{
$userId = User::where('userName', $user)->first()->id; // I am expecting user id here like "1"
}

Trying to count record by user id

I am trying to get record by user id.This is working for login user .
But I am Trying to get details for all users .Not only.
Here is model
public function referrer()
{
return $this->belongsTo('App\User', 'referred_by');
}
public function referrals()
{
return $this->hasMany('App\User', 'referred_by');
}
Now I am Getting refferals no from this code.
$referrals=auth()->user()->referrals()->count();
BUt I am Nedd to get same result for every user listing ..
means I need to change this query.by user_id.
This case you must be use withCount() method
$users = User::withCount('referrals')->get();
foreach ($users as $user) {
dd($user->referrals_count);
}
Pass the user_id to an eloquent query
$user_id = request()->get('id'); // Your user_id here
$referrals_count = \App\User::find($user_id)->referrals()->count();
Hope this helps

Why does this Eloquent relationship return null in a foreach loop?

I have a relationship that's acting weird. If I get the results and dd(), it has the correct data. However, if I run the collection through a foreach loop it's like the relationship disappears.
The users table has a field called referred_by, which stores the user ID of the person who referred the user. In my instance I'm looking for all the new users who were referred by the user with the ID of 3.
Here's the relationship in User.php
public function referrer()
{
return $this->belongsTo(User::class, 'referred_by');
}
Here's the code which is returning funky results
$users = User::where('referred_by', 3)
->with('referrer')
->get();
// doing dd() here returns a collection with full referrer relationship;
// the returned data is as expected
dd($users);
foreach($users as $user)
{
// dd($user) here returns the relationship, as it should
// dd($user->referrer) here returns null, like the relationship doesn't exist
}
Try with
foreach($users as $user)
{
// dd($user) here returns the relationship, as it should
dd($user['referrer'])
}
Rather then
// dd($user->referrer)
Turns out I had a database column on the users table named referrer that was causing an issue. I changed the relationship's method name from referrer() to referredBy() and it worked. *eyeroll*

Return relationship only if user is logged in?

I have a Posts and a Comments table, where each post can have multiple comments.
I want to make a query that gets all posts, and also all of the logged in user's comments.
Here is what I have so far:
$posts = Post::select('posts.*')
->with(['comments' => function($query) {
if (Auth::check()) {
$query->where('user_id', Auth::user()->id);
}
}])
->get();
And my Post.php model class looks like this:
class Post extends Model
{
public function comments()
{
return $this->hasMany('App\Comment');
}
}
The query returns the correct results when the user is logged in.
But when the user is not logged in, it returns the comments of ALL users, instead of returning nothing (because the user is logged in and therefore they have no comments).
How can I fix this?
you can do a little trick in your post model:
class Post extends Model
{
public function comments()
{
if(Auth::check()) {
return $this->hasMany('App\Comment')->where('user_id', Auth::user()->id);
}else{
return $this->hasMany('App\Comment')->where('user_id',-1);
}
}
}
and then simply :
$posts = Post::select('posts.*')->with('comments')->get()
so if user is not logged in it will return all comments with user_id of "-1" which will be nothing
There are two ways I can think of to this.
First you can only load the comments if the user is logged in:
$posts = Post::select('posts.*');
if(Auth::check()) {
$posts->with(['comments' => function($query) {
$query->where('user_id', Auth::user()->id);
}]);
}
$posts = $posts->get();
Or you could load all comments but set the user_id to null if the user isn't logged in. Since every comment should have a user_id no comments will be returned.
$posts = Post::select('posts.*')
->with(['comments' => function($query) {
$query->where('user_id', Auth::check() ? Auth::id() : null);
}])
->get();
The code in the second one looks cleaner IMO, but the first one will prevent an unnecessary query from being executed.
You can separate it, more legible and practical:
$posts = Post::all();
At your Post model create a function that will return all user's comments:
public function userComments()
{
return $this->comments->where('user_id', Auth::user()->id);
}
And i guess at your view you have a foreach to iterate all posts, inside your foreach you load post's comments, so you can do that:
#foreach($posts as $post)
$post->userComments()
#endforeach

How to query relationships in Laravel 4 with Eloquent?

Coming from CodeIgniter's Datamapper ORM I am still trying to get my head around Laravel's Eloquent ORM.
Given the fact that I have an ACCOUNT and a USER table (simplified):
ACCOUNT
- id
- name
USER
- id
- account_id
- username
One account has many users. One user belongs to one account. So we're dealing with a one-to-many relationship. Everything is already set-up in the models.
In CodeIgniter's Datamapper I would have done the following to get the user from any given ID and at the same time check if that user is related to the current account:
$u = new User();
$u->where('username', $username);
$u->where_related_account('id', $account_id);
$u->get();
if ( ! $u->exists()) exit; // or do something...
// otherwise continue to use the "$u" user object
This syntax is very logical and easy to understand. In Eloquent I have a hard time to achieve the same with a similar easy syntax. Does anyone have any suggestions?
Very simply (ignoring the relationship between the user and the account), it could just be:
$u = User::where('username', $username)
->where('account_id', $id)
->get();
That will return you your user's details.
Otherwise, assuming that you have your User and Account classes and DB tables are set up correctly (as per the Laravel docs), you should be able to just do:
$user_exists = Account::find($account_id)
->users()
->where("username", "=", $username)
->first()
->exists;
if ($user_exists)
{
doThings();
}
If you've correctly set up your models and database tables (as #msturdy said) you should actually be able to return your user account by simply going:
$user = User::whereUsername($username)
->first(); // or User::where('username', $username)->first();
if ($user) {
$account = $user->accounts()
->whereId($account_id)
->first(); // or $user->accounts()->where('id', $account_id)->first();
}
This gives you the ability to access the user and account models
you could even extend your User model to include the following methods:
class User extends Eloquent {
...
public static function byUsername($username) {
return static::whereUsername($username)->first();
}
public function getAccount($id) {
return $this->accounts()->whereId($id)->first();
}
...
}
and then simply go
$user = User::byUsername($username);
if ($user) {
$account = $user->getAccount($account_id);
}
which might be better for you if you are using the code in multiple controllers.

Resources