Let's say we have a method of an Class that is being called in iteration n times, and the method in itself has a statement that pulls data from a cache system - Redis.
Now if this method is called n times the cache is also hit n times leading to a continuous fetch and unserializing of the same data n times which in the case of an interpreter like PHP consumes a good amount of time & CPU.
Passing the cached data to this method could also be a no as we might instantiate n number of instances of this class.
So is there a way where we can avoid hitting the cache multiple times in the context of a Class/Object instead if we can use the static properties of the Object to hold the value?
CodePudding user response:
If you are in the opinion that you should not use a service-class (which the other answer explains),
then consider using PHP's $GLOBALS
variable to backup the loaded-Cache (instead of adding yet another custom static
variable).
Examples
Maybe backup once for all:
In Laravel's AppServiceProvider.php
file, do something like:
<?php
namespace App\Providers;
// ...
use Illuminate\Support\Facades\Cache;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
$keyList = [
'my-unique-key',
'my-other-key',
];
foreach($keyList as $key) {
$GLOBALS['cache-' . $key] = Cache::get($key);
}
}
}
Finally, use $GLOBALS['cache-my-unique-key']
anywhere required.
Or, backup per class:
<?php
use Illuminate\Support\Facades\Cache;
class YourClass {
private $myData;
public function __construct()
{
$key = 'my-unique-key';
$value = & $GLOBALS['cache-' . $key];
if ( ! isset($value)) {
$value = Cache::get($key);
}
$this->myData = $value;
}
// Finally, use `$this->myData` anywhere in this same class.
}
Note that as you may already know, in both cases we use
'cache-'
prefix to not overwrite anything by mistake.
CodePudding user response:
You can use static properties to store the cached data and use access it same.
class CacheClass
{
private static $cachedData;
public function retrieveData()
{
if (!isset(self::$cachedData)) {
// re-assign the value
self::$cachedData = fetchDataFromCache();
}
return self::$cachedData;
}
}
CodePudding user response:
First, write a service class that:
- Provides getter, which:
- Loads required value from cache (based on unique-key),
- But also backups the loaded-value,
- Finally, returns backupped-value instead of re-loading from cache.
- Provides setter which updates both backup and cache.
Then simply use Laravel's feature to inject and/or get instance of said service-class.
(I write and/or say "backupped" instead of "backed up", because dictionary is wrong, as prove:
- "backupped cake" remains it's meaning,
- while "backed up cake" is confusing.)
Example
<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
class MyCacheService
{
protected $backupMap = [];
/**
* Requests an instance of this-class from Laravel.
*
* @return MyCacheService|null
*/
public static function instance()
{
return \Illuminate\Support\Facades\App::make(MyCacheService::class);
}
public function get($key)
{
$backup = & $this->backupMap[$key];
if ( ! isset($backup)) {
$backup = $this->rawGet($key);
}
return $buckup;
}
public function set($key, $value)
{
$this->rawSet($key, $value);
$this->backupMap[$key] = $value;
}
/** Loads from cache */
private function rawGet($key)
{
// ... your normal loading from cache logic goes here,
// but as sub-example:
return Cache::get($key);
}
/** Saves into cache */
private function rawSet($key, $value)
{
// ... your normal saving into cache logic goes here,
// but as sub-example:
Cache::set($key, $value);
}
}
Usage:
use App\Services\MyCacheService;
use Illuminate\Support\Facades\App;
// ...
// Get instance once, like:
$cacheService = MyCacheService::instance();
// Or like:
/** @var MyCacheService|null $cacheService */
$cacheService = App::make(MyCacheService::class);
// Finally, reuse as many times as required, like:
$myValue = $cacheService->get('my-unique-key');
$myOtherValue = $cacheService->get('my-other-key');
Note that Laravel stores the class's instance for us, else one could use
private static
property named$instance
, andreturn
that frominstance()
method.WARNING: as you may already know, maybe replace rawGet and rawSet's logic.
Also, place
MyCacheService.php
file (which's source is above) inapp/Services
folder.