Laravel事件监听器和缓存无效

14
我正在使用Laravel开发应用程序时遇到一些困难。 我想使用事件和监听器删除并重建对象的缓存。

以下是代码:

app\Events\CampaignEvent.php

namespace App\Events;

use Illuminate\Queue\SerializesModels;

class CampaignEvent extends Event
{
    use SerializesModels;
    public $user_id;
    public $cache_keys;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($user_id, $cache_keys)
    {
        $this->user_id = $user_id;
        $this->cache_keys = $cache_keys;
    }
}

app\Listenters\CampaignListener.php

<?php

namespace App\Listeners;

use App\Events\CampaignEvent;
use Cache;
use Log;
use App\BrandCampaign;

class CampaignListener
{

    /**
     * Handle the event.
     *
     * @param  CampaignEvent  $event
     * @return void
     */
    public function handle(CampaignEvent $event)
    {
        /**
         * Remove cache
         */
        if(is_array($event->cache_keys)){
            foreach($event->cache_keys as $index => $cache_key){
                \Cache::forget($cache_key);
                Log::debug("[CACHE] Deleted cache for: " . $cache_key);
            }
        } else {
            \Cache::forget($event->cache_keys);
            Log::debug("[CACHE] Deleted cache for: " . $event->cache_keys);
        }

        /**
         * Rebuild cache for BrandCampaigns
         */
        $campaigns = BrandCampaign::with(['influencers' => function($query){
            $query->with(['influencer' => function($query){
                $query->select('id','profile_picture');
            }])->latest();
        }])->where('user_id', $event->user_id )->latest()->get();

        $total_influencers = [];
        foreach($campaigns as $campaign){
            foreach ($campaign->influencers as $influencer) {
                if(!in_array($influencer->influencer_id, $total_influencers))
                    $total_influencers[] = $influencer->influencer_id;
            }
        }
        $total_influencers = count($total_influencers);

        $campaigns = collect($campaigns)->toArray();

        \Cache::forever('@suppliers_campaigns('.$event->user_id.')', $campaigns);
        \Cache::put('@suppliers_total_campaigns('.$event->user_id.')', $total_influencers, 10);

        Log::debug("[CACHE] Cache rebuilt successfully!");
        return $event;
    }
}

I want to cache an array "forever", but in my campaign controller, after the event is fired, when I pull the array from cache it is returning null

Thanks!


你的缓存驱动是什么?你确定你的键 '@suppliers_campaigns('.$event->user_id.')' 和值 $campaigns 不为空且正确吗?suppliers_total_campaigns 缓存是否正常工作? - Mtxz
1
你能展示一下在控制器中如何检索数据吗?另外,为什么不导入缓存 use Illuminate\Support\Facades\Cache;?也许你正在使用指向不同配置的不同缓存类。 - Adrian Hernandez-Lopez
1
你是否在 EventServiceProvider.php 文件中注册了事件和监听器的组合? - Taha Paksu
抱歉如果这显得太明显了,但你是否在日志中验证了被删除的密钥实际上与你预期的匹配?你在这里呈现的代码看起来很好,所以我倾向于认为你的问题在于输入。另外,一些离题的建议: "Cache"已经被别名化了,所以你不需要像Adrian建议的那样使用整个命名空间,你现在的写法就可以了。在该事件中没有模型,因此您也不需要SerializeModels trait。如果你将$event->cache_keys强制转换为数组,你可以省略if/else块,直接使用循环。 - kmuenkel
1
这与问题有些无关,但你可能想重新考虑一下你的设计。理论上,监听器可以是异步的,并且可以由队列作业处理程序在应用的不同实例中执行,该处理程序甚至可能不在同一台服务器上,导致目标缓存超出范围。这可能不适用于你特定的用例,但考虑到解耦的事件和监听器的性质和目的,这感觉像是一种反模式。 - kmuenkel
1
你是否已将事件添加到事件服务提供商或启用了事件发现?请参考 https://laravel.com/docs/8.x/events#event-discovery。为确保事件正常触发,请向事件添加日志记录。 - Cameron
2个回答

0

适用于 Laravel 5(基于问题)和 Laravel 7(最新版本)。

use Illuminate\Support\Facades\Cache;

// Remove cache
Cache::forget('brandCampaigns');

// Rebuild cache for BrandCampaigns. Here, when the cache key doesn't exists, the function will be called and the returned value will be stored in the cache
$campaigns = Cache::rememberForever('brandCampaigns', function () {
    return BrandCampaign::with(['influencers' => function ($query) {
        $query->with(['influencer' => function ($query) {
            $query->select('id', 'profile_picture');
        }])->latest();
    }])->where('user_id', $event->user_id)->latest()->get();
});

你如何触发事件? - Snapey
@Snapey 你可以使用事件类的静态dispatch方法分派事件。在阅读文档时,请从上到下仔细阅读。 - dbf
我在询问他们的调度方法。至于作业,请查看Laracasts论坛排行榜(仅第一行)。 - Snapey

0

EventServiceProvider类中启用发现功能非常重要。

-> app/Providers/EventServiceProvider.php

public function shouldDiscoverEvents()
{
    return true;
}

确保此函数返回 true,否则 eventslisteners 将无法配合使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接