Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Retrieved Observer not firing from CachedBuilder #510

paularmstrong80 started this conversation in Ideas
Discussion options

Hi Mike,

First, thank you for the great package, really appreciate your work!

I came across this issue when attempting to hook into the model's retrieved event.

The retrieved event only fires if the result hasn't been cached. Once the result is in cache, it no longer fires.

To work around the issue I had to do the following:

  1. Replaced newEloquentBuilder in base model to return extended GeneaLabs\LaravelModelCaching\CachedBuilder if model is cachable.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use App\Database\Eloquent\Builder\OverrideCachedBuilder;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
abstract class BaseModel extends Model
{
 use Cachable;
 public function newEloquentBuilder($query)
 {
 if (! $this->isCachable()) {
 $this->isCachable = false;
 return new EloquentBuilder($query);
 }
 return new OverrideCachedBuilder($query); // call custom extended CachedBuilder
 }
}
  1. Override CachedBuilder cachedValue method with a modified version that fires the retrieved model event.
namespace App\Database\Eloquent\Builder;
use GeneaLabs\LaravelModelCaching\CachedBuilder;
class OverrideCachedBuilder extends CachedBuilder
{
 public function cachedValue(array $arguments, string $cacheKey)
 {
 $method = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
 $cacheTags = $this->makeCacheTags();
 $hashedCacheKey = sha1($cacheKey);
 $result = $this->retrieveCachedValue(
 $arguments,
 $cacheKey,
 $cacheTags,
 $hashedCacheKey,
 $method
 );
 // start - my hack to fire model retrieved event
 if ($resultValue = data_get($result, 'value')) {
 try {
 if (is_subclass_of($resultValue, 'Illuminate\Database\Eloquent\Model')) {
 $resultValue->fireModelEvent('retrieved', false);
 }
 } catch (\Throwable $th) {
 //throw $th;
 }
 }
 // end - my hack to fire model retrieved event
 return $this->preventHashCollision(
 $result,
 $arguments,
 $cacheKey,
 $cacheTags,
 $hashedCacheKey,
 $method
 );
 }
}

My solution is not pretty, but works. I had troubles doing it other ways because of the debug_backtrace in the cacheValue event.

If there's a way to improve this solution, and/or get it into core, that would be amazing.

Kind Regards,
Paul

Originally posted by @paularmstrong80 in #171 (comment)

You must be logged in to vote

Replies: 3 comments

Comment options

Hi @paularmstrong80, thanks for moving this over to a new issue.

I'm going to have to ponder this a bit, but I can see where you're coming from.

You must be logged in to vote
0 replies
Comment options

Coming from this exact same issue (getting retrieved event for cached model instances, too). This will be fixed, ie, we will get retrieved for all models, cached or not? if Yes, there is a way to differentiate which one is cached or not cached?
Another option is to get another event like retrievedFromCache or something like that in case of model instances which came from cache.

You must be logged in to vote
0 replies
Comment options

There is a event Illuminate\Cache\Events\CacheHit which might be useful to you

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Converted from issue

This discussion was converted from issue #399 on March 05, 2025 13:59.

AltStyle によって変換されたページ (->オリジナル) /