Answer the question
In order to leave comments, you need to log in
Data caching is "more correct" describe in model or controller?
In any modern project, it is worth immediately providing for data caching, be it a file, memcached or redis.
I would like to know how you cache, i.e. in what place, what is responsible for caching?
I will give examples, for example, caching in the controller is often found in simple examples on many sites.
Every time when it is necessary to get some information from the model, it is checked whether the data that the method returns is in the cache, if not, then we “pull” the model and save the cache. Below is an example code.
class Users extends ApplicationModel {
function __construct()
{
}
function getName($id) {
$result = $this->db->execute("SELECT user_name FROM user WHERE id = {$id}");
return $result;
}
}
class UserSettings extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showMainSettings()
{
$key = "UserName_{$id}";
$username = $this->cache->load($key);
if ($username === false) {
$username = $user->getName($id);
$this->cache->save($username, $key);
}
/*
another code and render view
*/
}
}
class UserHome extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showHome()
{
$key = "UserName_{$id}";
$username = $this->cache->load($key);
if ($username === false) {
$username = $user->getName($id);
$this->cache->save($username, $key);
}
/*
another code and render view
*/
}
}
class Users extends ApplicationModel {
function __construct()
{
$this->cache = new Cache();
}
function getName($id) {
$key = "Users_getName_{$id}";
$result = $this->cache->load($key);
if ($result === false) {
$result = $this->db->execute("SELECT user_name FROM user WHERE id = {$id}");
$this->cache->save($result, $key);
}
return $result;
}
}
class UserSettings extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showMainSettings()
{
$username = $user->getName($id);
/*
another code and render view
*/
}
}
class UserHome extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showHome()
{
$username = $user->getName($id);
/*
another code and render view
*/
}
}
class Users extends ApplicationModel {
function __construct()
{
$this->cache = new Cache();
}
function getName($id) {
$result = $this->db->execute("SELECT user_name FROM user WHERE id = {$id}");
return $result;
}
function __call($name,$arguments)
{
$parts = explode('__', $name);
if ('cache'==$parts[0] && method_exists($this,$parts[1]) ) {
$model = get_class($this);
$method = $parts[1];
$arguments_str = md5(serialize($arguments));
$key = "{$model}_{$method}_{$arguments_str}";
$result = $this->cache->load($key);
if($result === false)
{
$result = call_user_func_array(array($this,"{$method}"), $arguments);
$this->cache->save($result,$key);
return $result;
}
else
return $result;
}
else
{
echo "Sorry method not found {$model}::{$method}";
exit(1);
}
}
}
class UserSettings extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showMainSettings()
{
$username = $user->getName($id); // get data from DB
$username_cached = $user->cache__getName($id); // get cached data if exist
/*
another code and render view
*/
}
}
class UserHome extends ApplicationController {
function __construct()
{
$user = new Users();
}
function showHome()
{
$username = $user->getName($id); // get data from DB
$username_cached = $user->cache__getName($id); // get cached data if exist
/*
another code and render view
*/
}
}
Answer the question
In order to leave comments, you need to log in
I usually cache in the model, the controller should only have the model->getData function, and where this data comes from is no longer the concern of the controller, and here's why: only the model knows what data can / cannot be cached, how long the cache remains valid and when and how data needs to be updated. It is bad when information about the nature of the data is blurred both on the model and on the controller. IMHO.
In the repository. A simple POPO model, knows nothing about the database at all, its only area of responsibility is to model the subject area. The responsibility of the repository is to store the entities of the model where and as soon as it knows. Alternatively, yes, a proxy that implements the same interface as the "clean" repository. Another option is to cache query results even lower, somewhere at the DBAL/DAL level. But in practice, I only implemented directly in the repository, something like
class UserRepository {
public function getById($id) {
if ($this->cache->hasKey('user' . $id)) {
$user = $this->cache->getByKey('user' . $id);
} else {
$user = $this->db->getUserById($id);
$this->cache->set('user' . $id, $user);
}
}
In the model
The model selects data from the database, saves it to the cache
The model saves the data to the database - updates / clears the cache
The model can be called from many controllers. It is irrational to write cache saving/updating in each of the controllers.
Magic methods are evil. The person who has to debug your code will then bury you alive in a graveyard.
Whether it is worth caching simple selections (by id) is a moot point, for unloaded projects it is not worth it. It is worth caching complex selections, and in some cases, chunks of HTML.
I never liked the cumbersome constructions of checking for the presence of cached data. Therefore, I am happy to use the approach implemented in Laravel: laravel.com/docs/cache/usage
Achieved getting rid of the cumbersome construction shown in your examples, while maintaining brevity and clarity of the actions performed.
Your question is rather ideological, rooted in the issue of "thick/thin controllers/models". Here is a post on the topic from Makarov: rmcreative.ru/blog/post/tonkie-i-tolstye-modeli
IMHO it depends heavily on logic, I cache:
- data (Output in the Model), as a rule, the main content, for example, a large request that breaks pages
- I cache the HTML block (In the controller), usually tops, or thematic banners for thematic sections or other offers , not the main content, but often requested ) As a rule, such content is calculated by krone.
- a fully HTML page (usually index.htm or frequently-requested pages). I have this caching configured using WEB server tools.
If desired, block caching can also be configured using WEB server tools using ssi. I wrote about this on Habré habrahabr.ru/post/109050/
But in this case, the framework becomes much more complicated
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question