Идентифицировать пользователя комментария и отправить уведомление Laravel

#php #laravel

#php #laravel

Вопрос:

У меня есть система сообщений. На моем сайте пользователи могут публиковать статьи и оставлять комментарии к каждой статье. Я хочу выпустить: когда какой-либо пользователь (не автор сообщения) комментирует сообщение, мне нужно отправить уведомление автору сообщения, чтобы его сообщение было прокомментировано по имени пользователя… Я делаю это так:

В CommentController у меня есть метод для публикации комментария к сообщению:

 public function postComment(Post $post, AddPostRequest $request)
{
    if ($request->parent_id !== null) {
        $parent = Comment::where('id', $request->parent_id)->first();
        $this->authorize('canComment', $parent);
    }

    $data = [
        'user_id' => Auth::check() ? Auth::user()->id : null,
        'post_id' => $post->id
    ];

    $comment = $post->createComment(array_merge($request->except('g-recaptcha-response'), $data));

    $post->owner->sendReviewNotification($review);

    return $review;
}
  

В моей системе комментариев у меня есть вложенные комментарии. В сообщении модели у меня есть метод createReview.

 public function owner()
{
    return $this->belongsTo(User::class, 'user_id');
}

public function comments()
{
    return $this->hasMany(Comment::class);
}

public function createComment($data = [])
{
    $review = $this->comments()->create($data);

    return $review;
}
  

В комментарии к модели у меня есть:

 public function post()
{
    return $this->belongsTo(Post::class);
}

public function user()
{
    return $this->belongsTo(User::class);
}

public function parent()
{
    return $this->belongsTo(static::class, 'id', 'parent_id');
}

public function children()
{
    return $this->hasMany(static::class, 'parent_id');
}

public function scopeActive($query)
{
    return $query->whereNotNull('user_id')->where('active', 1);
}
  

Теперь: когда комментарий создан, уведомления отправляются автору сообщения, но когда автор может ответить на комментарий о его публикации, уведомление отправляется ему снова, но мне нужно отправить уведомление автору комментария. Как я могу определить этот случай? Мне не нужно всегда отправлять уведомления автору сообщения, мне нужно уведомлять и авторов комментариев, что на комментарии к ним отвечает автор сообщения.

Ответ №1:

Насколько я понимаю, вы пытаетесь отправить уведомление по электронной почте автору сообщения через класс электронной почты, sendReviewNotification с $review в качестве параметра. если это так, то эта строка

 $post->owner->sendReviewNotification($review);
  

потому что $post->owner возвращает красноречивую связь (это конструктор запросов)

вот как я бы это сделал. Я бы использовал приведенное выше соотношение, чтобы получить адрес электронной почты пользователя (автора)

 $post->owner->email
  

строка выше вернет адрес электронной почты авторов

затем используйте почтовый фасад

 Mail::to($post->owner->email)->send(new sendReviewNotification($review));
  

Я предполагаю, sendReviewNotification это ваш почтовый класс
также не забудьте добавить эту строку в начале вашего класса чуть ниже пространства имен.
use IlluminateSupportFacadesMail;

Ответ №2:

Я думаю, что вы действительно хотите отправить уведомление каждому участнику обсуждения, но только тем людям, которые прокомментировали с момента вашего последнего комментария:

 Post #4321 (Author Richard)
  -> Comment #1 by John
  -> Comment #2 by Elias
  -> Comment #3 by Richard    <-- the author
  -> Comment #4 by Michael
  -> Comment #5 by John
  -> Comment #6 by Merry
  -> Comment #7 by Richard    <-- the author
  

В этом сценарии вы, вероятно, захотите отправить уведомление в следующих ситуациях:

  1. Ричард получает уведомление, если кто-то прокомментировал его сообщение
  2. Автор комментария получает уведомление, если Ричард также комментирует

Первая ситуация кажется простой. Всякий раз, когда создается новый комментарий, вы уведомляете автора сообщения, которое было прокомментировано:

 if ($comment->author_id !== $comment->post->author_id) {
    $comment->post->author->notify(new PostWasCommented($comment));
}
  

Как вы можете видеть, я ожидаю, что вы будете использовать встроенную в Laravel систему уведомлений. Это делает вашу жизнь намного проще, если быть честным.


Вторая ситуация немного более сложная и снова допускает два возможных решения:

  • Вы отправляете уведомление всем, кто прокомментировал сообщение до того, как прокомментировал Ричард.
    В приведенном выше примере, когда Ричард создает комментарий # 3, Джон и Элиас получат уведомление. Когда Ричард создает комментарий # 7, Джон, Элиас, Майкл и Мерри получают уведомление. ( $comment будет ли создан новый комментарий.)

     $users = User::query()
        ->whereHas('comment', function ($query) use ($comment) {
            return $query->where('post_id', $comment->post_id);
        })
        ->where('user_id', '!=', $comment->post->author_id)
        ->get();
    
    foreach ($users as $user) {
        $user->notify(new PostWasCommented($comment));
    }
      
  • Вы отправляете уведомление только тем людям, которые прокомментировали с момента последнего комментария автора.
    В приведенном выше примере это означает, что Джон и Элиас будут уведомлены, когда Ричард создаст комментарий # 3. И когда Ричард создает комментарий # 7, тогда уведомляются только Майкл, Джон и Мерри, но не Элиас. Это потому, что только эти три человека прокомментировали между # 3 и # 7.

     $users = User::query()
        ->whereHas('comment', function ($query) use ($comment) {
            return $query->where('post_id', $comment->post_id)
                ->where(
                   'created_at', 
                   '>', 
                   DB::raw(
                       "SELECT MAX(created_at) FROM comments WHERE post_id = ? AND author_id = ?", 
                       [$comment->post_id, $comment->author_id]
                   )
                );
        })
        ->where('user_id', '!=', $comment->post->author_id)
        ->get();
    
    foreach ($users as $user) {
        $user->notify(new PostWasCommented($comment));
    }
      

Комментарии:

1. Неплохо. Но во второй ситуации, когда мне нужно написать ваш код? И у меня есть вложенные комментарии, у каждого комментария могут быть дочерние элементы

2. Я думаю, вы могли бы написать это в sendReviewNotification($comment) . Или вы добавляете событие с именем CommentCreated и помещаете его в прослушиватель событий (вероятно, более приятное решение, поскольку оно разделяет логику). То, как вы будете работать с вложенными комментариями, немного зависит от того, как они хранятся. Хранят ли вложенные комментарии также post_id или только parent_id предыдущий (родительский) комментарий ?

3. У меня есть и post_id и parent_id в таблице комментариев.

4. Ну, тогда почему родительский элемент вообще имеет значение? Я думаю, что это интересно, только если вы хотите уведомить автора родительского комментария или только публикации, что было бы ситуацией, которую я не включил в свой ответ. Это также не сильно отличается от того, что я описал, если вы не используете бесконечную вложенность комментариев.