Reputation: 6976
I have 2 tables in my database, a notifications
table and a notifications_user
table.
A notification can have many notification users. And a result in my notification model I have the following relationship,
public function user()
{
return $this->belongsToMany('User')->withPivot('is_read');
}
What I am wanting to achieve is to get all notifications that are unread (or is_read = 0), the is_read column is in the notification user table though and I cannot work out how to run a query on it becuase of that.
Current I have this,
$unread = Notification::has('user')->with('user')->get();
Now this pulls the relationship into the results, but takes no account of the is_read value.
Is there a way to select all the data from a table based on a value in its 1:n relationship.
Upvotes: 1
Views: 139
Reputation: 964
So while it may make sense to have the relation that notifications have many users it really doesn't make sense from an ownership. Notifications are one-time things while users persist in a way. So try to think of users as the base object and notifications as the abundant resource.
The goal here is to get the users notifications so out of this you have to choose whether to duplicate notifications for each user or have one notification for many users. In one case where it's universal notifications (admin panel maybe) and the other is notifications that are personal to the user. If you're doing the latter you don't really need a pivot table and just a notifications table.
User -> hasOne -> Notification
Notification -> belongsTo -> User
This enables you to really customize the notifications per-user than relying on maybe another table for read notifications you can just mark it as "read" in the row.
If however you need universal notifications the structure just implements a third table called a pivot as you know. (I noticed you have the class names pluralized which is not recommended)
User -> Notification_User -> Notification
For ease you also could just soft-delete the notification_user row or notification themselves. You can simply just say ->withTrashed()->limit(x) to get previous notifications.
This really simplifies the work done by the DB and your code. The personal notifications allows you to order by creation/update and deal with read in two ways, soft-deletion and IsRead variables.
Your code becomes as simple as this.
Auth::user()->notifications()
Your User class has the following (assuming standard naming schemes)
public function notifications()
{
//You're free to append other requirements here
return $this->hasMany('App\Notification','id','user_id');
}
The Notification class has the inverse
public function user()
{
//You're free to append other requirements here
return $this->belongsTo('App\User','user_id','id');
}
If for some reason you require to know all unread notifications universally just query the Notification table.
Notification::where('isRead','null')->get();
Alternatively you can lazy load the users for each notification or group by users in this case for whatever purpose you need.
Upvotes: 0
Reputation: 6544
You can use the wherePivot
and orWherePivot
functions provided by laravel for relations. Link
Upvotes: 0
Reputation: 3060
You can query on the relationship by doing something like:
$unread = Notification::has('user')->with('user')->where('is_read','!=', 0)->get();
Check the docs: http://laravel.com/docs/5.1/eloquent-relationships#querying-relations
Upvotes: 1