using a foreign key or not? - php

I have a table named 'Feedbacks' with 5 fields:
('id', 'user_id', 'instruction', 'description', 'fk_eleve')
The admin can create several recordings, here is a screenshot.
Here, I have a recording which is Menier Jeremy it's the student
In my rubric 'Eleves' (english: Student) we can see several recordings:
Here, Menier Jeremy has like email address test#gmail.com.
Menier Jeremy wants to connect...
There are 2 rubrics for now:
- Student Profil and Feedback
the user Menier Jeremy can see his profil
However, when the user wants to see his 'feedback'.
Unfortunately, I get the following error message:
SQLSTATE [42S22]: Column not found:
1054 Field Field 'email' unknown in where (SQL: select count (*) as aggregate fromreturnswhere email= test#gmail.com)
I have a problem with the email ?
public function index(Request $request)
{
$user = $request->user();
$feedbacks = Feedback::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
$query->where('email', $user->email);
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->join('eleves', 'feedbacks.fk_eleve', '=', 'eleves.id')
->orderBy('eleves.nom', 'asc')
->where('eleves.nom', 'like', '%'.$request->input('search').'%');
})
->paginate(5);
return view('admin.feedbacks.index', compact('feedbacks'))
->with('display_search', $user->hasRole('admin'));
}
Do know you where is the problem?
Thank you a lot
Edit code #Watercayman
When, the user Jeremy Menier is connected, I see several recordings:
I have to retrieve only ID n° 1
public function index(Request $request)
{
$user = $request->user();
$feedbacks = Feedback::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
\Auth::user()->load('feedbacks');
$feedbacksForThisUser = \Auth::user()->feedbacks;
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->join('eleves', 'feedbacks.fk_eleve', '=', 'eleves.id')->orderBy('eleves.nom', 'asc')->where('eleves.nom','like','%'.$request->input('search').'%');
})
->paginate(5);
return view('admin.feedbacks.index', compact('feedbacks'))
->with('display_search', $user->hasRole('admin'));
}
My model User:
public function feedbacks()
{
return $this->hasMany('App\Feedback', 'user_id', 'id');
}
My model Feedback
public function user()
{
return $this->belongsTo('App\User', 'id', 'user_id');
}

Sure, you can get the email for the users that have provided feedback using the FK. But I don't think you need all of the query you are using. I think you can make this much simpler. Because the user has a relation with the Feedback model (I assume through an Eleve model), you can simply eager load the relationship using the name search if you wish:
// Note I have removed the query() method you had in your original query
$feedbacks = Feedback::with('eleves', function ($query) use($request)
$query->orderBy('eleves.nom','asc')->where('eleves.nom','like','%'.$request->input('search').'%');
})->paginate(5);
To simplify the explanation I've removed the where from the query. To demonstrate I'll just use an if check before the query - you can make this more complex if you wish, but it is a little easier to see this way.
Something like:
if($request->has('search'){ do the query above }
else { $feedbacks = Feedback::with('eleves')->paginate(5); }
Then, because you have pulled the relations, you can then just get the email from any eleves that have been loaded:
$feedback->first()->eleve->email
So if you use the $feedbacks in a loop in your blade file:
#foreach($feedbacks as $feedback)
{{ $feedback->eleve->email }}
#endforeach

OK, I think because of the edit, the question is pretty different than what was first asked, so I'll add another answer rather than try to convey this in the comments.
I think you are asking that when the user tries to see his feedbacks, you are getting the SQL error. If the user is selecting the feedback option, it may only be the single user that is looking for his own feedbacks. I suggest you change your query to the reverse (pull the feedbacks from the user instead of pulling all the feedbacks and then getting user to match):
\Auth::user()->load('feedbacks');
$feedbacksForThisUser = \Auth::user()->feedbacks;
Or if you want to get another user's feedbacks (and the user has permission to see them), just query on that user:
$user = User::with('feedbacks')->find($idOfUserYouWantToSee);
$feedbacks = $user->feedbacks;
Same thing goes for if you want to search for feedbacks from a user with a specific name:
$user = User::with('feedbacks')->where('nom','like','%'.$request->input('search').'%')->first();
$feedbacksForSearchedUser = $user->feedbacks;
The key is to forget about the emails - the relationship will link all feedbacks to the user. You don't need to join, or query on the email. You always have it on the $user object. (i.e. $user->email will always work).
If you want to see ALL feedbacks from ALL users, this isn't really any harder, just query all users and eager load the feedbacks relationship:
$users = User::with("feedbacks")->get();
Then in your blade:
#foreach($users as $user)
// If you want to display only a special set of users to the Auth::User(), then do an if-check here
#if(\Auth::user()->hasPerm("someperm") && $user->isInSomeCategory)
#foreach($user->feedbacks as $feedback)
{{ $feedback->text // or whatever the field you want to show }}
#endforeach
#endif // The if check is totally optional in this - just giving you an example
#endforeach
EDIT: to show a simple index()
public function index(Request $request)
{
if(!\Auth::user()->hasRole('admin')) {
\Auth::user()->load('feedbacks');
$feedback = \Auth::user()->feedbacks;
}
elseif($request->has('search')) {
$user = User::with('feedbacks')->where('nom','like','%'.$request->input('search').'%')->first();
$feedbacks = $user->feedbacks;
}
return view('admin.feedbacks.index', compact('feedbacks'));
}
Note: to make this as simple as possible, I also removed:
->with('display_search', $user->hasRole('admin'));
You can check this on the Blade page because \Auth::user() is already loaded automatically.

Related

Using Model Relationship in a Single Query

Consider the following:
$posts = $this->model->newQuery()
->whereIn('user_id', $user->following) // specifically this line
->orWhere('user_id', $user->id)
->get();
The problem with the above is that there are two queries:
Get following: $user->following
Get posts: Above
This would be much more efficient with the use of a subquery, however, I cannot actually remember the correct way to do it...
I have tried all of the following:
// This was a long-shot...
...->whereIn('user_id', function ($query) use ($user) {
$query->raw($user->following()->toSql());
});
// This works but pretty sure it can be done better with eloquent...
...->whereIn('user_id', function ($query) use ($user) {
$query->select('follow_id')
->from('user_follows')
->where('user_id', $user->id);
});
Is there a way that this can be achieved by using the previously defined relationship $user->following() instead of manually defining the relationship query like the last example above?
Reference
The following relationship is defined as follows:
/**
* Get the users that the user follows.
*/
public function following()
{
return $this->belongsToMany('SomeApp\User\Models\User', 'user_follows', 'user_id', 'follow_id')
->withTimestamps();
}
Use this:
->whereIn('user_id', $user->following()->getQuery()->select('id'))

How to get all posts from the User's subscriptions

In my application, I have setup a User model that can have subscribers and subscriptions through a pivot table called subscriptions.
public function subscribers()
{
return $this->belongsToMany('Forum\User', 'subscriptions', 'subscription_id', 'subscriber_id');
}
public function subscriptions()
{
return $this->belongsToMany('Forum\User', 'subscriptions', 'subscriber_id', 'subscription_id');
}
My question is, what relationship should I use to get a list of paginated Post models (belong to a User) from the User's subscriptions?
You can use the whereHas method to filter based on relationships. Assuming your Post model has a user relationship defined, your code would look something like:
// target user
$user = \App\User::first();
$userId = $user->id;
// get all of the posts that belong to users that have your target user as a subscriber
\App\Post::whereHas('user.subscribers', function ($query) use ($userId) {
return $query->where('id', $userId);
})->paginate(10);
You can read more about querying relationship existence in the documentation.
You can do something like this
\App\Post::with(['subscriptions' => function ($query) {
$query->where('date', 'like', '%date%');
}])->paginate(15);
Or without any conditions
\App\Post::with('subscriptions')->paginate(15);

Displaying posts of users the user follows through Laravel relationships

I would like to display the posts of everyone the current user follows, ordered by date desc.
I have a many to many relationship supplying all the people the user is following.
$users = User::find(Auth::user()->id)->follow()->get();
I have a one to many relationship displaying the posts for any user.
$updates = App\User::find(?????)->updates()->orderBy('created_at', 'desc')->get();
The question mark's shows where the followers ID's need to be placed.
I can put the above query inside the for each loop but that obviously works its way through each follower rather than all posts in date order.
I suspect I may need to set a new relationship and work from the beginning. Can anyone advise.
User Model
public function updates()
{
return $this->hasMany('App\update');
}
/**
* User following relationship
*/
// Get all users we are following
public function follow()
{
return $this->belongsToMany('App\User', 'user_follows', 'user_id', 'follow_id')->withTimestamps()->withPivot('id');;;
}
// This function allows us to get a list of users following us
public function followers()
{
return $this->belongsToMany('App\User', 'user_follows', 'follow_id', 'user_id')->withTimestamps();;
}
}
Update Model
public function user_update()
{
return $this->belongsTo('App\User');
}
Thank you.
Since you want the posts, it is probably going to be easier starting a query on the Post model, and then filter the posts based on their relationships.
Assuming your Post model has an author relationship to the User that created the post, and the User has a follower relationship to all the Users that are following it, you could do:
$userId = Auth::user()->id;
$posts = \App\Post::whereHas('author.follower', function ($q) use ($userId) {
return $q->where('id', $userId);
})
->latest() // built in helper method for orderBy('created_at', 'desc')
->get();
Now, $posts will be a collection of your Post models that were authored by a user that is being followed by your authenticated user.

Laravel 5.1 Where Condition In Many To Many relationships

Hello I'm very new in Laravel and, I'm having the following models :
organizations
-----------------
id
name
public function users()
{
return $this->belongsToMany( 'App\User' );
}
users
-----------------
id
name
organization_user
------------------
user_id
organization_id
The there is a many to many relationship between organization and user. Now I want to find the organization where the user belongs to. How can I add a where condition for the user in the relationship.
For example I want to find all the organization of the logged in user. I'm trying the following :
$organisations = Organisation::where('user_id' , '=' , $user->id)->paginate(10);
But its not working because user_id is in my Pivot Table. Please help and Thanks in advance.
I think you need to use wherePivot() function in your code like
$organisations = Organisation::with(array('user'=> function($query) use ($user){
$query->wherePivot('user_id' , '=' , $user->id);
}) )->paginate(10);
May be this can help
I think below code may help you
$organisations = Illuminate\Support\Facades\DB::table('organizations')
->join('organization_user', 'organizations.id', '=', 'organization_user.organization_id')
->join('users', 'users.id', '=', 'organization_user.user_id')
->where('users.id', '=', $user->id)
->paginate(10);
I think you need to add this to your User Model
public function organizations()
{
return $this->belongsToMany('App\Organization');
}
and then will be something simple like this
$organizations = Auth()->user()->organizations;
First of all add your relations in your models:
User.php
public function organizations()
{
return $this->hasMany(organization_user::class);
}
Or
public function organizations()
{
return $this->hasManyThrough(organizations::class,organization_user::class);
}
I recommend the second one. For more information follow this:
Laravel hasManyThrough
Please note that use same idea for organization model to create the relation

Authorization not working for Users Search

I'm using Laravel 5.1.26, including authorizations with policies. I have a basic ACL model where a user has a Role, of course an integer Role field.
My Roles are:
0 - Administrator (can perform any operation over users);
1- Operator (can't perform any operation over users);
2- Viewer (can't perform any operation over users).
I provide the option to perform a User's search. Only Administrators can perform this because my roles definition. So, I have a method in the UserController to display my results:
public function postSearch(Request $request)
{
$this->authorize('search', User::class);
$query = User::select('name', 'email')
->where('name', 'LIKE', "%$request->name%")
->where('email', 'LIKE', "%$request->email%")
->where('role', '=', "%$request->role%");
return $this->displayResult($query, $request);
}
As you see, the authorize method perform the validation, and the rest of code creates the result. Simple.
Problem is because if I search (using an Administrator user for all cases) for an Operator user, then all my operations are disabled: create, delete, edit, etc. Same behaviour if I search for a Viewer user.
But if I search for an Administrator user, then all my operations are enabled!
So, I guess that the authorize method is receiving the user found! Not the user authenticated. How can I solve this? I'm passing the User::class because if I don't pass anything, then my Policies don't work (therefore, I followed the last comment here https://laracasts.com/discuss/channels/laravel/laravel-511s-new-authorization-doesnt-read-policies/?page=2).
Thanks.
After perfom another Search option on my application, I found that Eloquent is a little bit different than usual and I created a Search method on my model. Which basically perform this:
public function scopeSearch($query, $field, $value)
{
if(is_numeric($value))
return $query->where($field, '=', "$value");
else
return $query;
}
So, I changed my original code to this and my Role is an integer:
public function postSearch(Request $request)
{
$this->authorize('search', User::class);
$query = User::select('name', 'email')
->where('name', 'LIKE', "%$request->name%")
->where('email', 'LIKE', "%$request->email%")
->search('role', "$request->role");
return $this->displayResult($query, $request);
}
Now works fine!

Categories