3

I am building a social network with Laravel framework, and I have a Notifications System.

Basically whenever a user interacts with the website in these 5 different ways:

  1. User upvotes a Post.
  2. User comments in a Post.
  3. User upvotes a comment.
  4. User replies to a comment.
  5. User upvotes a reply.

A notification is added to notifications table for that user (the OP (original poster) for instance, if a user upvotes a comment, a notification is added for the user who owns that comment, and in that notifications table I have these configuration.

$table->string('id')->primary();
        $table->string('type');
        $table->morphs('notifiable');
        $table->text('data');
        $table->timestamp('read_at')->nullable();
        $table->timestamps();

Hence basically I can get each logged In user's unread notifications by using command Auth::user()->unreadNotifications which is an array consisting of all the information of notifications.

But here is my question. For instance 100 user upvotes one of the post of an OP, that would mean that if I loop through unread notifications array, I'll get 100 notifications, but instead I want something like this, 'last user who interacted with the post' . 'x' people have . 'interacted' with your post.'

But I am just not able to execute it, so far I have managed to count the number of notifications user will see by using this logic:

public function get_Notification_Count()
{
    $total_notifications = Auth::user()->unreadNotifications;
    $num_of_posts = array();
    $num_of_comments = array();
    $num_of_replies = array();
    $num_of_upvoted_comments = array();
    $num_of_upvoted_replies = array();
    // $num_of_notifications = array();

    foreach ($total_notifications as $notification) {
        if ($notification->type == 'App\Notifications\UserUpvotedPost') {
            array_push($num_of_posts, $notification->data['post_id']);
            $num_of_posts = array_unique($num_of_posts);
        }
        if ($notification->type == 'App\Notifications\UserCommented') {
            array_push($num_of_comments, $notification->data['post_id']);
            $num_of_comments = array_unique($num_of_comments);
        }
        if ($notification->type == 'App\Notifications\UserReplied') {
            array_push($num_of_replies, $notification->data['comment_id']);
            $num_of_replies = array_unique($num_of_replies);
        }
        if ($notification->type == 'App\Notifications\UserUpvotedComment') {
            array_push($num_of_upvoted_comments, $notification->data['comment_id']);
            $num_of_upvoted_comments = array_unique($num_of_upvoted_comments);
        }
        if ($notification->type == 'App\Notifications\UserUpvotedReply') {
            array_push($num_of_upvoted_replies, $notification->data['reply_id']);
            $num_of_upvoted_replies = array_unique($num_of_upvoted_replies);
        }
    }

    $num_of_notifications = count(array_merge($num_of_posts, $num_of_comments, $num_of_replies, $num_of_upvoted_comments, $num_of_upvoted_replies));

    return $num_of_notifications;
}
halfer
  • 19,824
  • 17
  • 99
  • 186
slapbot
  • 627
  • 1
  • 6
  • 17

1 Answers1

3

I think your best bet would be to group the query:

Auth::user()->unreadNotifications()->select(\DB::raw('COUNT(*) as count'), 'type')
->groupBy('type')
->get();

I haven't tested this, but give it a spin ;)

thijsdemaa
  • 326
  • 1
  • 3
  • 11
  • Your answer is just beautiful, I never thought using query builders to solve my problem, I have just one more question, how to get data just like the type as I tried `return Auth::user()->unreadNotifications()->select(DB::raw('COUNT(*) as count'), 'type', 'data') ->groupBy('type') ->get();` and I am getting an error. – slapbot Sep 07 '16 at 08:38
  • there is an issue with your answer too, imagine a user upvoting two different posts of OP, I'll still get 1 notification because of grouping by type. – slapbot Sep 07 '16 at 09:13
  • What error are you getting? For your second question: `->groupBy('type', 'other_user_id')` where other_user_id should be replaced – thijsdemaa Sep 07 '16 at 09:22
  • Plus, if you make the data column a JSON column, I believe you can group on that too – thijsdemaa Sep 07 '16 at 09:24
  • This is the error `SQLSTATE[42000]: Syntax error or access violation: 1055 'laravel53.notifications.data' isn't in GROUP BY (SQL: select `data`, `type` from `notifications` where `notifications`.`notifiable_id` = 1 and `notifications`.`notifiable_id` is not null and `notifications`.`notifiable_type` = App\User and `read_at` is null group by `type` order by `created_at` desc)` and yeah, it is a JSON column and I am having no luck so far. – slapbot Sep 07 '16 at 09:29
  • I've solved the problem, and here is a link to a specific answer to this problem [link](http://stackoverflow.com/q/25800411/6303162) So the correct way to do would be `Auth::user()->unreadNotifications()->select('data', 'type') ->groupBy('data', 'type') ->get();` – slapbot Sep 07 '16 at 10:00