Laravel multi relationship - php

I am working on chat application in laravel/vue and in this app I have users where each user have several rooms each room has at least 2 user in it and several messages I am trying to make relation or query to get all the rooms for each users and the messages in them
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->enum('status',['active','busy','Do Not Disturb']);
$table->timestamp('email_verified_at')->nullable();
$table->string('image')->default('user0.jpg');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('rooms', function (Blueprint $table) {
$table->id();
$table->string('room_unique');
$table->foreignId('user_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->enum('type',['text','image','link']);
$table->string('content');
$table->foreignId('user_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
$table->foreignId('room_id')->constrained()->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});

What you have is good. I would just take out the foriegn key user_id from rooms and access user's room through their messages. Hence, messages will be like a pivot table making the relationship between users and rooms many to many.
Hence to access the rooms of a user I would
$rooms = User::find(1)->rooms()->get();
To access users in a room
$users = Room::find(1)->users()->get();
To display messages of a user per room would be like accessing pivot table. Hence
$user = User::find(1);
foreach ($user->rooms as $rooms) {
echo $rooms->pivot->content;
}
So, this is many to many relationship and message is the pivot table. I will stick with the documentation for more details.

The best solution i have found is to make complex relation like this
//relations
public function message()
{
return $this->hasMany(messages::class)->take(1);
}
public function friends()
{
return $this->belongsToMany(User::class, 'friends', 'user_id', 'friend_id');
}
public function rooms()
{
return $this->belongsToMany(Room::class,'user_room','user_id','room_id');
}
public static function getInit()
{
//get room of auth user
$rooms = DB::table('user_room')->where('user_id',Auth::id())->select('room_id')->get()->toArray();
//flatten the array
$roomArray = array_column(json_decode(json_encode($rooms), true),'room_id');
//get users friends and rooms belong to auth user with the last message
$user = User::with(array('friends.rooms' => function($query) use ($roomArray){
$query->whereIn('rooms.id',$roomArray);
},'friends.rooms.messages' => function($query) {
$query->orderBy('created_at','Desc');
}))->whereId(Auth::id())->get()->toArray();
return $user;
}
in getinit I just use this relation after each other like (friends.rooms)
laravel will use friends relation then each result will use rooms relation on it in my case i just need to pick rooms that user and friend have so i limited the relation by using where in rooms belong to the auth user like if we say the auth user has rooms 2,3,4 and his friend has 3,1,5 so the room relation will only return the union of auth user rooms and friend rooms in our case it's 3 then i return messages in each room but for design purpose i just need the last message for each room so i limit my relation message to take 1 and in getinit order them by created date desc

Related

Laravel save data from one form to different database tables

I want to create a student with some courses.
This is the Laravel view
I created two different tables: a students table
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('student_name');
$table->string('first_name');
$table->string('last_name');
$table->string('email');
});
}
and a courses table.
public function up()
{
Schema::create('student_courses', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('student_id');
$table->string('course_name');
$table->timestamps();
});
}
The students table creates the information of the student and saves it in the student table.
I want to save the courses into the courses table, with the student id. They should have a One to Many relationship. How can I save the different courses into the courses table with the id of the specific student?
You can't store course name in student courses table. You need to create separate tables for courses. After that you can use foreign key for store both the data of student and courses into the student_courses table as per below.
public function up()
{
Schema::create('student_courses', function (Blueprint $table) {
$table->id();
$table->integer('student_id')->unsigned()->nullable();
$table->foreign('student_id')->references('id')->on('students')->onDelete('cascade');
$table->integer('course_id')->unsigned()->nullable();
$table->foreign('course_id')->references('id')->on('courses')->onDelete('cascade');
$table->timestamps();
});
}
Hope this will helps you.
First create Relationship:
In User Model Create:
public function courses(){
return $this->hasMany(Course::class);
}
In Course Model Create:
public function students(){
return $this->belongsTo(Studnet::class);
}
Now in your save function:
$course = new Course($request->all());
$user->courses()->save($course);

Laravel many to many relationship returning empty array

I'm trying to get the results using laravel many to many relationship but the query is generating wrong therefore it return empty array.
$user->survey()->get() is returning empty array.
$user->survey()->toSql() is returning wrong query:
SELECT
*
FROM
`survey`
INNER JOIN `survey_user` ON `survey`.`id` = `survey_user`.`survey_id`
WHERE
`survey_user`.`user_id` IS NULL
Here, in the end, the user_id should not be null.
Migration for the survey pivot table:
Schema::create('survey_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('survey_id')->unsigned();
$table->string('status', 50)->nullable();
$table->timestamps();
});
Schema::table('survey_user', function (Blueprint $table) {
$table->foreign('user_id')->on('users')->references('id');
$table->foreign('survey_id')->references('id')->on('survey')
->onDelete('cascade')
->onUpdate('cascade');
});
}
here are the two relation:
public function survey()
{
return $this->belongsToMany(Survey::class, 'survey_user')
->withPivot('status')
->withTimestamps();
}
public function user()
{
return $this->belongsToMany(User::class, 'survey_user')
->withPivot('status')
->withTimestamps();
}
I'm just trying to get all the users who have survey assigned in their pivot.
$user = new User();
var_dump($user->survey()->get());
I'm just trying to get all the users who have survey assigned in their pivot.
To get all Users where the survey relationship exists, your code would look like this:
$users = User::has('survey')->get();
If you need the survey relationship loaded on the models when you use them, then add with() to eager load the relationship:
$users = User::has('survey')
->with('survey')
->get();
Here, in the end, the user_id should not be null.
The reason it was searching with a null user id is because you are searching with a new User instance that hasn't been saved to the database. This is your code with the problem:
$user = new User();
var_dump($user->survey()->get());
Since $user is a new object that hasn't been saved to the database it doesn't have an id. When you call $user->survey() it builds a query to search survey_user where the user id is null.

Laravel - A show can have multiple providers

So I am trying to figure a solution to this but not sure exactly how to do this. I have a table that stores all the shows that happen. In a given show I can have multiple providers attend that show. A provider could also attend many shows as well. So how do I store this in the DB and do the eloquent relationship?
Show Schema
Schema::create('shows', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('number')->unsigned();
$table->dateTime('airDate');
$table->string('podcastUrl')->nullable();
$table->timestamps();
});
Provider Schema
Schema::create('providers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('shortName')->nullable();
$table->string('image')->nullable();
$table->string('social')->nullable();
$table->timestamps();
});
Would I store the provider_id in the shows schema?
Update 1
So I created a new migration for a pivot table
Schema::create('provider_show', function (Blueprint $table) {
$table->integer('provider_id')->unsigned()->index();
$table->foreign('provider_id')->references('id')->on('providers')->onDelete('cascade');
$table->integer('show_id')->unsigned()->index();
$table->foreign('show_id')->references('id')->on('shows')->onDelete('cascade');
$table->primary(['provider_id', 'show_id']);
});
Then in the show model I created the following
public function providers()
{
return $this->belongsToMany(Provider::class);
}
Now when I am saving a new show I added a multiselect to select the providers I want
$show = new Show;
$show->name = $request->name;
$show->number = $request->number;
$show->airDate = $request->airDate;
$show->podcastUrl = $request->podcastUrl;
$show->providers()->attach($request->providerList);
$show->save();
Session::flash('message', "Created Successfully!");
return back();
Then when I save I get the following error
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: provider_show.show_id (SQL: insert into "provider_show" ("provider_id", "show_id") select 1 as "provider_id", as "show_id" union all select 2 as "provider_id", as "show_id")
Create a provider_show migration which will act as your pivot table.
This table would contain both provider_id and show_id which will provide the many-to-many relationship between those entities.
Then on your Provider model you can provide a shows() method which returns a BelongsToMany relationship.
// In your Provider model
public function shows()
{
return $this->belongsToMany('App\Show');
}
Note that Laravel by default looks for a pivot table name based alphabetically on the two relationships.
You can also add the inverse on your Show model by providing a providers() method that also returns a BelongsToMany relationship.

Laravel: query many-to-many relationship

I have a User model which belongsToMany() Conferences. Conferences hasMany Users, also a m:m relationship.
I am working on a link() method in my ConferencesController, but I'm not sure how to go about.
I collect the given Conference by id, and the Auth::check-ed User. How do I add the conference and user into the pivot table?
create a pivot table
//conference_user
Schema::create('conference_user', function(Blueprint $table) {
$table->increments('id');
$table->integer('conference_id')->unsigned()->index();
$table->foreign('conference_id')->references('id')->on('conferences');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
now in User model, add this method
public function conferences()
{
return $this->belongsToMany('Conference','conference_user');
}
and in Conference model, add this method
public function users()
{
return $this->belongsToMany('User','conference_user');
}
now in your controller, you can use something like this
$conferences=$user->conferences;
or
$users=$conference->users;

What type of relationship these two tables will have in laravel?

i have four tables in database:
users (for storing user details)
conversations (for storing conversations id).
conversationsmember (for storing conversations member)
conversationsreply (for storing conversations reply)
A user will have many conversations and each conversation will have its members and replies.
here are the details:
Users migration:
$table->increments('id');
$table->string('name', 32);
$table->string('username', 32);
$table->string('email', 320);
$table->string('password', 64);
$table->timestamps();
Conversations migration:
$table->increments('id');
$table->timestamps();
conversationsmembers migration:
$table->increments('id');
$table->integer('conversation_id');
$table->integer('user_id');
$table->timestamps();
conversationsreply migrations
$table->increments('id');
$table->integer('conversation_id');
$table->integer('user_id');
$table->timestamps();
Now in User model, i need to define relationship between users table and conversations table. As they are not directly connected, i used hasManyThrough relation.
..app/models/User.php
...
public function conversations()
{
return $this->hasManyThrough('Conversation', 'ConversationsMember', 'conversation_id', 'id');
}
...
When i 'm trying to use it, it's showing a blank array.
I would try a belongsToMany relationship, where conversationsmembers is your pivot table.
public function conversations()
{
return $this->belongsToMany('Conversation', 'conversationsmembers');
}
You may also want to define the inverse of the relationship in your Conversation model:
public function users()
{
return $this->belongsToMany('User', 'conversationsmembers');
}
I'm a bit confuse about your migration so I'm not sure that's what you want.

Categories