Laravel: how to cache route for 5 minutes? - php

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;
});

Related

How to clear cache with specific key in laravel 9?

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');

How to get data, passed by a view composer to certain views, inside the controller?

My View Composer passes some data to certain views (and it works, of course):
use Illuminate\View\View;
use App\Util\Helper
class PublicSettingsComposer
{
public function compose(View $view)
{
$view->with('settings', Helper::readSettingsFromFile()); // json
}
}
The appropriate provider is added into the configuration and it provides this composer correctly for all specific views:
view()->compose('public.layouts.*', 'App\Http\ViewComposers\PublicSettingsComposer');
However, inside (only) one of my views I need specific information from database, but therefore I have to use some data, that had been passed by my View Composer:
class BranchController extends Controller
{
public function branches()
{
$settings = retrieve_settings_passed_by_PublicSettingsComposer; // This is what I need
$headquartersId = $settings->headquartersid;
return view('public.layouts.branches', [
'headquarters' => Branch::find($headquartersId) // Branch is a Model
]);
}
}
FYI: Laravel version I'm using is: 5.5
P.S. #moderators: Please, be careful with considering my question as a duplicate. I know there are many questions about view composers and passing data to the views and grabbing data from within controllers. However, I really could not find any question with this context (titles are often misleading).
I see two rather simple solutions for this. The first one is to cache the parsed file within each request. The other is to use an actual cache for this job.
The first option is very straight forward to implement. In your Helper class you'll have to introduce a static property to hold the parsed contents of the read file. Then, just like you do within the singleton pattern, you either return the cached data or you first parse the file, cache the data and return it afterwards. This scenario solves your actual problem of parsing the settings twice per requests if used in two places of your app.
class Helper
{
protected static $cachedSettings;
public function readSettingsFromFile()
{
if (!self::$cachedSettings) {
self::$cachedSettings = // Do the parsing here. This should be your current implementation of Helper::readSettingsFromFile(). You can also put this in its own function.
}
return self::$cachedSettings;
}
}
The other option is to use an actual cache (an external one). You can either cache the parsed file for a specific amount of times (like 1, 3, 5 or 10 minutes or even longer). Or you cache it forever and invalidate the cache when you update the settings (if this happens within your app and you know it was updated).
This solution does only make sense if your settings do not change too frequently though. It also depends a bit on the amount of requests you expect towards your app. If your settings change not too frequently (less than every x minutes) and your app is used frequently (multiple requests every x minutes), then it could be a viable solution.
class Helper
{
public function readSettingsFromFile()
{
return Cache::remember(function () {
$settings = // Put your current calculation here
return $settings;
}, 3 * 60); // 3 * 60 = 180 seconds
}
}

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.

Cannot update Laravel Session variable?

I have an ongoing problem in Laravel. I am building "load more" system for comments with Laravel and Ajax, and using Session variable for counting and skipping already loaded rows. But for some reason my session variable wont persist, for unknown reason (trying whole the day to resolve this).. Ok here is some code:
public function load_more() {
$comments = Comments::whereid(Input::get('article_id'))->orderBy('id','DESC')->skip(Session::get('loaded')->take(12)->get();
Session::set('loaded', Session::get('loaded') + 12 ) ;
return \Response::json($comments);
}
So as you can see i am trying to increment variable each call. But the variable stays the same all the time.. When I make another variable for example Session::set('another', Session::get('loaded') + 12 ) ;
it actually get summed and i have sum in this variable.. but why it cannot update itself?
Fixed the problem in frontend with Jquery global counter which I am sending as an GET argument on every request, instead of using Session variables. Still don't know what's the problem with session, maybe some bug in my Laravel installation.
If your have laravel 5.2 the probleme is you put your route into group web
Route::group(['middleware' => ['web']], function () {
PUT YOUR ROUTE HERE
}

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