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.
Related
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);
});
}
I've 2 tables
Users table
id
name
...
Chats table
id
from_id // fk - id on users, the user sent the message
to_id // fk - id on users, intended user
message_body
Now, I'm trying to set up One to Many relation where user has many chat messages but a chat message has two user. from and to user
How can I define this relationship?. I have to user eager loading.
I tried to use Compoships but it didn't work.
My code
User Model
public function chats() {
return $this->hasMany(Chat::class, ['from_id', 'to_id'], 'id');
}
Chat Model
public function user() {
return $this->belongsTo(User::class, ['from_id', 'to_id'], 'id');
}
public function chats() {
return $this->hasMany(Chat::class, 'from_id', 'id') + $this->hasMany(Chat::class,'to_id','id');
}
public function userFrom() {
return $this->belongsTo(User::class, 'from_id', 'id');
}
public function userTo() {
return $this->belongsTo(User::class, 'to_id', 'id');
}
Why don't you do something like that?
On your User model, set up two relationships like this:
public function chatsFrom() {
return $this->hasMany('App\Chat', 'from_id');
}
public function chatsTo() {
return $this->hasMany('App\Chat', 'to_id');
}
Then, on your Chat model, also set up two relationships, one to from and another to to, both referencing a User model. Like this:
public function fromUser() {
return $this->belongsTo('App\User', 'from_id');
}
public function toUser() {
return $this->belongsTo('App\User', 'to_id');
}
This way, you can access the relationships using something like this:
$user->chatsFrom();
$user->chatsTo();
$chat->fromUser();
$chat->toUser();
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);
}
I have 3 models that are related to each other.
Group
GroupMember
GroupPost
GroupPostComment
Now, I have separeted the database tables aswell.
groups
group_members
group_posts
group_post_comments
For each group a member is a member of, I insert a new row in group_members.
The foreign key here is "group_id", wich relates to the id field in groups.
In group_posts there is a new row for every post posted. This container a group_id field aswell.
What I'm struggling with is the GroupMember model.
How can I get an collection of all the posts from this GroupMember, that the GroupMember posted in that one group its related to?
Here is my models setup.
Group model
public function category() {
return $this -> belongsTo('App\GroupCategory', 'category_id');
}
public function owner() {
return $this -> hasOne('App\GroupMember', 'group_id') -> where('owner', true);
}
public function mods() {
return $this -> hasMany('App\GroupMember', 'group_id') -> where('mod', true);
}
public function admins() {
return $this -> hasMany('App\GroupMember', 'group_id') -> where('admin', true);
}
public function members() {
return $this -> hasMany('App\GroupMember', 'group_id');
}
public function posts() {
return $this -> hasMany('App\GroupPost', 'group_id');
}
public function comments() {
return $this -> hasMany('App\GroupPostComment', 'group_id');
}
GroupMember model
public function group() {
return $this -> belongsTo('App\Group');
}
public function posts() {
return $this -> hasMany('App\GroupPost', 'group_id', 'group_id');
}
public function comments() {
return $this -> hasMany('App\GroupPostComment', 'group_id', 'group_id');
}
public function user() {
return $this -> belongsTo('App\User');
}
GroupPost model
public function user() {
return $this -> belongsTo('App\User');
}
public function comments() {
return $this -> hasMany('App\GroupPostComment', 'post_id');
}
public function group() {
return $this -> belongsTo('App\Group');
}
The problem is the GroupMember model and the posts() / comments() method.
There is an error in my relation, but I can't see what I am doing wrong.
Does anyone see what I'm doing wrong?
This case is a little bit confusing to resolve, although easy to. I guess that's why you haven't received any help yet because some people struggle to understand.
1. Clear some confusions
In your title you mentioned
Laravel relationship between 3 models (group,member,post)
Yet, there is no Member model to be seen. And I think most of your difficulties come from there. In my tryout, I will assume you have a User model and the table that goes with.
Question: Can a user be member of many groups ? If the answer is yest, then you have a many to many relationship between Group and User (members). Thus, update your Group model like this:
public function members() {
return $this->belongsToMany('App\User', 'group_members', 'group_id', 'member_id');
}
And in the User model, you define the opposite
public function groups() {
return $this->belongsToMany('App\Group', 'group_members', 'member_id', 'group_id');
}
Right, you noticed now group_members table has a composite key made of group_id and member_id respectively representing groups and users table.
2. How to get the all the posts belonging to a member in a specific group
First thing first, a GroupPost (post) belongs to two entities: a Group and User (member). In your GroupPost model you already have a relationship to User. So all good. To answer your questions, there are many possibilities.
//Direct eloquent when user id and group id are known
$posts = GroupPost::where('user_id', 1)->where('group_id', 1)->get();
//Directly from the user
$member = User::find(1);
$posts = $member->groupPosts()->where('group_id', 1)->get();
Don't forget to define groupPosts() relationship in User model
public function groupPosts() {
return $this->hasMany('App\GroupPost');
}
I am trying to do a single query to get back an order and the card to charge, but getting an error.
Card model:
class Card extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function user()
{
return $this->belongsTo('User');
}
public function orders()
{
return $this->hasMany('Order');
}
}
Order model:
class Order extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function user()
{
return $this->belongsTo('User');
}
public function card()
{
return $this->hasOne('Card');
}
public function address()
{
return $this->belongsTo('Address');
}
public function orderItems()
{
return $this->hasMany('OrderItem');
}
}
What I am trying to get back:
$order = Order::with('card')->find($id);
This obviously doesn't work and I have tried several combos. I think the issue is with my models/relationships.
Any idea how I can get back the order with the card/token details?
DB info: Each order can have only one card_id and each card can be in many orders. There is no order_id in the card.
Orders table basically:
id | card_id
Cards table:
id | token
Trying to get the token col to return with the Order.
In your Order model, you need to change this:
public function card()
{
return $this->hasOne('Card');
}
to this:
public function card()
{
return $this->belongsTo('Card');
}
The reason is that you are defining the inverse of the hasMany relationship. With the belongsTo relationship, Eloquent will look for a card_id column on the orders table.