Using eloquent to query multiple tables - laravel

I am using Laravel 5.6. I am trying to query information from the grading_info table but I also want to return the students name and other info from the student_info table. I only want to return records in the grading_info table that are related to the currently logged in teacher. Currently its returning information for all teachers. I know I can add a where clause but I am trying to learn eloquent and was wondering if there was any way to accomplish this?
Teachers and students can have many enteries in the grading_info table and any teacher can grade any student.
I would like to return something like this
{
gradeID,
gradeDate,
gradeInfo
.....
student: {
studentName,
studentPhoneNumber,
studentEmail
......
}
}
users table (only stores teachers, not student)
id
teacher_info
teacherID (linked to id from users table)
student_info
id (auto increment. not relation to the users table)
grading_info
studentID (linked to id from student_info)
teacherID (linked to id from users)
User model
public function grades(){
return $this->hasMany(GradingInfo::class, 'studentID');
}
GradingInfo model
public function teacher(){
return $this->belongsTo(User::class, 'id', 'teacherID');
}
public function student() {
return $this->belongsTo(StudentInfo::class, 'studentID', 'id');
}
StudentInfo model
public function grades() {
return $this->hasMany(SessionInfo::class, 'studentID', 'id');
}
TeacherInfo model
// Nothing in here.
TeacherController
public function getGrades(Request $request)
{
$user = Auth::user(); // This is the teacher
$grades = $user->with('sessions.student')->orderBy('created_at', 'DESC')->get();
return response()->json(['sessions' => $sessions], 200);
}

You have Many to Many relationship between user(teacher) and student(student_info) tables
User Model
public function gradeStudents(){
return $this->belongsToMany(StudentInfo::class, 'grading_info', 'teacherID', 'studentID');
}
public function info(){ //get teacher info
return $this->hasOne(TeacherInfo::class, 'teacherID');
}
StudentInfo model
public function gradeTeachers(){
return $this->belongsToMany(User::class, 'grading_info', 'studentID', 'teacherID');
}
Now Fetch the data (TeacherController)
public function getGrades(Request $request)
{
$user = Auth::user(); // This is the teacher
$students = $user->gradeStudents; // it will return all graded students by logged in teacher
return response()->json(['students' => $students], 200);
}
Here grading_info is a pivot table for Many-To-Many relationship
for details check this https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
Fetch Extra info from pivot table
If you want to add extra info in pivot table (grading_info) then add column (info) in this table and then need to change relationship like this
public function gradeStudents(){
return $this->belongsToMany(StudentInfo::class, 'grading_info', 'teacherID', 'studentID')
->withPivot('info')
->as('grade')
->withTimestamps();
}
Now if you fetch data
$user = Auth::user(); // This is the teacher
$students = $user->gradeStudents;
foreach($students as $student){
print_r($student);
print_r($student->grade->info);
print_r($student->grade->created_at);
}

Related

Laravel query builder with the User and Auth

How to List all rows from a table (agendas) in my DB where records are saved by the connected user.I'm using default Auth from Laravel.
public function index ($id = null)
{
$agendas = Agenda::where('id', Auth::user()->id)->get();
$users = User::all();
return view('admin.agendas.index', compact('agendas','users','id'));
}
My controller here.
Need help
Assuming
agendas table (containing records for Agenda model) has a column user_id which references the id column on users table
User hasMany Agenda
Agenda belongTo User
class User extends Model
{
public function agendas()
{
return $this->hasMany(Agenda::class);
}
//... rest of class code
}
class Agenda extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
//... rest of class code
}
public function index($id = null)
{
$user = User::with('agendas')->findOrFail(auth()->id());
return view('admin.agendas.index', [
'user' => $user,
'agendas' => $user->agendas,
'id' => $id
]);
}
Your User model should have a relationship:
public function agendas()
{
return $this->hasMany(Agenda::class);
}
In your controller, you could then simplify the use as such:
public function index (Request $request, $id = null)
{
$agendas = $request->user()->agendas;
$users = User::all();
return view('admin.agendas.index', compact('agendas','users','id'));
}
if you wanna get data related to another data , you have to join those tables together by a field. in this case i guess you have a column in Agenda table named 'user_id'.
you have two way :
join tables in your Model.
search in Agenda table in your controller
if you want to use joining your tables from model :
// in App\User.php
...
class User ...{
...
public function Agenda(){
return $this->hasMany(Agenda::class);
}
...
}
...
then you can access to all of "Agenda" from everywhere like this :
Auth()->user()->agenda
if you want to search in table from your controller you can do :
Agenda::where('id', Auth::user()->id)
you can read more about eloquent-relationships in : https://laravel.com/docs/8.x/eloquent-relationships

How to get users from a group, with a union between two relationships in laravel?

I want to recieve all users from a group.
The problem is in this group their are student users (with a pivot table) and normal users.
So i have to merge them together, but i still want to maintain all possibilities from eloquent.
I came to this:
dd($this->belongsToMany(User::class)->union($this->hasManyThrough(User::class,Student::class,'class_id','id','id','user_id'))->get());
But as result i get:
My database relationships
Users
- id
Group
- id
Students
- id
- user_id (fk to users)
- class_id (fk to groups)
User_Group
- user_id (fk to users)
- group_id (fk to groups)
User-model:
public function students()
{
return $this->hasMany(Student::class);
}
public function groups()
{
return $this->belongsToMany(Group::class);
}
Student-model
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function class()
{
return $this->belongsTo(Group::class, 'class_id');
}
Group-model
public function students()
{
return $this->hasMany(Student::class, 'class_id');
}
public function users()
{
return $this->belongsToMany(User::class);
}
public function members()
{
//this causes the problem!!
return $this->belongsToMany(User::class)->union($this->hasManyThrough(User::class,Student::class,'class_id','id','id','user_id'));
}
in User model relationship
public function group(){
return $this->belongsToMany(Group::class);
}
in Group model relationship
public function user(){
return $this->belongsToMany(User::class, 'user_group');
}
in Students model relationship
public function user(){
return $this->belongsToMany(User::class, 'user_id', 'id');
}
public function group(){
return $this->belongsToMany(Group::class, 'class_id', 'id');
}
you can call now
$users = User::whereHas('groups',function ($query){
$query->where('group_id',1);
})->get();
Sometimes you have two relations from one model to another, due pivot tables. In my example you could go from users to groups with the relation user_groups and the relation students. To get all users that belong to a certain group i need to call both relations. To solve this issue, i made use of Abdulmajeed's example to solve it. You can see the code below. Thanks for helping me out.
public function members()
{
return User::whereHas('groups', function($q)
{
$q->where('id',$this->id);
})->orWhereHas('students', function($q)
{
$q->where('class_id',$this->id);
});
}

Laravel relations pivot table name trouble

in my app I have 2 conversations types: normal private conversations between users and conversations for people which are interested of user product.
In my User model I declared relations like:
public function conversations()
{
return $this->belongsToMany('App\Conversation', 'conversation_user');
}
public function conversationsProduct()
{
return $this->belongsToMany('App\ConversationProduct', 'conversation_product_user', 'user_id', 'product_id');
}
Where 'conversation_user' and 'conversation_product_user' are pivot tables between 'users'-'conversations' and 'users'-'conversations_product' tables.
My conversation_user pivot table has conversation_id and user_id table properties, but conversation_product_user pivot table has additional property product_id.
In my Conversation Model I have:
public function users()
{
return $this->belongsToMany('App\User');
}
public function messages()
{
return $this->hasMany('App\Message');
}
In ConversationProduct Model I wrote:
protected $table = 'conversations_product';
public function users()
{
return $this->belongsToMany('App\User', 'conversation_product_user');
}
public function messages()
{
return $this->hasMany('App\MessageProduct');
}
In my ConversationProductController I have method to find user conversations:
public function showUserConversationsProduct(Request $request){
$user_id = $request->user_id;
//var_dump($user_id);
$userData = User::where('id', $user_id)->with('conversationsProduct')->first();
}
And there is my problem: In controller ->with('conversationsProduct') don't take relation for conversation_product_user, but for conversation_user pivot table. I can't handle it why its happen if I add second parameter as 'conversation_product_user' in my relation:
public function conversationsProduct()
{
return $this->belongsToMany('App\ConversationProduct', 'conversation_product_user', 'user_id', 'product_id');
}
I need protected $table = 'conversations_product'; to point my ConversationsProductController#store where to save conversation, but I think that can be problem with recognise proper relation.
I really appreciate any help. I attach photo of my db relations.

Retrieve related models using hasManyThrough on a pivot table - Laravel 5.7

I'm trying to retrieve related models of the same type on from a pivot table.
I have 2 models, App\Models\User and App\Models\Group and a pivot model App\Pivots\GroupUser
My tables are have the following structure
users
id
groups
id
group_user
id
user_id
group_id
I have currently defined relationships as
In app/Models/User.php
public function groups()
{
return $this->belongsToMany(Group::class)->using(GroupUser::class);
}
In app/Models/Group.php
public function users()
{
return $this->belongsToMany(User::class)->using(GroupUser::class);
}
In app/Pivots/GroupUser.php
public function user()
{
return $this->belongsTo(User::class);
}
public function group()
{
return $this->belongsTo(Group::class);
}
I'm trying to define a relationship in my User class to access all other users that are related by being in the same group. Calling it friends. So far I've tried this:
app/Models/User.php
public function friends()
{
return $this->hasManyThrough(
User::class,
GroupUser::class,
'user_id',
'id'
);
}
But it just ends up returning a collection with only the user I called the relationship from. (same as running collect($this);
I have a solution that does work but is not ideal.
app/Models/User.php
public function friends()
{
$friends = collect();
foreach($this->groups as $group) {
foreach($group->users as $user) {
if($friends->where('id', $user->id)->count() === 0) {
$friends->push($user);
}
}
}
return $friends;
}
Is there a way I can accomplish this using hasManyThrough or some other Eloquent function?
Thanks.
You can't do that using hasManyThrough because there is no foreign key on the users table to relate it to the id of the group_user table. You could try going from the user to their groups to their friends using the existing belongsToMany relations:
app/Models/User.php:
// create a custom attribute accessor
public function getFriendsAttribute()
{
$friends = $this->groups() // query to groups
->with(['users' => function($query) { // eager-load users from groups
$query->where('users.id', '!=', $this->id); // filter out current user, specify users.id to prevent ambiguity
}])->get()
->pluck('users')->flatten(); // massage the collection to get just the users
return $friends;
}
Then when you call $user->friends you will get the collection of users who are in the same groups as the current user.

Laravel eloquent -getting user info based on id, for each comment in a query

I have an API endpoint where I am suppose to send all the relevant data for articles. I have tables users, comments, articles. Users table has fields id, first_name, last_name, table comments has fields id, article_id, user_id. Relationships are defined like this:
Article model:
public function comments()
{
return $this->hasMany('App\Comment');
}
User model:
public function comments()
{
return $this->hasMany('App\Comment');
}
Comment model:
public function user()
{
return $this->belongsTo('App\User');
}
Now in my function I am getting articles and then creating an array with info about comments. I should get user first_name, and last_name for each comment, but I am not sure how to do this and if it is possible to do it when getting a collection from eloquent query?
This is the function:
$result = Article::where('publish', 1)->orderBy('created_at', 'desc')->paginate(15);
foreach($result as $article){
$articles[$article->id] = $article;
$articles[$article->id]['comments'] = $article->comments()->get();
}
return $articles;
Now that you have defined the relationships use it like :
$article = Article::with('comments.user')->where('publish', '1')->orderBy('created_at', 'desc')->paginate(15);
now in your view do like this :
#foreach($article->comments as $comment)
{{$comment->body}} by {{$comment->user->name}}
#endforeach

Resources