laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
31.82k stars 10.77k forks source link

Cache::forget not remove cached data with redis #51671

Closed yanalshoubaki closed 1 week ago

yanalshoubaki commented 1 month ago

Laravel Version

11.8.0

PHP Version

8.2.19

Database Driver & Version

MySQL 8.0.36

Description

I have an issue when clearing the cache for a key, the issue is every key has a prefix with the name of the project like ( project1{key} ), I set the key by remember function. I use for forget the value forget function, so I debug the issue and I found that this function return (bool) $this->connection()->del($this->prefix.$key); the prefix variable is empty and not getting the actual prefix key in the config file.

Steps To Reproduce

  1. Use this for remember a value : $this->likes = Cache::remember("message:{$this->message->id}:likes", now()->addHours(4), function () { return $this->message->likes; });
  2. use this for forget the value Cache::forget("message:{$this->message->id}:likes");remember
driesvints commented 1 month ago

Heya, thanks for reporting.

We'll need more info and/or code to debug this further. Can you please create a repository with the command below, commit the code that reproduces the issue as one separate commit on the main/master branch and share the repository here? Please make sure that you have the latest version of the Laravel installer in order to run this command. Please also make sure you have both Git & the GitHub CLI tool properly set up.

laravel new bug-report --github="--public"

Please do not amend and create a separate commit with your custom changes. After you've posted the repository, we'll try to reproduce the issue.

Thanks!

yanalshoubaki commented 1 month ago

@driesvints

This is my code that have the issue, when there is not much caching on the page, it's work correctly :) But when there is much caching on the page, it's not working

this is my code for the component that is not working on it

<?php

namespace App\Livewire\Component;

use App\Models\Message;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Livewire\Attributes\On;
use Livewire\Component;

class MessageWithReplay extends Component
{
    public Message $message;

    public ?User $authUser = null;

    public Collection $likes;

    public Collection $favorites;

    public int $likes_count = 0;

    public bool $liked = false;

    public int $favorites_count = 0;

    public bool $favorited = false;

    public $usersLike;

    public $messageDetails = [];

    public function mount(Message $message)
    {
        $this->message = $message;
        $this->authUser = Cache::remember('user:' . Auth::id(), now()->addHours(4), function () {
            return Auth::user();
        });
        $this->likes = Cache::remember("message:{$message->id}:likes", now()->addHours(4), function () {
            return $this->message->likes;
        });
        $this->favorites = Cache::remember("message:{$message->id}:favorites", now()->addHours(4), function () {
            return $this->message->favorites;
        });
        $this->likes_count = $this->likes->count();
        $this->favorites_count = $this->favorites->count();
        if ($this->authUser) {
            $this->liked = $this->message->likes->contains('user_id', $this->authUser->id);
            $this->favorited = $this->message->favorites->contains('user_id', $this->authUser->id);
        }
        $this->messageDetails = [
            'title' => $this->message->message,
            'url' => route('message.show', ['message' => $this->message]),
        ];
    }

    #[On('add-like')]
    public function refreshLikes()
    {
        Cache::forget("message:{$this->message->id}:likes");
        $this->liked = $this->message->likes->contains('user_id', $this->authUser->id);
        $this->likes_count = $this->likes->count();
    }

    #[On('add-favorite')]
    public function refreshFavorites()
    {
        Cache::forget("message:{$this->message->id}:favorites");
        $this->favorited = $this->message->favorites->contains('user_id', $this->authUser->id);
        $this->favorites_count = $this->favorites->count();
    }

    public function addLike()
    {
        if ($this->liked) {
            $this->message->likes()->where('user_id', $this->authUser->id)->delete();
            $this->dispatch('add-like');

            return;
        }
        $this->message->likes()->create([
            'user_id' => $this->authUser->id,
        ]);
        $this->dispatch('add-like');
    }

    public function addFavorite()
    {
        if ($this->favorited) {
            $this->message->favorites()->where('user_id', $this->authUser->id)->delete();
            $this->dispatch('add-favorite');

            return;
        }
        $this->message->favorites()->create([
            'user_id' => $this->authUser->id,
        ]);
        $this->dispatch('add-favorite');
    }

    public function render()
    {
        return view('livewire.component.message-with-replay', [
            'message' => $this->message,
            'likes' => $this->likes,
            'liked' => $this->liked,
            'favorites' => $this->favorites,
            'favorited' => $this->favorited,
            'likes_count' => $this->likes_count,
            'favorites_count' => $this->favorites_count,
            'message_details' => $this->messageDetails,
        ]);
    }
}

When I click on the button that has addLike function then will create a new like or deleted it, then forget the cache for the key "message:{$this->message->id}:likes", and get the new count for likes ( execute new query ) and reflected it on the same component.

** If there is another way to do caching, please let me know.

** edit : I tried something else to update likes data :

      ... mount function
        $this->likes = Cache::remember("message:{$message->id}:likes", now()->addHours(4), function () {
            return $this->message->likes()->get();
        });
        $this->favorites = Cache::remember("message:{$message->id}:favorites", now()->addHours(4), function () {
            return $this->message->favorites()->get();
        });
....
   #[On('add-like')]
    public function refreshLikes()
    {
        Cache::forget("message:{$this->message->id}:likes");

        $this->likes = Cache::remember("message:{$this->message->id}:likes", now()->addHours(4), function () {
            return $this->message->likes()->get();
        });

        $this->liked = $this->likes->contains('user_id', $this->authUser->id);
        $this->likes_count = $this->likes->count();
    }
....
    #[On('add-favorite')]
    public function refreshFavorites()
    {
        Cache::forget("message:{$this->message->id}:favorites");
        $this->favorites = Cache::remember("message:{$this->message->id}:favorites", now()->addHours(4), function () {
            return $this->message->favorites()->get();
        });
        $this->favorited = $this->favorites->contains('user_id', $this->authUser->id);
        $this->favorites_count = $this->favorites->count();
    }

Is this the best solution for fixing the issue ?

Thank you

driesvints commented 2 weeks ago

@yanalshoubaki there's way too much going on in this code example that's not related to the problem at hand. Please create a minimal reproduction repo with the CLI command from above for us to debug.

driesvints commented 1 week ago

Closing this issue because it's inactive, already solved, old or not relevant anymore. Feel to open up a new issue if you're still experiencing this.