How to clear cache with specific key in laravel 9? - php

I created a cache with a key USERS:
return Cache::remember('USERS', Carbon::now()->addMinutes(30), function() {
return User::orderBy('name')->get();
});
I want to clear the USERS cache when adding new User.
How to clear the USERS cache?

You could use Cache::forget() like this
Cache::forget('USERS');
for more info check the docs here

To clear Laravel cache, simply use the forget() function as shown below:
=> Cache::forget('key');
You can also retrieve a cache value and can delete it immediately. Technically, you can call it one time caching.
=> $articles = Cache::pull('key');

Related

Laravel: how to cache route for 5 minutes?

I want to cache one route in Laravel project and clear it for every 5 minutes.
I searched a bunch of articles but only found artisan route:cache command and I have no idea if it possible to configure caching time.
So, this is my routes routes/web.php:
$router->group(['middleware' => ['api','cors']], function () use ($router) {
$router->get('game', ['uses' => 'GameController#checkGameStatus']);
$router->get('promo', ['uses' => 'PromoController#sendPromoCode']);
$router->get('get_leaders', ['uses' => 'GameController#getLeaders']); // <-- cache this for 5m
});
And every time when user loads rating page the getLeaders() function initiates DB request to get and calculate all user results. Therefore I want to reduce DB load and make it calculating all results once in 5 minutes. The rest of the time get_leaders route should send back just cached json output.
How to set such configuration? Is it possible to do just with Laravel (artisan) or should I change .htaccess file (I am using apache)?
To add to #TimLewis 's answer, if you're using laravel 5.8 or newer then the Cache::remember function can simplify the controller code quite a bit
public function getLeaders(){
$leaders = Cache::remember('leaders', 300, function () {
return Leader::where(...)->get();
});
return response()->json(['leaders' => $leaders]);
}
The Cache::remember function takes care of the entire caching workflow, it first checks the cache for the leaders object and returns that if it exists. If not, it runs the code inside the closure and stores the result in the cache under the key specified in the first param, for the number of seconds specified in the second param. So in this case it would cache the result under the key "leaders" for 300 seconds (5 minutes).
This is a pretty simple to solve problem actually. In your function getLeaders(), you'll need to modify the code:
public function getLeaders(){
$leadersCache = Cache::get("leaders", null);
if($leadersCache){
return response()->json(["leaders", $leadersCache], 200);
}
$leaders = Leader::where(...)->get();
Cache::put("leaders", $leaders, 5);
return response(["leaders", $leaders], 200);
}
So, what this does, is first, check if "leaders" exists in the cache. If it does, it will simply return that. If it doesn't (which will be the case when this route is first called), then it will do the calculations, and using Cache::put(), store it in the cache, then return. For the next 5 minutes, anytime this route is hit, it will return the cached result, until the process is started over again.
Note the above is pseudo-code, as your Controller wasn't shown, but the approach can be easily adapted to existing code. Also, you may need to include use Cache; at the top of your Controller, or reference Cache via \Cache::{method}
Everything about the cache can be found in the documentation: https://laravel.com/docs/5.7/cache
Laravel > 7 u can use cash::rmember(), and u will save a lot with writing less
Example :
$getleaders = Cache::remember('getleaders', 'minutes', function () {
u query;
});

Force logout of all users in Laravel

How can I force all users to be logged out in a SPA? I want it so that when I deploy a new version, all users automatically get logged out.
I tried the following, but I'm not sure if it's the safest way to do it.
php artisan key:generate
If your session data is stored in the database, you need to clear the sessions table. Running a simple SQL query will solve the problem:
DELETE FROM sessions;
If you sessions are stored in files, then as #Karl suggests, you need to delete the session files from the filesystem:
rm -rf storage/framework/sessions/*
The name of the session cookie can also be changed to force all sessions to be invalid, but this is a code change rather than clearing data. The name can be updated in the cookie key in config/session.php file. This option is NOT recommended.
As you can see, the SessionGuard does a few things, and they are agnostic of the type of SESSION_DRIVER you have set in your environment.
So after reading some of the discussion on forums with Taylor and some other Laravel heavy-weights about why there isn't such a simple function, perhaps the best solution would be create a post-deploy Job or Command that you could run that would simply cycle through all users, so for whatever is Session is set. I'd try something like:
\App\User::each(function ($u) {
Auth::login($u);
Auth::logout();
});
You can destroy all the sessions. If you use Laravel Envoy to handle deployments, you can add the following line.
rm -rf storage/framework/sessions/*
If you're using the database session driver, clearing the sessions table is easy.
DB::table('sessions')->truncate();
it's really depend on with session drive you picked.
if you using file drive you can delete storage/framework/sessions
path
if you using database drive you can delete all rows of session
table,
for any other drive you can do that like others.
You can also change cookie value in app/session.php, so user will automatically logout because of cookie is not match with the config
It's worth noting that Laravel actually only stores active sessions in
the session folder; those that are 'remembered' but haven't been
actively accessing your application do not count among these sessions.
As such, just deleting the files won't finish the job.
You must also clear all Remember Tokens from the users table, as this
token is used in conjunction with the local token stored in the cookie
to re-create the session when a user reconnects.
I'm updating all user's remember tokens to blank and then flushing stored session and then modifying HomeController.
\DB::table('users')->update(array(
'remember_token' => '',
'logout_at' => Carbon::now()->toDateTimeString()));
Session::flush();
Then in HomeController modify index function
public function index()
{
if (Auth::check()) {
$token = Auth::user()->remember_token;
if ($token) {
return view('home');
} else {
return redirect('/logout');
}
} else {
return view('home');
}
}
I'd like to share another way to achieve this, if the driver used is file.
This is the "pure" php way, so it could be a helper 'flush_sessions()':
$sessions = glob(storage_path("framework/sessions/*"));
foreach($sessions as $file){
if(is_file($file))
unlink($file);
}
It is safe to use this function? PHP will keep hidden files inside given directory (.gitignore)... so, try it out, it is safe.
It is worth to mention that if you put this inside a controller method, then your session will be restored after delete the file (apparently, Laravel will try to update the file after the request ends and if it doesn't exists, will re-create it). But all other sessions (users) will be logged out. If you run this code in php artisan tinker, for example, will not keep your own session file (because artisan runs with 'array' driver).
But, that is useful in my opinion. For example: if admin user wants to logout all users except himself.
For example:
You have two sessions:
After running the function, you have only one (the user that used it):
I hope this helps someone.
//To Logout Specific user:
//$id == user id to to whom you want to logout
\DB::table('users')->where('id', $id)->update(['remember_token' => null]);
\DB::table('sessions')->where('user_id', $id)->delete();
//To Logout All Users
$sessions = glob(storage_path("framework/sessions/*"));
foreach ($sessions as $file) {
if (is_file($file))
unlink($file);
}
//$id == user id to to whom you want to logout
\DB::table('users')->update(['remember_token' => null]);
\DB::table('sessions')->truncate();
No need to use sessions table operation if you are not using database as session driver.

How to return once from database and store in memory in Laravel

What I want to do:
Return a bunch of rows from database, convert in a array stored in memory and make this array visible from the whole project in such a way that other controllers for example can read it. My function is simple as that:
class BoardController extends Controller
{
/*
* returns something like
* ['name' => 'description',
...
]
*
* */
public static function getAll()
{
$boards = Board::orderBy('ordem')->get();
$retorno = array();
foreach($boards as $b)
{
$retorno[$b->sigla] = $b->nome;
}
return $retorno;
}
}
If I just keep calling BoardController::getAll() it will again read from database again. I also tried making this call inside a config file into a variable and returning it there but laravel gave me a 500 error. So, what is the best practice/way to do it?
If you don't want to call the database everytime then the best approach that can be followed here is to use caching and cache the results.
The Approach is simple, You make a Database call once and cache the reaults and the next time you hit the same function you check the cache first whether its empty or not. If its not empty, then return the cached results.
Remember, the cache has a time limit otherwise if you change/update anything in the database then you'll have to clear the cache that is already stored.
Laravel has some features for caching the results. You can see it Here.
Also You can also view this link for more effective implementation of cache in Laravel.
Hope this helps.

Yii2 Caching Active Record

I need help with caching Active Record data in Yii2.
In documentation has example:
$result = Customer::getDb()->cache(function ($db) {
return Customer::find()->where(['id' => 1])->one();
});
I understand that it need to implement the method in model class such a:
public static function getByPk($pk)
{
$result = self::getDb()->cache(function ($db) use ($pk) {
return self::find()->where(['id' => $pk])->one();
});
return $result;
}
If this query result was already cached in $result will set value from cache, otherwise will execute query, correctly?
Also I have question about dependency, what dependency I can use for invalidation this cache value?
As an opinion! You know it depends on data that you add to cache storage. If it's some static data such as status, position etc. you can set the second param duration. You can read about at official doc.
If you make a few same queries on the page you can set 1 or 2 seconds and it helps you a little.

How do I check if a Cache element has expired in Laravel 5?

I want to store an array in Cache. I'm using "MemCached" as Cache driver and it works like a charm in queries, but I want to use it for my search suggestions. I've been looking at Laravel Documentation (http://laravel.com/docs/5.1/cache) but I haven't been able to find what I were looking for.
For example, I have this function in which if I find the element on Cache I get it. If not, I get results from DB and then store them on Cache for 10 minutes:
public function get_suggestions() {
if(Cache::get('search_suggestions')) {
return $search_suggestions;
} else {
$search_suggestions = Suggestions::get();
Cache::put('search_suggestions', '$search_suggestions', 10);
return $search_suggestions;
}
}
Some questions:
If the element in Cache expires, what will the Cache::get function returns?
There is a function to check if the element exists in the database but is there anyone to check if the Cache item has expires?
Is my approach OK to manage the Cache?
You could use Cache::has to check for existance.
But in your case I suggest to use Cache::remember
public function get_suggestions() {
return Cache::remember('search_suggestions', 10, function() {
return Suggestions::get();
});
}

Categories