I have Repository class with a method as follows:
public function GetOne($id){
$method = __METHOD__;
$post = null;
$post = $this->CacheManager($method, function($id) {
return DB::select("select * from posts where id = ?", [$id]);
});
return $post;
}
I want to cache the result, but in the closure/callback function the $id parameter is not working. The CacheManager is a trait where I'm using it in my repository.
public function CacheManager($method, $fn) {
$obj = null;
if(!$this->HasCache($method)){
$obj = $fn();
}else {
$obj = $this->GetCache($method);
}
return $obj;
}
I have some other methods without parameters and they're working as intended.
解决方案
Use use. :D
With the use clause, you can import variables from the parent scope into the scope of the function.
public function GetOne($id){
$method = __METHOD__;
$post = null;
$post = $this->CacheManager($method, function() use ($id) {
return DB::select("select * from posts where id = ?", [$id]);
});
return $post;
}
Just a side note. Since it looks you are building a caching mechanism, you will need to include the ID in the cache as well. Currently you only check by $method, but for each id you will probably have a different cache entry which may or may not exist. So I think in your function you need to do something like the line below to make the cache key more unique. I would also call the parameter $method something like $cacheKey instead, since to the cache it shouldn't be linked to a method name per se.
$method = __METHOD__ . ";$id";
Update for PHP 7.4: arrow functions
The RFC for arrow functions (AKA 'short closures') has passed voting.
With these you don't specify the parameters you want to close in, because they can only have a single expression anyway, so any expression/value they use can (and will) be taken from the parent function scope.
Since in this case the anonymous function just has a single statement, it can be rewritten into an arrow function. The call to the cache manager will then look like this:
public function GetOne($id){
$method = __METHOD__;
$post = null;
$post = $this->CacheManager($method, fn() => DB::select("select * from posts where id = ?", [$id]));
return $post;
}