I am trying to build a 'facebook groups' style application, which contains groups filled with members, each member has a membership type (eg. admin, officer, user..) and each group has its group type (public, closed, secret).
so I created few tables:
users - (id, name ..)
groups - (id, name, group_type_id ..)
group_types - (id, type)
group_members - (user_id, group_id, membership_type_id)
group_membership_types - (id, type)
I believe this is the proper approach to structure the DB (correct me if I wrong).
now I need to convert it to Eloquent models, so I created the models, but got really confused when trying to make the relationship between them, I read about 'pivot' and 'hasManyThrough' and got even more confuse.
theses are the models I created so far:
class Group extends BaseModel
{
protected $table = 'groups';
public function Members() {
return $this->belongsToMany('App\GroupMemeber');
}
public function Type() {
return $this->belongsTo('App\GroupType');
}
}
--
class GroupType extends BaseModel
{
protected $table = 'group_types';
protected $guarded = ['id', 'type'];
}
--
class GroupMemebershipType extends BaseModel
{
protected $table = 'group_membership_types';
}
--
class GroupMember extends BaseModel
{
protected $table = 'group_members';
public function User() {
return $this->belongsTo('App\User');
}
public function Group() {
return $this->hasMany('App\Group');
}
public function MembershipType() {
return $this->belongsTo('App\GroupMemebershipType');
}
}
am I doing it right? how would you create those models?
whereHas() works basically the same as has() but allows you to specify additional filters for the related model to check.
BelongsTo relationship in laravel is used to create the relation between two tables. belongsTo means create the relation one to one in inverse direction or its opposite of hasOne. For example if a user has a profile and we wanted to get profile with the user details then we can use belongsTo relationship.
Pivot tables are, by convention, named tablename1_tablename2
where tablename1
is alphabetically superseding tablename2
. In this case, group_members
should be group_user
. If you change this, you don't need to define the $table variable, so you can remove those to clean up the code if you want.
The Eloquent relationships are well documented, and if you are ever unsure you can always refer to the code documentation, which is pretty straight-forward:
hasOne
Define a one-to-one relationship.
hasMany
Define a one-to-many relationship.
hasManyThrough
Define a has-many-through relationship.
belongsTo
Define an inverse one-to-one or many relationship.
belongsToMany
Define a many-to-many relationship.
When using a pivot-table, you can add ->withPivot()
and Eloquent will automagically find your conventionally named pivot table. You don't even need models for these "middle"-objects, because they (probably) won't be used in your presentation-layer.
Now, as for your group memberships, here is where things get a little complicated. The hasManyThrough
relation is for accessing distant relations via an intermediate relation, and is not what you are looking for. Laravel does not offer any "plug-and-play" functionality for this type of relationship, and while there is a Laravel 4 library for this purpose, it is not very dynamic but only offers three-way functionality. This is fine for now, but what if you decide to expand on your pivot-table in the future? Then this would break.
I looked over the structure of your tables, and noticed that it can easily be restructured:
By avoiding the three-way pivot tables, your code (and table structure) is much more easily maintained and more readable. I think this applies to any pivot-table with three-way relations, and a good rule of thumb is to avoid it by using a smarter table structure.
A user
Code:
class User extends Model
{
public function memberships() {
return $this->belongsToMany('App\Membership');
}
public function groups() {
return $this->hasManyThrough('App\Group', 'App\Membership');
}
}
A membership
Code:
class Membership extends Model
{
public function users() {
return $this->hasMany('App\User');
}
public function group() {
return $this->hasOne('App\Group');
}
}
A group
Code:
class Group extends Model
{
public function memberships() {
return $this->hasMany('App\Membership');
}
public function users() {
return $this->hasManyThrough('App\User', 'App\Membership');
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With