Carosobin's avatar

Undefined array key "post_slug"

now i have two notifcation when a user comment on author post the author get notified and also when a author create a post they get point and get notified so think both notification are conflicting each other how can i resolve this please my code below

post create component

<?php

namespace App\Http\Livewire;

use App\Gamify\Points\PostCreated;
use App\Models\Category;
use App\Models\Post;
use App\Models\Tag;
use App\Models\User;
use App\Notifications\PointAdd;
use Illuminate\Support\Str;
use Livewire\Component;
use Illuminate\Http\Response;
use Livewire\WithFileUploads;

class PostCreate extends Component
{
    use WithFileUploads;
    public $post;
    public $users;
    public $body;
    public $slug;
    public $photo;
    public $title;
    public $category = 1;
    public $points = 10;
    public $energy = 1;

    public function increment()
    {
        $this->points++;
    }

    protected $rules = [
        'category' => 'required|integer|exists:categories,id',
        'title' => 'required|min:4',
        'body' => 'required|min:4',
    ];

    public function createPost()
    {
        if (auth()->check()) {
            $this->validate();
            $random =  str_pad(mt_rand(1,999999),6,'0',STR_PAD_LEFT);
            $post = Post::create([
                'user_id' => auth()->user()->id,
                'title' => $this->title,
                'category_id' => $this->category,
                'body' => $this->body,
                'post_number' => $random,
                'slug' => Str::slug($this->title) ?? null,
            ]);
                $users = auth()->user();
                $points = $users->givePoint(new PostCreated($post));
                $users->notify(new PointAdd($points));

                $image = $this->photo->storeAs('posts', str::random(30));
                $post->image = $image;
                $post->save();
                session()->flash("message", "Featured image successfully uploaded");

                preg_match_all('/(?<=#)(\w+)/mi', $this->body, $matchedTags, PREG_SET_ORDER, 0);
                foreach ($matchedTags as $matchedTag) {
                    if (!$tag = Tag::where('name', $matchedTag[0])->first()) {
                        $tag = tag::create(['name' => $matchedTag[0]]);
                    }
                    $post->tags()->attach($tag->id);
                    $tag->addEnergy(1);
                }

                preg_match_all('/(?<=@)(\w+)/mi', $this->body, $matchedMentions, PREG_SET_ORDER, 0);
                foreach ($matchedMentions as $matchedMention) {
                    optional(User::where('username', $matchedMention[0])->first(), function ($user) {
                        // $user->notify(new MentionsNotify($user));
                    });
                 }


            // $users = auth()->user();
            // $users->increment('points', 10);

            session()->flash('success_message', 'Post was added successfully!');

            $this->reset();

            return redirect()->route('post.index');
        }

        abort(Response::HTTP_FORBIDDEN);
    }




    public function upload()
    {
        $this->validate();


    }
    public function render()
    {
        return view('livewire.post-create', [
            'categories' => Category::all(),
        ]);
    }
}

point add notification

<?php

namespace App\Notifications;

use App\Models\Post;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class PointAdd extends Notification
{
    use Queueable;
    public $users;
    public User $user;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail', 'database'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('The introduction to the notification.')
                    ->action('Notification Action', url('/'))
                    ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            'user_id' => $this->user->id,
            'user_name' => $this->user->name,
            'user_avatar' => $this->user->avatar,
            'user_points' => $this->user->reputation,
           
        ];
    }
}

comment component

<?php

namespace App\Http\Livewire;

use App\Models\Comment;
use App\Models\Movie;
use App\Models\Post;
use App\Notifications\NewComment;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Notification;
use Livewire\Component;

class AddComment extends Component
{

    public $post;
    public $movie;
    public $comment;
    protected $rules = [
        'comment' => 'required|min:4',
    ];

    public function mount(Post $post)
    {
        $this->post = $post;
    }

    // public function mount(Movie $movie)
    // {
    //     $this->movie = $movie;
    // }


    public function addComment()
    {
        if (auth()->guest()) {
            abort(Response::HTTP_FORBIDDEN);
        }

        $this->validate();

        $comment = Comment::create([
            'user_id' => auth()->id(),
            'post_id' => $this->post->id,
            'movie_id' => $this->post->id,
            'body' => $this->comment,
        ]);

        $this->reset('comment');
        $this->post->user->notify(new NewComment($comment));
        $this->emit('commentWasAdded', 'Comment was posted!');
    }

    public function render()
    {
        return view('livewire.add-comment');
    }
}
Addcomment notification
<?php

namespace App\Notifications;

use App\Models\Comment;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NewComment extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(Comment $comment)
    {
       $this->comment = $comment;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail','database'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
        ->subject('Tribe Creators: A comment was posted on your story')
        ->markdown('email.comment',[
            'comment' => $this->comment,
        ]);
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            'comment_id' => $this->comment->id,
            'comment_body' => $this->comment->body,
            'user_avatar' => $this->comment->user->avatar,
            'user_name' => $this->comment->user->name,
            'post_id' => $this->comment->post->id,
            'post_slug' => $this->comment->post->slug,
            'post_title' => $this->comment->post->title,
        ];
    }
}

Notification blade to display all notifcation


div x-data="{ isOpen: false }"class="relative" >
    <button @click=
        "isOpen = !isOpen
        if (isOpen) {
            Livewire.emit('getNotifications')
        }
    ">
        <svg class="w-8 h-8 text-purple-500" viewBox="0 0 20 20" fill="currentColor">
            <path d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z" />
        </svg>
        @if ($notificationCount)
            <div class="absolute flex items-center justify-center w-6 h-6 text-white bg-red-500 border-2 rounded-full text-xxs -top-1 -right-1">{{ $notificationCount }}</div>
        @endif
    </button>
    <ul
        class="absolute z-10 overflow-y-auto text-sm text-left text-gray-700 bg-white w-76 md:w-96 shadow-dialog rounded-xl max-h-128 -right-28 md:-right-12"
        x-cloak
        x-show.transition.origin.top="isOpen"
        @click.away="isOpen = false"
        @keydown.escape.window="isOpen = false"
    >
        @if ($notifications->isNotEmpty() && ! $isLoading)
            @foreach ($notifications as $notification)
            <li>
                <a
                    href="{{ route('post.show', $notification->data['post_slug']) }}"
                    {{-- @click.prevent="
                    @click.prevent="
                        isOpen = false
                    " --}}
                    "
                    wire:click.prevent="markAsRead('{{ $notification->id }}')"
                    class="flex px-5 py-3 transition duration-150 ease-in hover:bg-gray-100"
                >
                    <img src="{{ $notification->data['user_avatar'] }}" class="w-10 h-10 rounded-xl" alt="avatar">
                    <div class="ml-4">
                        <div class="line-clamp-6">
                            <span class="font-semibold">{{ $notification->data['user_name'] }}</span> commented on
                            <span class="font-semibold">{{ $notification->data['post_title'] }}</span>:
                            <span class="line-clamp-2">"{{ $notification->data['comment_body'] }}"</span>
                        </div>
                        <div class="mt-2 text-xs text-gray-500">{{ $notification->created_at->diffForHumans() }}</div>
                    </div>
                </a>
            </li>
            @endforeach
        <li class="text-center border-t border-gray-300">
            <button
                wire:click="markAllAsRead"
                @click="isOpen = false"
                class="block w-full px-5 py-4 font-semibold transition duration-150 ease-in hover:bg-gray-100"
            >
                Mark all as read
            </button>
        </li>
        @elseif ($isLoading)
            @foreach (range(1,3) as $item)
                <li class="flex items-center px-5 py-3 transition duration-150 ease-in animate-pulse">
                    <div class="w-10 h-10 bg-gray-200 rounded-xl"></div>
                    <div class="flex-1 ml-4 space-y-2">
                        <div class="w-full h-4 bg-gray-200 rounded"></div>
                        <div class="w-full h-4 bg-gray-200 rounded"></div>
                        <div class="w-1/2 h-4 bg-gray-200 rounded"></div>
                    </div>
                </li>
            @endforeach
        @else
            <li class="w-40 py-6 mx-auto">
                <img src="{{ asset('img/logo/no-posts.svg') }}" alt="No posts" class="mx-auto" style="mix-blend-mode: luminosity">
                <div class="mt-6 font-bold text-center text-gray-400">No new notifications</div>
            </li>
        @endif
    </ul>
</div>
0 likes
10 replies
Snapey's avatar

conflict in what way?

You have shown a lot of code, but not given any idea what is going wrong

Carosobin's avatar

@Snapey both notification is working fine but whenever i click on the notification bell to view it, i get this error

if there is no point notification and there is only comment notification the notification blade works perfectly when i view it

the issue i think is from the point notification i cant seem to get post_slug even tho i did this

'post_slug' => $this->user->post->slug
`
Undefined array key "post_slug"
Tray2's avatar

Just a few suggestions

In your controller try to stick to these method names.

  • index
  • show
  • edit
  • update
  • create
  • destroy

It will make your code easier to understand.

You also to the auth check inside your controller, I suggest you handle that with a middleware.

Either put a

->middlerware('auth'):

on your routes that need an authenticated user or put it in the controllers constructor.

 public function __construct()
    {
        $this->middleware('auth')->except(['index', 'show']);
    }

Your validation can be moved into FormRequests as well.

Tray2's avatar

@Carosobin Is the post slug set in your post?

public function toArray($notifiable)
    {
        return [
            'comment_id' => $this->comment->id,
            'comment_body' => $this->comment->body,
            'user_avatar' => $this->comment->user->avatar,
            'user_name' => $this->comment->user->name,
            'post_id' => $this->comment->post->id,
            'post_slug' => $this->comment->post->slug, //Does this return the slug or does it fail?
            'post_title' => $this->comment->post->title,
        ];
    }

What happens if you dd the ´$notification` ?

href="{{ route('post.show', $notification->data['post_slug']) }}"
Carosobin's avatar

@Tray2 yes its set in my post and working fine when i click on it , since i have added the point notification i have been experiencing the issue , also the point notification isnt working as i expected because the notification is meant only for the post author not everyone

Tray2's avatar

@Carosobin Then check the code for the point notification them and use dd to dump it to see that it's there in every step.

Snapey's avatar

You have two types of notification. one has a post_slug, the other does not.

In the display of the notification, you have to decide which you are dealing with and display it appropriately.

Snapey's avatar

Test the type

@if

@else

@endif    

Alternatively, make sure each database notification conforms to the same design. For instance, you could make the notification contain only a message and a link. You display the message and allow them to click the link to go to the related item.

You would do this in the toArray method in the notification

Please or to participate in this conversation.