Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to renew or reset when using Eloquent cache? #2794

Closed
abishekrsrikaanth opened this issue Nov 25, 2013 · 16 comments
Closed

How to renew or reset when using Eloquent cache? #2794

abishekrsrikaanth opened this issue Nov 25, 2013 · 16 comments

Comments

@abishekrsrikaanth
Copy link

If I am caching the results of a Eloquent object using

$articles = Countries::remember(5)->get();

or

$articles = Countries::rememberForever()->get();

how can i renew or reset this to fill in fresh data from the database to the cache?

@Anahkiasen
Copy link
Contributor

You mean without doing artisan cache:clear ? Like just empty Eloquent's cache ? Not sure if that's possible.

@abishekrsrikaanth
Copy link
Author

@Anahkiasen, yes. without using artisan cache:clear. I don't wish to clear the entire cache. Lets say, I added a new country to my country table and want to clear the cache specific to the data when I did $articles = Countries::remember(5)->get();. How do I do that?

@anlutro
Copy link
Contributor

anlutro commented Nov 25, 2013

Didn't I tell this on irc a while ago?

$query = Countries::newQuery()->remember(5);
Cache::forget($query->getCacheKey());
$countries = $query->get();

@crynobone
Copy link
Member

@anlutro wouldn't it be nice to have Countries::clearAndRemember()->get(); to force clear cache and generate a new cache.

p/s: Not entirely agree with the method name.

@abishekrsrikaanth
Copy link
Author

@anlutro, Don't seem to have noticed it on IRC. I will try to check the messages again. Thnx for notifying again. Appreciate your help.

@crynobone, I was thinking on the same terms as well

@anlutro
Copy link
Contributor

anlutro commented Nov 25, 2013

Or maybe just the option to do $query->forget() or $query->clearCache() - would be handy.

@abishekrsrikaanth
Copy link
Author

IMO $query->forget() or $query->clearCache() means more like clearing the cache of a a single query. Model::clearCache or Model::forget() would make more sense.

@anlutro
Copy link
Contributor

anlutro commented Nov 25, 2013

I don't think Model::forget() could work. remember() saves the results with the SQL query string as a key, so without a query builder there isn't really anything to clear.

@stayallive
Copy link
Contributor

Maybe in 4.1 cached queries can be tagged with eloquent:<class> so both is possible...

@crynobone
Copy link
Member

@stayallive

Model::whereUserId(5)->remember()->get();

// and

Model::whereId(5)->remember()->get();

should both generate two different key, if we tagged it with just eloquent:<class>, both would be flushed.

@stayallive
Copy link
Contributor

@crynobone: Yeah thats the idea ;)

There could be 2 options to have a little something something for everyone:

First: Model::clearCache(), wich is using the tags.
Second: $query->flushCache(), wich is using the actual query cache key.

@lucasmichot
Copy link
Contributor

Using the cache key attribute can be helpful :

// get last 5 users
$users = User::remember(60, 'last_5_users')->orderBy('created_at', 'desc')->take(5)->get();

// delete this specific cache entry
Cache::forget('last_5_users');

@taylorotwell
Copy link
Member

Yes, I would just pass a cache key as noted by @semalead.

@abishekrsrikaanth
Copy link
Author

@taylorotwell, @semalead, could you advice on how should the implementation be in case of the below scenario:

Countries Table

----------------------
id     |    name
----------------------
1      |    Australia
2      |    Austria
3      |    Algeria
4      |    Angola
//Retrieves all the countries and stores them on the cache
$countries = Countries::rememberForever('countries')->get();  

//Retreives all the countries starting with letter `A`
$countries_starting_with_a = Countries::rememberForever('countries_a')->where('name','like','A%')->get();

//Inserting a new country with letter `A`
Countries::create(array('Andorra'));

Cache::forget('countries'); only clears the cache with key countries and not the cache countries_a.

So calling

$countries_starting_with_a = Countries::rememberForever('countries_a')->where('name','like','A%')->get();

will retrieve all countries starting with the letter A except the one that was inserted later Andorra.

Is there a way to clear all cache that belong to the model Countries? Please advice

@abishekrsrikaanth
Copy link
Author

Discussed with @taylorotwell over IRC, and we can use the tags method of the query builder to do this.

Countries::remember(5,'countries')->tags(array('countries'))->get();
Countries::remember(5,'countries_a')->tags(array('countries'))->where('name','like','A%')->get();

And you can use the flush method of the Cache tags in Laravel 4.1 to flush them.

Cache::tags('countries')->flush();

Thnx @taylorotwell. Laravel is super cool...

@jonascarlbaum
Copy link

Reading the documentation of Laravel 4.2 it seems that the correct way of implementing the tagging is to write the following:

Countries::cacheTags(array('countries'))->remember(5,'countries')->get();

Note the cacheTags-method instead of tags-method and putting it before remember-method.

So that the flushing of tags will work:

Cache::tags('countries')->flush();

And it is worth noting that you have to use the memcached driver for this to work.

I'm just starting to look into this, having some issues. But it's an promising solution...
But am I on the correct path?

@taylorotwell @abishekrsrikaanth

My issue now is that Cache::tags('my-tag')->flush(); don't seem to work, I still get the result with a removed instance of my model, so I have to elaborate a bit more regarding this. The only difference from what I wrote here, except model name and tag name is that I don't supply a second parameter to remember-function.

Edit:
I got it working, my problem was related to a separate model serving as a sorted index (has a huge collection that needs advanced sorting) where the row that referred to the model instance was not deleted when deleting the instance of the model. Removing that row on the sorted index model and cache those queries with same tag made my code work.

Both Model::cacheTag(array('my-tag')->rememberForever()->get(); and Cache::tags('my-tag')->rememberForever('cache_key', function () {}); was perfectly playing along with calling Cache::tags('my-tag')->flush(); when model collection and instances (and in my case sorted index-tables) changes.

In short, the approach works great, if implemented correctly... ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants