За последние 24 часа нас посетили 18366 программистов и 1678 роботов. Сейчас ищут 973 программиста ...

Уведомления

Тема в разделе "Laravel", создана пользователем Dimon2x, 26 янв 2019.

  1. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    В базу.

    Пользователь создаёт тему, эту тему комментит другой пользователь, и пользователю, который создал эту тему, приходит уведомление, что на его тему, кто-то оставил коммент.

    В правильном ли направлении я вообще двигаюсь?

    Нотофикация
    PHP:
    1. <?php
    2.  
    3. namespace App\Notifications;
    4.  
    5. use Illuminate\Bus\Queueable;
    6. use Illuminate\Notifications\Notification;
    7. use Illuminate\Contracts\Queue\ShouldQueue;
    8. use Illuminate\Notifications\Messages\MailMessage;
    9.  
    10. class MyFirstNotification extends Notification {
    11.  
    12.     use Queueable;
    13.  
    14.     private $details;
    15.  
    16.     public function __construct($details) {
    17.         $this->details = $details;
    18.     }
    19.  
    20.     public function via($notifiable) {
    21.         return ['database'];
    22.     }
    23.  
    24.     public function toDatabase($notifiable) {
    25.         return [
    26.             'user_id' => $this->details['user_id'],
    27.             'comment_id' => $this->details['comment_id']
    28.         ];
    29.     }
    30.  
    31. }
    Контроллер

    PHP:
    1. public function sendNotification()
    2.     {
    3.         //здесь будет id юзера, который создал тему
    4.          $user = User::find(1);
    5.        
    6.        
    7.          //user_id - тот кто ответил
    8.          //comment_id - id коммента
    9.        
    10.         $details = [
    11.             'user_id' => Auth::id(),
    12.             'comment_id' => 5,
    13.         ];
    14.  
    15.         Notification::send($user, new MyFirstNotification($details));
    16.  
    17.         dd('done');
    18.     }
    19.    
    20.    
    21.    
    22.     //этот метод для того, что бы
    23.     //пользователю показать его уведомления
    24.    
    25.     public function readNotification()
    26.     {
    27.         //здесь будет Auth::id()
    28.         //это для примера
    29.         $user = User::find(1);
    30.        
    31.         foreach ($user->unreadNotifications as $notification) {
    32.             dump($notification->data);
    33.         }
    34.         die;
    35.     }
     
  2. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Ну да. А что тут сложного-то? Уведомления в базу - это надо просто переписать то, что написано в доке. Я ещё понимаю, если бы ты спрашивал про броадкастинг - там действительно, ноду поставить, LaravelEcho поднять, я ещё проксирую его через nginx - тоже, в принципе, не так сложно, и дока есть, и статьи в нете, не сложно, но, скажем так, слегка заморочно. А уведомления в базу - Laravel всё сам за тебя делает
     
    Dimon2x нравится это.
  3. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer всё равно в доке примеров для меня маловато
     
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Слушай, отношения пользователь-уведомления - это обычные один-ко-многим, всё, о чём тут разговаривать. Просто Laravel дал несколько более удобную оболочку для этого всего
     
  5. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    Вывожу уведомления.

    В таблицу notifications в дату добавляются данные, таким способом

    PHP:
    1.   public function toDatabase($notifiable) {
    2.         return [
    3.             'post_id' => $this->details['post_id'], // id поста
    4.             'comment_id' => $this->details['comment_id'], //id комента
    5.             'user_comment_id' => $this->details['user_comment_id'] // id юзера, который оставил коммент
    6.         ];
    Теперь мне надо вывести список уведомлений, что бы было видно, кто оставил комент,
    и на какой пост, сделал это так

    PHP:
    1.  public function readNotification()
    2.     {      
    3.          $user = User::find(Auth::id());
    4.        
    5.          $allData = collect();
    6.        
    7.           foreach ($user->unreadNotifications as $notification) {
    8.               $collect1 = collect(Post::find($notification->data['post_id']));
    9.               $collect2 = collect(['user_comment' => Comment::find($notification->data['comment_id'])->text]);
    10.               $collect3 = collect(['user_name' => User::find($notification->data['user_comment_id'])->name]);
    11.              
    12.               $allData->push($collect1
    13.                       ->merge($collect2)
    14.                       ->merge($collect3)
    15.                       ->merge(['id_notif' => $notification->id]));
    16.           }
    17.          
    18.          
    19.        
    20.          return view('read-notifications', [
    21.             'allData' => $allData,
    22.              ]);
    23.     }
    HTML:
    1. <section class="section main-content">
    2.         <div class="container">
    3.          
    4.            @foreach ($allData as $data)
    5.             <div class="card">
    6.                 <div class="card-body">
    7.                   <h5 class="card-title">{{$data['user_name']}}, добавил комментраий к посту - {{$data['description']}}</h5>
    8.                   <div class="card-text">{!!$data['user_comment']!!}</div>
    9.                   <br>
    10.                   <a href="/post/{{$data['id']}}" class="btn btn-primary">Перейти</a>
    11.                   <a href="/mark-notif-read/{{$data['id_notif']}}" class="btn btn-primary">Отменить прочитанным</a>
    12.                 </div>
    13.              </div>
    14.            <br>
    15.             @endforeach
    16.            
    17.         </div>
    18.       </section>
    Это нормальный способ? Какой есть по лучше?
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.103
    Симпатии:
    1.243
    Адрес:
    там-сям
    Ты бы мог использовать стену своего профиля для ведения блога "Что сейчас ковыряет Димон".
    Походу ты чемпион по темам!
     
  7. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Попробуй самостоятельно убрать запросы в цикле. Ты же в курсе, что не хорошо? Коллекции здесь не пойми зачем, обычным массивом тоже самое было бы сделать проще и красивее.
     
  8. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer сделать 1 запрос, вместо трёх?
     
  9. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    @Dimon2x, у тебя не три запроса, а 3 * на кол-во уведомлений (это если там ещё with-ов нет внутри). Вот сделай, чтоб было просто 3
     
  10. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer в смысле сделать просто 3?
     
  11. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Ну вот возьми и подумай, как эти запросы можно вынести из цикла. У тебя запросы внутри цикла. Их можно оттуда вынести. Я бы конечно вообще один вызов find сделал, и хранил бы только comment_id в уведомлении, а пост и комментатора получал по связям и with(), но давай по очереди
     
  12. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    Вот так сделал

    PHP:
    1.  $user = User::find(Auth::id());
    2.        
    3.  
    4.           foreach ($user->unreadNotifications as $notification) {
    5.                $aaa = Comment::with('post)
    6.                       ->with('users')
    7.                       ->where('post_id', $notification->data['post_id'])
    8.                       ->where('user_id', $notification->data['user_comment_id'])
    9.                       ->where('id', $notification->data['comment_id'])
    10.                       ->get();
    11.            
    12.               dump($aaa);
    13.              
    14.          }
     
  13. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Уже лучше. Но можно вынести из цикла, надо немного сообразительность проявить. Ты же не салага уже, думай :)
     
  14. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer теперь меньше запросов?
     
  15. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    @Dimon2x, запросов не меньше, но код выглядит лучше :) @Dimon2x, я тебе уже третий раз говорю - вынеси запросы из цикла, а ты их пишешь внутри цикла. Оно работать так будет, как ты написал, но ты же сам спрашиваешь, как лучше :)
     
  16. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer в доке такого нету
    --- Добавлено ---
    @mkramer а чем код стал лучше? Я особо не вижу
     
  17. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Дока не заменяет мозг :) Тут нужно напрячь мозг, вспомнить, что у нас SQL в итоге получается, вспомнить, зачем нам Query Builder и прочее.
    Больше механизмов Laravel-я задействовано.
     
  18. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer всё равно, что бы добавить id уведомления, надо использовать коллекции

    PHP:
    1.  $user = User::find(Auth::id());
    2.        
    3.          $aaa = collect();
    4.        
    5.           foreach ($user->unreadNotifications as $notification) {
    6.                $collect1 = collect(Comment::with('question')
    7.                        ->with('users')
    8.                        ->where('post_id', $notification->data['post_id'])
    9.                        ->where('user_id', $notification->data['user_comment_id'])
    10.                        ->where('id', $notification->data['comment_id'])
    11.                        ->get());
    12.              
    13.                $aaa->push($collect1
    14.                       ->merge(['id_notif' => $notification->id]));    
    15.              
    16.           }
     
  19. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    Коробочный компонент уведомлений.

    Когда комментишь статью, то приходят уведомления, и они помечаются прочитанными,
    как сделать, что бы при удалении статьи, из таблицы удалялись эти уведомления?

    Ведь в таблицу не записывается отдельный id статьи, а записывается всё в столбец data.

    Может раширить таблицу уведомлений и добавить отдельный столбец id поста?

    Или есть уже готовое решение?

    Ведь взять все записи и перебрать каждую, потом искать есть ли в этом объекте id поста,
    это будет слишком большая нагрузка и это не логично.
     
  20. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    Какая СУБД и какой версии?
     
  21. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer mysql 5.7
    --- Добавлено ---
    Нашёл этот чудесный способ

    PHP:
    1.   $notifications = DB::table('notifications')
    2.                 ->whereJsonContains('data->post_id', $id)
    3.                 ->get();
    4.        
    5.         dd($notifications);
     
  22. Dimon2x

    Dimon2x Старожил

    С нами с:
    26 фев 2012
    Сообщения:
    2.209
    Симпатии:
    185
    @mkramer вот так сделал, допустимо ли?

    PHP:
    1.   $notifications = array_keys(DB::table('notifications')->select('id')
    2.                 ->whereJsonContains('data->post_id', $id)
    3.                 ->get()->groupBy('id')->toArray());
    4.      
    5.         DB::table('notifications')->whereIn('id', $notifications)->delete();
    --- Добавлено ---
    Так мне больше нравится

    PHP:
    1.   $notifications = DB::table('notifications')->select('id')
    2.                 ->whereJsonContains('data->post_id', $id)
    3.                 ->get()->pluck('id')->toArray();
     
  23. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.579
    Симпатии:
    1.759
    @Dimon2x, да, допустимо. Поэтому я и спросил про версию СУБД. MySQL научилась ладить с JSON только в 5.7. Хорошее решение