How to call a relationship who contains another relationship - Laravel - php

I'm trying to make a site where users have projects, and I'm trying to make a kind of "activity wall" to improve the communication of each project, so this "activity wall" messages belong to the project and the Messages inserted in it belong to the user too. So, I created the migration below:
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->string('content'); //the message
$table->string('file'); //if has a file
$table->integer('user_id')->constrained(); //to make the relationship with the Users table
$table->integer('projeto_id')->constrained();//to make the relationship with the Projetos (Projectc) table
$table->timestamps();
});
And in Projeto Model, I create the relation.
Projeto.php
public function message()
{
return $this->hasMany(Message::class);
}
The same to
User.php
public function messages()
{
return $this->hasMany(Message::class);
}
And this to
Message.php
public function projetos()
{
return $this->belongsTo(Projeto::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
But the problem is: When I try to get the Messages table with the Project relationship.
public function index($id)
{
$projeto = Projeto::findOrFail($id);
$messages = $projeto->message;
}
I can't get the User relationship to get the owner username of the message to return to my view. What is the better way to do this?

you should use with, to prevent n query:
public function index($id)
{
$projeto = Projeto::with('message', 'message.user') // this will get the relation `message`, and `user` from the message
->findOrFail($id);
$messages = $projeto->message;
}

Related

Best Practice to update hasMany Relationships with laravel

Hello Actually am trying to create an app in which every project has some users i.e ProjectMembers.
here is project model with TeamMembers function.
class Project extends Model
{
use HasFactory;
function TeamMembers(){
return $this->hasMany(ProjectMember::class);
}
}
project members table schema.
Schema::create('projects_members', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('project_id')->nullable();
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('project_id')->references('id')->on('projects');
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
Now for updating project members i have to first delete relationships from Project members and then saving new one. because i have added multiselect dropdown. $request->team_members have type array.
public function update(Request $request, $id)
{
// return $request;
$project = Project::findorfail($id);
$project->name = $request->project_name;
$project->details = $request->details;
$project->start_date = $request->start_date;
$project->end_date = $request->end_date;
$members = $request->team_members;
ProjectMember::where('project_id', $id)->delete();
$this->update_project_memebers($members, $project);
return redirect('/projects');
}
public function update_project_memebers($members, $project){
foreach ($members as $member_id) {
$project_member = new ProjectMember();
$project_member->project_id = $project->id;
$project_member->user_id = $member_id;
$project_member->save();
}
}
here am deleting cuz if someone created project with two members and when the he/she want to update then he/she can remove one member from multiselect then i have to delete relationship cuz he/she selected only one user.
I don't think it's a good practice, so can i achieve this same func. with another way?
thankyou.
First of all please make a proper naming convention of pivot tabel according to laravel and same for the model name too.
As of now the solution is
define relation as
Project
public function teamMembers()
{
return $this->belongsToMany(ProjectMember::class, 'projects_members', 'project_id', 'member_id');
}
ProjectMember
public function projects()
{
return $this->belongsToMany(Project::class, 'projects_members', 'member_id', 'project_id');
}
So now instead of deleting use sync() method. AS
$project->teamMembers()->sync($members);
Important docs,
https://laravel.com/docs/8.x/eloquent-relationships#syncing-associations

Laravel: Query Many to Many Pivot table

I have an app where Users can have multiple Books. I have set up the relation ship and the intermediary table. But the query is not working.
Book Model
public function user(){
return $this->belongsToMany('App\Book', 'book_user');
}
User Model
public function book(){
return $this->belongsToMany('App\User', 'book_user');
}
Create user_book table migration:
public function up()
{
Schema::create('book_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('book_id')->unsigned();
$table->foreign('book_id')->references('id')->on('books');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
}
Books controller I add the book_id and user _id to the table
public function readlist(Book $book)
{
DB::table('book_user')->insert(
['user_id' => auth()->id(),
'book_id' => request('book_id')]
);
}
In my home controller I try to access the books related to a user but my results return Null;
public function index()
{
$user = Auth::user();
$userbooks =$user->books;
dd($userbooks);
return view('/home');
}
First rename you book() method to books() in your User model :)
Then you can try to do this:
public function readlist(Request $request)
{
Auth::user()
->books()
->attach($request->get('book_id'));
}
User have multiple Books,
Book have multiple Users,
The relationship is many to many,
It's better to define the User model:
public function users(){
return $this->belongsToMany('App\Book', 'book_user');
}
And in your Book model
public function books(){
return $this->belongsToMany('App\User', 'book_user');
}
The Doc Link: https://laravel.com/docs/5.7/eloquent-relationships#many-to-many

Laravel post owner relationship

i have category_content, contents and users tables which each contents belong to many category_content and category_contentbelong to many contents and each contents belongs to one user and one user has many post on contents table
class Contents extends Model
{
...
public function categories()
{
return $this->belongsToMany(ContentCategories::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
class ContentCategories extends Model
{
...
public function contents()
{
return $this->belongsToMany(Contents::class);
}
}
class User extends Authenticatable
{
...
public function content()
{
return $this->hasMany(Contents::class);
}
}
by this below code i can find categories content that category id is 7
$nodejsContents = ContentCategories::find('7')->contents;
now, problem is here, how can i get post owner in this query which content is belongs to which user
i tested this code but i get error:
$nodejsContents = ContentCategories::find('7')->contents->user;
Error:
"Undefined property: Illuminate\Database\Eloquent\Builder::$contents"
contents_categories migration:
public function up()
{
Schema::create('contents_categories', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('lang',2)->default('fa');
$table->integer('parent')->default(0);
$table->timestamps();
});
}
user is within contents, so access with closure,
$nodejsContents = ContentCategories::has('contents')->with(['contents' => function($query){
$query->with('user')->get();
}])->find('7');
ContentCategories::find('7')->contents
belongsToMany Contents would return a collection. So you could either loop through the collection to get the related user of Contents
or
ContentCategories::find(7)->contents->with('user');

Laravel user can follow Comment, Category, Post etc

I wanted to implement a follow system where a User can follow Comment, Category, Post and more. I have tried using Laravel Polymorphic relations for this but could not wrap my head around it. If someone can guide me it will be great.
Here is what I have tried.
User Model
public function categories()
{
return $this->morphedByMany(Category::class, 'followable', 'follows')->withTimestamps();
}
Category Model
public function followers()
{
return $this->morphMany(Follow::class, 'followable');
}
Follow Model
public function followable()
{
return $this->morphTo();
}
public function user()
{
return $this->belongsTo(User::class);
}
Follow migration
Schema::create('follows', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->morphs('followable');
$table->timestamps();
});
How can I get the all the categories, comments followed by a user. Also how I can get the Followers of a Cateogry or Commnets etc.
Please help.
You dont't need Follow model.
All you need is pivot table like so
followable
user_id - integer
followable_id - integer
followable_type - string
add folowers method to all your classes which you need to follow
For example
Category Model
public function followers()
{
return $this->morphToMany(User::class, 'followable');
}
Then in User Model
public function followers()
{
return $this->morphToMany(User::class, 'followable');
}
public function followedCategories()
{
return $this->morphedByMany(Category::class, 'followable')->withTimestamps();
}
public function followedComments()
{
return $this->morphedByMany(Comment::class, 'followable')->withTimestamps();
}
public function followedPosts()
{
return $this->morphedByMany(Post::class, 'followable')->withTimestamps();
}
// and etc
public function followedStuff()
{
return $this->followedCategories
->merge($this->followedComments)
->merge($this->followedPosts);
}
Then you can reach your goal by accessing to followers of certain category, comment or post or whatever you wish(if it followable of courcse)
For example:
$folowers = $category->folowers;
// will return all followers this category
$all = $user->followedStuff();
// will return collection of all things followable by the user

Laravel 5.1 Multiple Many to Many Relationship on the Same Model

I seen to of got tangled in Laravel's ORM with the following:
Scenerio: All Users have a Watchlist, the Watchlist contains other Users.
I can't seem the get the relationships to work correctly as they are cyclical, so far I have the following:
class UserWatchlist extends Model
{
protected $table = 'UserWatchlist';
public function Owner() {
return $this->belongsTo('App\User');
}
public function WatchedUsers() {
return $this->hasMany('App\User');
}
}
Schema::create('UserWatchlist', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('Users')->onDelete('cascade');
$table->integer('watched_id')->unsigned();
$table->foreign('watched_id')->references('id')->on('Users')->onDelete('cascade');
$table->timestamps();
});
class User extends Model
{
public function Watchlist() {
return $this->hasOne('App\UserWatchlist');
}
public function WatchedBy() {
return $this->belongsToMany('App\UserWatchlist');
}
}
It is not pulling through the correct in formation i'm expecting. Am I missing something fundamental?
Since UserWatchlist is a pivot table, i suppose you are facing a many to many relationship with both the elements of the relation being the same model (User)
If that is the case, you should not build a model for the pivot table UserWatchlist but all you have to do is to set the relation between the users through the pivot table:
class User extends Model
{
//get all the Users this user is watching
public function Watchlist()
{
return $this->belongsToMany('User', 'UserWatchlist', 'user_id', 'watched_id' );
}
//get all the Users this user is watched by
public function WatchedBy()
{
return $this->belongsToMany('User', 'UserWatchlist', 'watched_id', 'user_id' );
}
}
Check here for more info on many-to-many relationship

Categories