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
Related
I am trying to implement a created_by column in my users' table.
I created a migration file to add the new column to the users' table:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('created_by')->default(0);
});
}
I have a User model which has the following relationships:
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function createdBy()
{
return $this->belongsTo(self::class, 'created_by');
}
In the UsersController, I have this method:
public function view($id)
{
$user = User::with(['roles', 'createdBy'])->where('created_by', Auth::id())->find($id);
return $user;
}
When I return the user variable, I get this result:
Now, I want to access the value from "email" in "created_by". I tried to do this:
return $user->created_by
What I'm getting is 2 but what I want to get is "biodunna#mailnator.com".
I also tried return $user->created_by->email but it returned an error since the result I'm getting from return $user->created_by is just a number.
I want to fetch the email value "biodunna#mailnator.com".
Please change the createdBy relationship function with the createdByUser.
here we just change the function name to avoid conflict between column name and relationship name.
public function createdByUser()
{
return $this->belongsTo(self::class, 'created_by');
}
so now, you can access like
$user->createdByUser->email
According to your JSON response this should work:
$user[0]->created_by->email
I'm currently working on a laravel project, but I'm kind of stuck finding the right eloquent relations.
My tables and the connections (should) look like this:
Project Relations
My model relations look like this:
User
public function team()
{
return $this->hasMany(Team::class, 'user_id');
}
public function evaluation()
{
return $this->hasMany(Evaluation::class, 'user_id');
}
Team
public function user()
{
return $this->belongsTo(User::class);
}
public function survey()
{
return $this->hasMany(Survey::class, 'team_id');
}
Evaluation
public function user()
{
return $this->belongsTo(User::class);
}
public function survey()
{
return $this->hasMany(Survey::class, 'evaluation_id');
}
Survey
public function team()
{
return $this->belongsTo(Team::class);
}
public function evaluation()
{
return $this->belongsTo(Evaluation::class);
}
public function surveyresponse()
{
return $this->hasMany(SurveyResponse::class, 'survey_id');
}
SurveyResponse
public function survey()
{
return $this->belongsTo(Survey::class);
}
public function testquestion()
{
return $this->belongsTo('App\TestQuestion');
}
Is this the way to go? Do I need a "Has Many Through" relation here? Or a "Polymorphic Relationship"?
Seems correct to me, i just didnt see the TesteQuestion model (your last relation).
Answering your question:
The HasManyThrough relation is just a shortcut for accessing distant relations via an intermediate relation, in your case: Users has many evaluations that has many surveys. With this relationship you could get all surveys from a user.
Your relation would look like this:
/**
* Get all of the surveys for the user.
*/
public function surveys()
{
return $this->hasManyThrough('App\Survey', 'App\Evaluation');
}
You can access this relation like this:
$user->surveys();
But you can achieve the same (without using the HasManyThrough) by doing:
$user->evaluations()->surveys();
Beware that this will return the evaluations too, not just the surveys and it requires more processing.
So i recommend you doing the HasManyThrough relationship if you pretend to access the surveys a lot.
I am trying to access the middle table attributes of many to many relationships using pivot but it return nulls.
class User extends Modal
{
public function packages()
{
return $this->belongsToMany('App\Package');
}
}
Class Package extend Model
{
public function users()
{
return $this->belongsToMany('App\User');
}
}
$package->pivot->created_at
but it returns null.
although i have a package associated to user.
By default, only the model keys will be present on the pivot object. If your pivot table contains extra attributes, you must specify them when defining the relationship:
public function packages()
{
return $this->belongsToMany('App\Package')->withPivot('created_at');
}
public function users()
{
return $this->belongsToMany('App\User')->withPivot('created_at');
}
Docs
Try this one:
class User extends Modal
{
public function packages()
{
return $this->belongsToMany('App\Package')->withTimestamps();
}
}
Class Package extend Model
{
public function users()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
}
Make sure you have timestamps in your table.
Schema::table('user_package', function (Blueprint $table) {
$table->timestamps();
});
you can do this by adding in your migrations
class User extends Modal
{
public function packages()
{
return $this->belongsToMany('App\Package')->withTimestamps();
}
}
Class Package extend Model
{
public function users()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
}
if you dont add this line your timestamps will not be saved in database.
return $this->belongsToMany('App\User')->withTimestamps();
Hope this helps.
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
I am implementing chat in my application using laravel. I have these Models:
`Users: id, name `
`Pages: id, user_id(foreign_key from Users table (id)), name`
`Posts: id, page_id(foreign_key from Pages table (id)), user_id(foreign_key from Users table (id)), body`
`Comments: id, post_id(foreign_key from Posts table (id)), user_id(foreign_key from Users table (id)), body`
I need to query followings
Get all posts of user with comments and with user
Get all posts of a page with comments and with user
I am using below query to get all posts of a page, but how can I include its comments and user details;
Page::with('post')->findOrFail($pageId)->post;
EDIT
USER Model: User.php
public function page() {
return $this->hasMany('Page');
}
public function post() {
return $this->hasMany('Post');
}
Page Model: Page.php
public function user()
{
return $this->belongsTo('User');
}
public function post() {
return $this->hasMany('Post');
}
Post Model: Post.php
public function user()
{
return $this->belongsTo('User');
}
public function page() {
return $this->belongsTo('Page');
}
public function comments() {
return $this->hasMany('Comment');
}
Comment Model: Comment.php
public function user()
{
return $this->belongsTo('User');
}
public function post() {
return $this->belongsTo('Post');
}
As your relationships are not that clear to me, i can only provide some hints where to look.
Getting posts of a user with comments sounds like laravel query scopes: http://laravel.com/docs/5.1/eloquent#query-scopes
You may also query for relationship existence: http://laravel.com/docs/5.1/eloquent-relationships#querying-relations
And Lazy Eager Loading could also help to retrieve the necessary instances.